@matter/node 0.16.0-alpha.0-20251108-514b3f69e → 0.16.0-alpha.0-20251110-c4c70a41b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/behavior/cluster/ClientBehavior.d.ts +0 -7
- package/dist/cjs/behavior/cluster/ClientBehavior.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/ClientBehavior.js +2 -8
- package/dist/cjs/behavior/cluster/ClientBehavior.js.map +2 -2
- package/dist/cjs/behavior/cluster/ClusterBehavior.d.ts +1 -1
- package/dist/cjs/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/ClusterBehavior.js +9 -4
- package/dist/cjs/behavior/cluster/ClusterBehavior.js.map +1 -1
- package/dist/cjs/behavior/cluster/ClusterBehaviorCache.d.ts +7 -1
- package/dist/cjs/behavior/cluster/ClusterBehaviorCache.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/ClusterBehaviorCache.js +7 -5
- package/dist/cjs/behavior/cluster/ClusterBehaviorCache.js.map +1 -1
- package/dist/cjs/behavior/cluster/ClusterBehaviorType.d.ts +57 -0
- package/dist/cjs/behavior/cluster/ClusterBehaviorType.d.ts.map +1 -0
- package/dist/cjs/behavior/cluster/{ClusterBehaviorUtil.js → ClusterBehaviorType.js} +70 -39
- package/dist/cjs/behavior/cluster/ClusterBehaviorType.js.map +6 -0
- package/dist/cjs/behavior/cluster/ClusterEvents.d.ts +1 -1
- package/dist/cjs/behavior/cluster/ClusterEvents.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/ClusterState.d.ts +1 -1
- package/dist/cjs/behavior/cluster/ClusterState.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/ValidatedElements.js +2 -2
- package/dist/cjs/behavior/cluster/ValidatedElements.js.map +1 -1
- package/dist/cjs/behavior/cluster/{ClusterBehaviorUtil.d.ts → cluster-behavior-utils.d.ts} +10 -8
- package/dist/cjs/behavior/cluster/cluster-behavior-utils.d.ts.map +1 -0
- package/dist/cjs/behavior/cluster/cluster-behavior-utils.js +41 -0
- package/dist/cjs/behavior/cluster/cluster-behavior-utils.js.map +6 -0
- package/dist/cjs/behavior/cluster/index.d.ts +2 -1
- package/dist/cjs/behavior/cluster/index.d.ts.map +1 -1
- package/dist/cjs/behavior/cluster/index.js +2 -1
- package/dist/cjs/behavior/cluster/index.js.map +1 -1
- package/dist/cjs/behavior/context/server/LocalActorContext.d.ts +4 -0
- package/dist/cjs/behavior/context/server/LocalActorContext.d.ts.map +1 -1
- package/dist/cjs/behavior/context/server/LocalActorContext.js +2 -3
- package/dist/cjs/behavior/context/server/LocalActorContext.js.map +1 -1
- package/dist/cjs/behavior/context/server/RemoteActorContext.d.ts +4 -0
- package/dist/cjs/behavior/context/server/RemoteActorContext.d.ts.map +1 -1
- package/dist/cjs/behavior/context/server/RemoteActorContext.js +1 -0
- package/dist/cjs/behavior/context/server/RemoteActorContext.js.map +1 -1
- package/dist/cjs/behavior/internal/BehaviorBacking.js +2 -2
- package/dist/cjs/behavior/internal/BehaviorBacking.js.map +1 -1
- package/dist/cjs/behavior/system/commissioning/CommissioningServer.d.ts.map +1 -1
- package/dist/cjs/behavior/system/commissioning/CommissioningServer.js +3 -3
- package/dist/cjs/behavior/system/commissioning/CommissioningServer.js.map +1 -1
- package/dist/cjs/behaviors/operational-credentials/OperationalCredentialsServer.js +1 -1
- package/dist/cjs/behaviors/operational-credentials/OperationalCredentialsServer.js.map +1 -1
- package/dist/cjs/behaviors/operational-credentials/VendorIdVerification.d.ts +6 -1
- package/dist/cjs/behaviors/operational-credentials/VendorIdVerification.d.ts.map +1 -1
- package/dist/cjs/behaviors/operational-credentials/VendorIdVerification.js +2 -2
- package/dist/cjs/behaviors/operational-credentials/VendorIdVerification.js.map +1 -1
- package/dist/cjs/endpoint/Endpoint.d.ts +8 -0
- package/dist/cjs/endpoint/Endpoint.d.ts.map +1 -1
- package/dist/cjs/endpoint/Endpoint.js +11 -3
- package/dist/cjs/endpoint/Endpoint.js.map +1 -1
- package/dist/cjs/endpoint/properties/Behaviors.d.ts +1 -1
- package/dist/cjs/endpoint/properties/Behaviors.d.ts.map +1 -1
- package/dist/cjs/endpoint/properties/Behaviors.js +6 -3
- package/dist/cjs/endpoint/properties/Behaviors.js.map +1 -1
- package/dist/cjs/endpoint/properties/EndpointInitializer.d.ts +0 -4
- package/dist/cjs/endpoint/properties/EndpointInitializer.d.ts.map +1 -1
- package/dist/cjs/endpoint/properties/EndpointInitializer.js +0 -6
- package/dist/cjs/endpoint/properties/EndpointInitializer.js.map +1 -1
- package/dist/cjs/node/Node.d.ts.map +1 -1
- package/dist/cjs/node/Node.js +2 -1
- package/dist/cjs/node/Node.js.map +1 -1
- package/dist/cjs/node/client/ClientCommandMethod.d.ts +11 -0
- package/dist/cjs/node/client/ClientCommandMethod.d.ts.map +1 -0
- package/dist/cjs/node/client/ClientCommandMethod.js +69 -0
- package/dist/cjs/node/client/ClientCommandMethod.js.map +6 -0
- package/dist/cjs/node/client/ClientEndpointInitializer.d.ts +0 -2
- package/dist/cjs/node/client/ClientEndpointInitializer.d.ts.map +1 -1
- package/dist/cjs/node/client/ClientEndpointInitializer.js +3 -34
- package/dist/cjs/node/client/ClientEndpointInitializer.js.map +1 -1
- package/dist/cjs/node/client/ClientStructure.d.ts.map +1 -1
- package/dist/cjs/node/client/ClientStructure.js +164 -32
- package/dist/cjs/node/client/ClientStructure.js.map +2 -2
- package/dist/cjs/node/client/ClientStructureEvents.d.ts +22 -0
- package/dist/cjs/node/client/ClientStructureEvents.d.ts.map +1 -0
- package/dist/cjs/node/client/ClientStructureEvents.js +92 -0
- package/dist/cjs/node/client/ClientStructureEvents.js.map +6 -0
- package/dist/cjs/node/client/PeerBehavior.d.ts +14 -1
- package/dist/cjs/node/client/PeerBehavior.d.ts.map +1 -1
- package/dist/cjs/node/client/PeerBehavior.js +111 -71
- package/dist/cjs/node/client/PeerBehavior.js.map +1 -1
- package/dist/cjs/node/client/Peers.d.ts +17 -0
- package/dist/cjs/node/client/Peers.d.ts.map +1 -1
- package/dist/cjs/node/client/Peers.js +96 -42
- package/dist/cjs/node/client/Peers.js.map +1 -1
- package/dist/cjs/node/server/ServerSubscription.d.ts +1 -1
- package/dist/cjs/node/server/ServerSubscription.d.ts.map +1 -1
- package/dist/cjs/node/server/ServerSubscription.js +2 -3
- package/dist/cjs/node/server/ServerSubscription.js.map +1 -1
- package/dist/esm/behavior/cluster/ClientBehavior.d.ts +0 -7
- package/dist/esm/behavior/cluster/ClientBehavior.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/ClientBehavior.js +2 -8
- package/dist/esm/behavior/cluster/ClientBehavior.js.map +2 -2
- package/dist/esm/behavior/cluster/ClusterBehavior.d.ts +1 -1
- package/dist/esm/behavior/cluster/ClusterBehavior.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/ClusterBehavior.js +9 -4
- package/dist/esm/behavior/cluster/ClusterBehavior.js.map +1 -1
- package/dist/esm/behavior/cluster/ClusterBehaviorCache.d.ts +7 -1
- package/dist/esm/behavior/cluster/ClusterBehaviorCache.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/ClusterBehaviorCache.js +7 -5
- package/dist/esm/behavior/cluster/ClusterBehaviorCache.js.map +1 -1
- package/dist/esm/behavior/cluster/ClusterBehaviorType.d.ts +57 -0
- package/dist/esm/behavior/cluster/ClusterBehaviorType.d.ts.map +1 -0
- package/dist/esm/behavior/cluster/{ClusterBehaviorUtil.js → ClusterBehaviorType.js} +66 -35
- package/dist/esm/behavior/cluster/ClusterBehaviorType.js.map +6 -0
- package/dist/esm/behavior/cluster/ClusterEvents.d.ts +1 -1
- package/dist/esm/behavior/cluster/ClusterEvents.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/ClusterState.d.ts +1 -1
- package/dist/esm/behavior/cluster/ClusterState.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/ValidatedElements.js +1 -1
- package/dist/esm/behavior/cluster/{ClusterBehaviorUtil.d.ts → cluster-behavior-utils.d.ts} +10 -8
- package/dist/esm/behavior/cluster/cluster-behavior-utils.d.ts.map +1 -0
- package/dist/esm/behavior/cluster/cluster-behavior-utils.js +21 -0
- package/dist/esm/behavior/cluster/cluster-behavior-utils.js.map +6 -0
- package/dist/esm/behavior/cluster/index.d.ts +2 -1
- package/dist/esm/behavior/cluster/index.d.ts.map +1 -1
- package/dist/esm/behavior/cluster/index.js +2 -1
- package/dist/esm/behavior/cluster/index.js.map +1 -1
- package/dist/esm/behavior/context/server/LocalActorContext.d.ts +4 -0
- package/dist/esm/behavior/context/server/LocalActorContext.d.ts.map +1 -1
- package/dist/esm/behavior/context/server/LocalActorContext.js +2 -3
- package/dist/esm/behavior/context/server/LocalActorContext.js.map +1 -1
- package/dist/esm/behavior/context/server/RemoteActorContext.d.ts +4 -0
- package/dist/esm/behavior/context/server/RemoteActorContext.d.ts.map +1 -1
- package/dist/esm/behavior/context/server/RemoteActorContext.js +1 -0
- package/dist/esm/behavior/context/server/RemoteActorContext.js.map +1 -1
- package/dist/esm/behavior/internal/BehaviorBacking.js +2 -2
- package/dist/esm/behavior/internal/BehaviorBacking.js.map +1 -1
- package/dist/esm/behavior/system/commissioning/CommissioningServer.d.ts.map +1 -1
- package/dist/esm/behavior/system/commissioning/CommissioningServer.js +4 -3
- package/dist/esm/behavior/system/commissioning/CommissioningServer.js.map +1 -1
- package/dist/esm/behaviors/operational-credentials/OperationalCredentialsServer.js +1 -1
- package/dist/esm/behaviors/operational-credentials/OperationalCredentialsServer.js.map +1 -1
- package/dist/esm/behaviors/operational-credentials/VendorIdVerification.d.ts +6 -1
- package/dist/esm/behaviors/operational-credentials/VendorIdVerification.d.ts.map +1 -1
- package/dist/esm/behaviors/operational-credentials/VendorIdVerification.js +1 -1
- package/dist/esm/behaviors/operational-credentials/VendorIdVerification.js.map +1 -1
- package/dist/esm/endpoint/Endpoint.d.ts +8 -0
- package/dist/esm/endpoint/Endpoint.d.ts.map +1 -1
- package/dist/esm/endpoint/Endpoint.js +11 -3
- package/dist/esm/endpoint/Endpoint.js.map +1 -1
- package/dist/esm/endpoint/properties/Behaviors.d.ts +1 -1
- package/dist/esm/endpoint/properties/Behaviors.d.ts.map +1 -1
- package/dist/esm/endpoint/properties/Behaviors.js +6 -3
- package/dist/esm/endpoint/properties/Behaviors.js.map +1 -1
- package/dist/esm/endpoint/properties/EndpointInitializer.d.ts +0 -4
- package/dist/esm/endpoint/properties/EndpointInitializer.d.ts.map +1 -1
- package/dist/esm/endpoint/properties/EndpointInitializer.js +0 -6
- package/dist/esm/endpoint/properties/EndpointInitializer.js.map +1 -1
- package/dist/esm/node/Node.d.ts.map +1 -1
- package/dist/esm/node/Node.js +2 -1
- package/dist/esm/node/Node.js.map +1 -1
- package/dist/esm/node/client/ClientCommandMethod.d.ts +11 -0
- package/dist/esm/node/client/ClientCommandMethod.d.ts.map +1 -0
- package/dist/esm/node/client/ClientCommandMethod.js +49 -0
- package/dist/esm/node/client/ClientCommandMethod.js.map +6 -0
- package/dist/esm/node/client/ClientEndpointInitializer.d.ts +0 -2
- package/dist/esm/node/client/ClientEndpointInitializer.d.ts.map +1 -1
- package/dist/esm/node/client/ClientEndpointInitializer.js +3 -34
- package/dist/esm/node/client/ClientEndpointInitializer.js.map +1 -1
- package/dist/esm/node/client/ClientStructure.d.ts.map +1 -1
- package/dist/esm/node/client/ClientStructure.js +164 -32
- package/dist/esm/node/client/ClientStructure.js.map +2 -2
- package/dist/esm/node/client/ClientStructureEvents.d.ts +22 -0
- package/dist/esm/node/client/ClientStructureEvents.d.ts.map +1 -0
- package/dist/esm/node/client/ClientStructureEvents.js +72 -0
- package/dist/esm/node/client/ClientStructureEvents.js.map +6 -0
- package/dist/esm/node/client/PeerBehavior.d.ts +14 -1
- package/dist/esm/node/client/PeerBehavior.d.ts.map +1 -1
- package/dist/esm/node/client/PeerBehavior.js +119 -74
- package/dist/esm/node/client/PeerBehavior.js.map +1 -1
- package/dist/esm/node/client/Peers.d.ts +17 -0
- package/dist/esm/node/client/Peers.d.ts.map +1 -1
- package/dist/esm/node/client/Peers.js +106 -43
- package/dist/esm/node/client/Peers.js.map +1 -1
- package/dist/esm/node/server/ServerSubscription.d.ts +1 -1
- package/dist/esm/node/server/ServerSubscription.d.ts.map +1 -1
- package/dist/esm/node/server/ServerSubscription.js +2 -3
- package/dist/esm/node/server/ServerSubscription.js.map +1 -1
- package/package.json +7 -7
- package/src/behavior/cluster/ClientBehavior.ts +2 -16
- package/src/behavior/cluster/ClusterBehavior.ts +9 -4
- package/src/behavior/cluster/ClusterBehaviorCache.ts +16 -9
- package/src/behavior/cluster/{ClusterBehaviorUtil.ts → ClusterBehaviorType.ts} +160 -64
- package/src/behavior/cluster/ClusterEvents.ts +1 -1
- package/src/behavior/cluster/ClusterState.ts +1 -1
- package/src/behavior/cluster/ValidatedElements.ts +1 -1
- package/src/behavior/cluster/cluster-behavior-utils.ts +48 -0
- package/src/behavior/cluster/index.ts +2 -1
- package/src/behavior/context/server/LocalActorContext.ts +8 -4
- package/src/behavior/context/server/RemoteActorContext.ts +6 -0
- package/src/behavior/internal/BehaviorBacking.ts +2 -2
- package/src/behavior/system/commissioning/CommissioningServer.ts +4 -3
- package/src/behaviors/operational-credentials/OperationalCredentialsServer.ts +1 -1
- package/src/behaviors/operational-credentials/VendorIdVerification.ts +3 -2
- package/src/endpoint/Endpoint.ts +23 -3
- package/src/endpoint/properties/Behaviors.ts +12 -6
- package/src/endpoint/properties/EndpointInitializer.ts +0 -7
- package/src/node/Node.ts +2 -1
- package/src/node/client/ClientCommandMethod.ts +63 -0
- package/src/node/client/ClientEndpointInitializer.ts +6 -39
- package/src/node/client/ClientStructure.ts +133 -27
- package/src/node/client/ClientStructureEvents.ts +97 -0
- package/src/node/client/PeerBehavior.ts +185 -104
- package/src/node/client/Peers.ts +131 -51
- package/src/node/server/ServerSubscription.ts +3 -3
- package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.d.ts.map +0 -1
- package/dist/cjs/behavior/cluster/ClusterBehaviorUtil.js.map +0 -6
- package/dist/esm/behavior/cluster/ClusterBehaviorUtil.d.ts.map +0 -1
- package/dist/esm/behavior/cluster/ClusterBehaviorUtil.js.map +0 -6
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Behavior } from "#behavior/Behavior.js";
|
|
8
|
+
import { ClusterBehavior } from "#behavior/cluster/ClusterBehavior.js";
|
|
9
|
+
import { DescriptorClient } from "#behaviors/descriptor";
|
|
10
|
+
import { Endpoint } from "#endpoint/Endpoint.js";
|
|
11
|
+
import { EndpointType } from "#endpoint/type/EndpointType.js";
|
|
12
|
+
import { Environment, Environmental, Observable } from "#general";
|
|
13
|
+
import { DeviceTypeId } from "#types";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* An environmental service that manages events endpoint and behavior types.
|
|
17
|
+
*/
|
|
18
|
+
export class ClientStructureEvents {
|
|
19
|
+
#endpointEvents?: Map<DeviceTypeId, Observable<[Endpoint]>>;
|
|
20
|
+
#clusterEvents?: Map<
|
|
21
|
+
string,
|
|
22
|
+
Array<{
|
|
23
|
+
requestedType: Behavior.Type;
|
|
24
|
+
event: Observable<[Endpoint, Behavior.Type]>;
|
|
25
|
+
}>
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
static [Environmental.create](env: Environment) {
|
|
29
|
+
const instance = new ClientStructureEvents();
|
|
30
|
+
env.set(ClientStructureEvents, instance);
|
|
31
|
+
return instance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
endpointInstalled<T extends EndpointType>(type: T): Observable<[endpoint: Endpoint<T>]> {
|
|
35
|
+
if (this.#endpointEvents === undefined) {
|
|
36
|
+
this.#endpointEvents = new Map();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let event = this.#endpointEvents.get(type.deviceType);
|
|
40
|
+
if (event === undefined) {
|
|
41
|
+
this.#endpointEvents.set(type.deviceType, (event = Observable()));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return event as Observable<[endpoint: Endpoint<T>]>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
clusterInstalled<T extends ClusterBehavior.Type>(type: T): Observable<[endpoint: Endpoint, type: T]> {
|
|
48
|
+
if (this.#clusterEvents === undefined) {
|
|
49
|
+
this.#clusterEvents = new Map();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let events = this.#clusterEvents.get(type.id);
|
|
53
|
+
if (events === undefined) {
|
|
54
|
+
this.#clusterEvents.set(type.id, (events = []));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const { requestedType, event } of events) {
|
|
58
|
+
if (requestedType.supports(type)) {
|
|
59
|
+
return event;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const event = Observable();
|
|
64
|
+
events.push({ requestedType: type, event });
|
|
65
|
+
|
|
66
|
+
return event;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
emitEndpoint(endpoint: Endpoint) {
|
|
70
|
+
if (this.#endpointEvents && endpoint.behaviors.supported.descriptor) {
|
|
71
|
+
const deviceTypes = endpoint.stateOf(DescriptorClient).deviceTypeList;
|
|
72
|
+
for (const dt of deviceTypes) {
|
|
73
|
+
this.#endpointEvents.get(dt.deviceType)?.emit(endpoint);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (const type of Object.values(endpoint.behaviors.supported)) {
|
|
78
|
+
this.emitCluster(endpoint, type);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const part of endpoint.parts) {
|
|
82
|
+
this.emitEndpoint(part);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
emitCluster(endpoint: Endpoint, type: Behavior.Type) {
|
|
87
|
+
const events = this.#clusterEvents?.get(type.id);
|
|
88
|
+
if (!events) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
for (const { requestedType, event } of events) {
|
|
92
|
+
if (type.supports(requestedType)) {
|
|
93
|
+
event.emit(endpoint, type);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -6,11 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
import { Behavior } from "#behavior/Behavior.js";
|
|
8
8
|
import { ClusterBehavior } from "#behavior/cluster/ClusterBehavior.js";
|
|
9
|
+
import { ClusterBehaviorType } from "#behavior/cluster/ClusterBehaviorType.js";
|
|
9
10
|
import { camelize, capitalize, InternalError } from "#general";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import {
|
|
12
|
+
AttributeModel,
|
|
13
|
+
ClusterModel,
|
|
14
|
+
CommandModel,
|
|
15
|
+
Conformance,
|
|
16
|
+
EncodedBitmap,
|
|
17
|
+
EventModel,
|
|
18
|
+
FeatureBitmap,
|
|
19
|
+
Matter,
|
|
20
|
+
type ValueModel,
|
|
21
|
+
} from "#model";
|
|
14
22
|
import {
|
|
15
23
|
Attribute,
|
|
16
24
|
AttributeId,
|
|
@@ -20,24 +28,77 @@ import {
|
|
|
20
28
|
Command,
|
|
21
29
|
CommandId,
|
|
22
30
|
MutableCluster,
|
|
23
|
-
Status,
|
|
24
|
-
StatusResponseError,
|
|
25
31
|
TlvAny,
|
|
26
32
|
TlvNoResponse,
|
|
27
33
|
} from "#types";
|
|
34
|
+
import { ClientCommandMethod } from "./ClientCommandMethod.js";
|
|
28
35
|
|
|
29
36
|
const BIT_BLOCK_SIZE = Math.log2(Number.MAX_SAFE_INTEGER);
|
|
30
37
|
|
|
31
|
-
const
|
|
38
|
+
const discoveredCache = {} as Record<string, ClusterBehavior.Type>;
|
|
39
|
+
const knownCache = new WeakMap<ClusterBehavior.Type, ClusterBehavior.Type>();
|
|
40
|
+
|
|
41
|
+
const isPeer = Symbol("is-peer");
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
44
|
* Obtain a {@link ClusterBehavior.Type} for a remote cluster.
|
|
35
45
|
*/
|
|
36
46
|
export function PeerBehavior(shape: PeerBehavior.ClusterShape): ClusterBehavior.Type {
|
|
37
|
-
|
|
47
|
+
let type: ClusterBehavior.Type;
|
|
48
|
+
|
|
49
|
+
switch (shape.kind) {
|
|
50
|
+
case "known":
|
|
51
|
+
if (Object.hasOwn(shape.behavior, isPeer)) {
|
|
52
|
+
return shape.behavior;
|
|
53
|
+
}
|
|
54
|
+
type = instrumentKnownShape(shape);
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case "discovered":
|
|
58
|
+
type = instrumentDiscoveredShape(shape);
|
|
59
|
+
break;
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
throw new InternalError(`Unknown cluster shape kind ${(shape as any).kind}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
(type as any)[isPeer] = true;
|
|
66
|
+
|
|
67
|
+
return type;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export namespace PeerBehavior {
|
|
71
|
+
export type ClusterShape = DiscoveredClusterShape | KnownClusterShape;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A cluster shape that we assemble using a combination of Matter standards and metadata discovered by reading from
|
|
75
|
+
* a peer.
|
|
76
|
+
*/
|
|
77
|
+
export interface DiscoveredClusterShape {
|
|
78
|
+
kind: "discovered";
|
|
79
|
+
id: ClusterId;
|
|
80
|
+
revision: number;
|
|
81
|
+
features: FeatureBitmap | number;
|
|
82
|
+
attributes: AttributeId[];
|
|
83
|
+
commands: CommandId[];
|
|
84
|
+
attributeNames: Record<AttributeId, string>;
|
|
85
|
+
commandNames: Record<CommandId, string>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* A known cluster shape that we instrument as is.
|
|
90
|
+
*/
|
|
91
|
+
export interface KnownClusterShape {
|
|
92
|
+
kind: "known";
|
|
93
|
+
behavior: ClusterBehavior.Type;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function instrumentDiscoveredShape(shape: PeerBehavior.DiscoveredClusterShape) {
|
|
98
|
+
const analysis = DiscoveredShapeAnalysis(shape);
|
|
38
99
|
|
|
39
100
|
const fingerprint = createFingerprint(analysis);
|
|
40
|
-
let type =
|
|
101
|
+
let type = discoveredCache[fingerprint];
|
|
41
102
|
if (type) {
|
|
42
103
|
return type;
|
|
43
104
|
}
|
|
@@ -50,31 +111,41 @@ export function PeerBehavior(shape: PeerBehavior.ClusterShape): ClusterBehavior.
|
|
|
50
111
|
baseType = ClusterBehavior;
|
|
51
112
|
}
|
|
52
113
|
|
|
53
|
-
type =
|
|
114
|
+
type = discoveredCache[fingerprint] = generateDiscoveredType(analysis, baseType);
|
|
54
115
|
|
|
55
116
|
return type;
|
|
56
117
|
}
|
|
57
118
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
features: FeatureBitmap | number;
|
|
63
|
-
attributes: AttributeId[];
|
|
64
|
-
commands: CommandId[];
|
|
65
|
-
attributeNames: Record<AttributeId, string>;
|
|
66
|
-
commandNames: Record<CommandId, string>;
|
|
119
|
+
function instrumentKnownShape(shape: PeerBehavior.KnownClusterShape) {
|
|
120
|
+
let type = knownCache.get(shape.behavior);
|
|
121
|
+
if (type) {
|
|
122
|
+
return type;
|
|
67
123
|
}
|
|
124
|
+
|
|
125
|
+
const base = shape.behavior;
|
|
126
|
+
|
|
127
|
+
type = ClusterBehaviorType({
|
|
128
|
+
base,
|
|
129
|
+
cluster: base.cluster,
|
|
130
|
+
schema: base.schema,
|
|
131
|
+
name: `${base.schema.name}Client`,
|
|
132
|
+
forClient: true,
|
|
133
|
+
commandFactory: ClientCommandMethod,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
knownCache.set(shape.behavior, type);
|
|
137
|
+
|
|
138
|
+
return type;
|
|
68
139
|
}
|
|
69
140
|
|
|
70
|
-
function
|
|
141
|
+
function generateDiscoveredType(analysis: DiscoveredShapeAnalysis, baseType: Behavior.Type): ClusterBehavior.Type {
|
|
71
142
|
// Ensure the input type is a ClusterBehavior
|
|
72
143
|
if (!ClusterBehavior.is(baseType)) {
|
|
73
|
-
throw new InternalError(`Base
|
|
144
|
+
throw new InternalError(`Base for cluster ${analysis.schema.name} is not a ClusterBehavior`);
|
|
74
145
|
}
|
|
75
146
|
|
|
76
147
|
let { schema } = analysis;
|
|
77
|
-
let
|
|
148
|
+
let isExtended = false;
|
|
78
149
|
const { attrSupportOverrides, extraAttrs, commandSupportOverrides, extraCommands } = analysis;
|
|
79
150
|
|
|
80
151
|
// Obtain a ClusterType. This provides TLV for known elements
|
|
@@ -99,7 +170,7 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
|
|
|
99
170
|
.map(([k]) => k);
|
|
100
171
|
if (featureNames.length) {
|
|
101
172
|
// Update ClusterModel
|
|
102
|
-
|
|
173
|
+
extendSchema();
|
|
103
174
|
|
|
104
175
|
// Update the cluster. Note that we do not validate feature combinations. What the device sends we work with
|
|
105
176
|
cluster = new ClusterComposer(cluster, true).compose(featureNames.map(capitalize));
|
|
@@ -111,10 +182,10 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
|
|
|
111
182
|
schema.revision !== analysis.shape.revision ||
|
|
112
183
|
extraAttrs.size ||
|
|
113
184
|
extraCommands.size ||
|
|
114
|
-
|
|
115
|
-
|
|
185
|
+
attrSupportOverrides.size ||
|
|
186
|
+
commandSupportOverrides.size
|
|
116
187
|
) {
|
|
117
|
-
|
|
188
|
+
extendSchema();
|
|
118
189
|
|
|
119
190
|
cluster = {
|
|
120
191
|
...cluster,
|
|
@@ -123,7 +194,7 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
|
|
|
123
194
|
commands: { ...cluster.commands },
|
|
124
195
|
};
|
|
125
196
|
|
|
126
|
-
if (attrSupportOverrides) {
|
|
197
|
+
if (attrSupportOverrides.size) {
|
|
127
198
|
for (const [attr, isSupported] of attrSupportOverrides.entries()) {
|
|
128
199
|
schema.children.push(attr.extend({ operationalIsSupported: isSupported }));
|
|
129
200
|
}
|
|
@@ -135,7 +206,7 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
|
|
|
135
206
|
schema.children.push(new AttributeModel({ id, name, type: "any" }));
|
|
136
207
|
}
|
|
137
208
|
|
|
138
|
-
if (commandSupportOverrides) {
|
|
209
|
+
if (commandSupportOverrides.size) {
|
|
139
210
|
for (const [command, isSupported] of commandSupportOverrides.entries()) {
|
|
140
211
|
schema.children.push(command.extend({ operationalIsSupported: isSupported }));
|
|
141
212
|
}
|
|
@@ -149,72 +220,47 @@ function generateType(analysis: ShapeAnalysis, baseType: Behavior.Type): Cluster
|
|
|
149
220
|
}
|
|
150
221
|
|
|
151
222
|
// Specialize for the specific cluster and schema
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (isCloned) {
|
|
223
|
+
return ClusterBehaviorType({
|
|
224
|
+
base: baseType,
|
|
225
|
+
cluster,
|
|
226
|
+
schema,
|
|
227
|
+
name: `${schema.name}Client`,
|
|
228
|
+
forClient: true,
|
|
229
|
+
commandFactory: ClientCommandMethod,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
function extendSchema() {
|
|
233
|
+
if (isExtended) {
|
|
164
234
|
return;
|
|
165
235
|
}
|
|
166
|
-
schema = schema.
|
|
236
|
+
schema = schema.extend();
|
|
167
237
|
schema.supportedFeatures = featureNames;
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function implementCommand(command: string) {
|
|
172
|
-
return async function (this: ClusterBehavior, fields?: {}) {
|
|
173
|
-
const node = this.env.get(Node) as ClientNode;
|
|
174
|
-
|
|
175
|
-
// TODO when implementing TCP add needed logic for Large messages
|
|
176
|
-
const chunks = (node.interaction as ClientInteraction).invoke(
|
|
177
|
-
Invoke({
|
|
178
|
-
commands: [
|
|
179
|
-
Invoke.ConcreteCommandRequest<any>({
|
|
180
|
-
endpoint: this.endpoint,
|
|
181
|
-
cluster,
|
|
182
|
-
command,
|
|
183
|
-
fields,
|
|
184
|
-
}),
|
|
185
|
-
],
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
for await (const chunk of chunks) {
|
|
190
|
-
for (const entry of chunk) {
|
|
191
|
-
// We send only one command, so we only get one response back
|
|
192
|
-
switch (entry.kind) {
|
|
193
|
-
case "cmd-status":
|
|
194
|
-
if (entry.status !== Status.Success) {
|
|
195
|
-
throw StatusResponseError.create(entry.status, undefined, entry.clusterStatus);
|
|
196
|
-
}
|
|
197
|
-
return;
|
|
198
|
-
|
|
199
|
-
case "cmd-response":
|
|
200
|
-
return entry.data;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
};
|
|
238
|
+
isExtended = true;
|
|
205
239
|
}
|
|
206
240
|
}
|
|
207
241
|
|
|
208
242
|
/**
|
|
209
243
|
* Create a compact string that uniquely identifies a shape for matching purposes.
|
|
210
244
|
*/
|
|
211
|
-
function createFingerprint(analysis:
|
|
212
|
-
const fingerprint = [analysis.shape.id] as (number | string)[];
|
|
245
|
+
function createFingerprint(analysis: DiscoveredShapeAnalysis) {
|
|
246
|
+
const fingerprint = [analysis.shape.id] as (number | string | bigint)[];
|
|
247
|
+
|
|
248
|
+
if (analysis.featureBitmap) {
|
|
249
|
+
fingerprint.push("f", analysis.featureBitmap);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (analysis.attrSupportOverrides.size) {
|
|
253
|
+
addSupportFingerprints("a", analysis.attrSupportOverrides);
|
|
254
|
+
}
|
|
213
255
|
|
|
214
256
|
if (analysis.extraAttrs.size) {
|
|
215
257
|
fingerprint.push("a", createElementFingerprint(analysis.extraAttrs));
|
|
216
258
|
}
|
|
217
259
|
|
|
260
|
+
if (analysis.commandSupportOverrides.size) {
|
|
261
|
+
addSupportFingerprints("c", analysis.commandSupportOverrides);
|
|
262
|
+
}
|
|
263
|
+
|
|
218
264
|
if (analysis.extraCommands.size) {
|
|
219
265
|
fingerprint.push("c", createElementFingerprint(analysis.extraCommands));
|
|
220
266
|
}
|
|
@@ -224,8 +270,8 @@ function createFingerprint(analysis: ShapeAnalysis) {
|
|
|
224
270
|
/**
|
|
225
271
|
* Create a fingerprint for a specific type of ACE element.
|
|
226
272
|
*
|
|
227
|
-
* For elements we
|
|
228
|
-
*
|
|
273
|
+
* For elements we create a series of bitmaps, one for each range of BIT_BLOCK_SIZE unique integers with an ID
|
|
274
|
+
* present. Note that these bitmaps may not be consecutive due to gaps in IDs. We then serialize all bitmaps
|
|
229
275
|
* present as "<block index>:<bitmap value>" and concatenate to create a unique fingerprint.
|
|
230
276
|
*
|
|
231
277
|
* The goal is to efficiently create a compact unique identifier.
|
|
@@ -243,15 +289,53 @@ function createFingerprint(analysis: ShapeAnalysis) {
|
|
|
243
289
|
.map(([block, map]) => (block ? `${block}:${map}` : map))
|
|
244
290
|
.join(",");
|
|
245
291
|
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Add fingerprints for overrides of element support.
|
|
295
|
+
*
|
|
296
|
+
* This adds an "x-" component for unsupported elements and "x+" for supported elements.
|
|
297
|
+
*/
|
|
298
|
+
function addSupportFingerprints(prefix: string, elements: Map<ValueModel, boolean>) {
|
|
299
|
+
let supported: Array<number> | undefined;
|
|
300
|
+
let unsupported: Array<number> | undefined;
|
|
301
|
+
|
|
302
|
+
for (const [{ id }, isSupported] of elements) {
|
|
303
|
+
if (id === undefined) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (isSupported) {
|
|
308
|
+
if (supported) {
|
|
309
|
+
supported.push(id);
|
|
310
|
+
} else {
|
|
311
|
+
supported = [id];
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
if (unsupported) {
|
|
315
|
+
unsupported.push(id);
|
|
316
|
+
} else {
|
|
317
|
+
unsupported = [id];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (supported) {
|
|
323
|
+
fingerprint.push(`${prefix}+`, createElementFingerprint(supported));
|
|
324
|
+
}
|
|
325
|
+
if (unsupported) {
|
|
326
|
+
fingerprint.push(`${prefix}-`, createElementFingerprint(unsupported));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
246
329
|
}
|
|
247
330
|
|
|
248
331
|
function createUnknownName(prefix: string, id: number) {
|
|
249
332
|
return `${prefix}$${id.toString(16)}`;
|
|
250
333
|
}
|
|
251
334
|
|
|
252
|
-
interface
|
|
335
|
+
interface DiscoveredShapeAnalysis {
|
|
253
336
|
schema: ClusterModel & { id: ClusterId };
|
|
254
|
-
|
|
337
|
+
featureBitmap: number | bigint;
|
|
338
|
+
shape: PeerBehavior.DiscoveredClusterShape;
|
|
255
339
|
attrSupportOverrides: Map<AttributeModel, boolean>;
|
|
256
340
|
extraAttrs: Set<number>;
|
|
257
341
|
commandSupportOverrides: Map<CommandModel, boolean>;
|
|
@@ -259,31 +343,25 @@ interface ShapeAnalysis {
|
|
|
259
343
|
}
|
|
260
344
|
|
|
261
345
|
/**
|
|
262
|
-
* Analyze
|
|
346
|
+
* Analyze a discovered cluster shape to determine how we should override the behavior and schema.
|
|
263
347
|
*/
|
|
264
|
-
function
|
|
348
|
+
function DiscoveredShapeAnalysis(shape: PeerBehavior.DiscoveredClusterShape): DiscoveredShapeAnalysis {
|
|
265
349
|
const standardCluster = Matter.get(ClusterModel, shape.id);
|
|
266
350
|
const schema =
|
|
267
351
|
standardCluster ??
|
|
268
352
|
new ClusterModel({ id: shape.id, name: createUnknownName("Cluster", shape.id), revision: shape.revision });
|
|
269
353
|
|
|
354
|
+
let featureBitmap: bigint | number;
|
|
355
|
+
if (typeof shape.features === "number") {
|
|
356
|
+
featureBitmap = shape.features;
|
|
357
|
+
} else {
|
|
358
|
+
featureBitmap = EncodedBitmap(schema.featureMap, shape.features);
|
|
359
|
+
}
|
|
360
|
+
|
|
270
361
|
const attrSupportOverrides = new Map<AttributeModel, boolean>();
|
|
271
362
|
const extraAttrs = new Set<number>(shape.attributes);
|
|
272
363
|
for (const attr of schema.attributes) {
|
|
273
364
|
maybeOverrideSupport(standardCluster, attr, extraAttrs, attrSupportOverrides);
|
|
274
|
-
if (standardCluster) {
|
|
275
|
-
const supported = extraAttrs.has(attr.id);
|
|
276
|
-
const applicability = attr.conformance.applicabilityFor(standardCluster);
|
|
277
|
-
if (!supported) {
|
|
278
|
-
if (applicability) {
|
|
279
|
-
attrSupportOverrides.set(attr, false);
|
|
280
|
-
}
|
|
281
|
-
} else {
|
|
282
|
-
if (applicability !== Conformance.Applicability.Mandatory) {
|
|
283
|
-
attrSupportOverrides.set(attr, true);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
365
|
extraAttrs.delete(attr.id as AttributeId);
|
|
288
366
|
}
|
|
289
367
|
|
|
@@ -296,6 +374,7 @@ function ShapeAnalysis(shape: PeerBehavior.ClusterShape): ShapeAnalysis {
|
|
|
296
374
|
|
|
297
375
|
return {
|
|
298
376
|
schema: schema as ClusterModel & { id: ClusterId },
|
|
377
|
+
featureBitmap,
|
|
299
378
|
shape,
|
|
300
379
|
attrSupportOverrides,
|
|
301
380
|
extraAttrs,
|
|
@@ -313,24 +392,26 @@ function ShapeAnalysis(shape: PeerBehavior.ClusterShape): ShapeAnalysis {
|
|
|
313
392
|
*
|
|
314
393
|
* * the element is optional according to the standard and is implemented on the peer
|
|
315
394
|
*/
|
|
316
|
-
function maybeOverrideSupport<T extends AttributeModel | CommandModel>(
|
|
395
|
+
function maybeOverrideSupport<T extends AttributeModel | CommandModel | EventModel>(
|
|
317
396
|
standardCluster: ClusterModel | undefined,
|
|
318
397
|
element: T,
|
|
319
|
-
supported: Set<number
|
|
398
|
+
supported: Set<number> | true,
|
|
320
399
|
overrides: Map<T, boolean>,
|
|
321
400
|
) {
|
|
322
401
|
if (!standardCluster) {
|
|
323
402
|
return;
|
|
324
403
|
}
|
|
325
404
|
|
|
326
|
-
const isSupported = supported.has(element.id);
|
|
327
|
-
const applicability = element.
|
|
405
|
+
const isSupported = supported === true || supported.has(element.id);
|
|
406
|
+
const applicability = element.effectiveConformance.applicabilityFor(standardCluster);
|
|
328
407
|
if (!isSupported) {
|
|
329
|
-
if (applicability) {
|
|
408
|
+
if (applicability === Conformance.Applicability.Mandatory) {
|
|
409
|
+
// We don't really pay attention to "unsupported mandatory attributes" but mark them anyway
|
|
330
410
|
overrides.set(element, false);
|
|
331
411
|
}
|
|
332
412
|
} else {
|
|
333
413
|
if (applicability !== Conformance.Applicability.Mandatory) {
|
|
414
|
+
// Indicate support for optional feature
|
|
334
415
|
overrides.set(element, true);
|
|
335
416
|
}
|
|
336
417
|
}
|