@matter/protocol 0.16.0-alpha.0-20251001-7eb06da95 → 0.16.0-alpha.0-20251004-92135c7df
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/action/client/ReadScope.d.ts +4 -0
- package/dist/cjs/action/client/ReadScope.d.ts.map +1 -1
- package/dist/cjs/action/client/ReadScope.js +2 -1
- package/dist/cjs/action/client/ReadScope.js.map +1 -1
- package/dist/cjs/ble/Ble.d.ts +3 -3
- package/dist/cjs/ble/Ble.d.ts.map +1 -1
- package/dist/cjs/ble/Ble.js.map +1 -1
- package/dist/cjs/common/Scanner.d.ts +2 -2
- package/dist/cjs/common/Scanner.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts +9 -7
- package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.d.ts +1 -0
- package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
- package/dist/cjs/interaction/InteractionClient.d.ts +13 -3
- package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionClient.js +94 -67
- package/dist/cjs/interaction/InteractionClient.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts +10 -90
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +98 -22
- package/dist/cjs/interaction/InteractionMessenger.js.map +2 -2
- package/dist/cjs/interaction/SubscriptionClient.d.ts +2 -2
- package/dist/cjs/interaction/SubscriptionClient.d.ts.map +1 -1
- package/dist/cjs/interaction/SubscriptionClient.js +1 -1
- package/dist/cjs/interaction/SubscriptionClient.js.map +1 -1
- package/dist/cjs/mdns/MdnsClient.d.ts +3 -3
- package/dist/cjs/mdns/MdnsClient.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsClient.js +28 -14
- package/dist/cjs/mdns/MdnsClient.js.map +1 -1
- package/dist/cjs/mdns/MdnsServer.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsServer.js +59 -5
- package/dist/cjs/mdns/MdnsServer.js.map +1 -1
- package/dist/cjs/mdns/MdnsSocket.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsSocket.js +10 -1
- package/dist/cjs/mdns/MdnsSocket.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.d.ts +2 -2
- package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +7 -5
- package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
- package/dist/cjs/peer/OperationalPeer.d.ts +2 -2
- package/dist/cjs/peer/OperationalPeer.d.ts.map +1 -1
- package/dist/cjs/peer/PeerAddressStore.d.ts +3 -1
- 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 +3 -3
- package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
- package/dist/cjs/peer/PeerSet.js +14 -9
- package/dist/cjs/peer/PeerSet.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts +2 -2
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +21 -17
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageChannel.d.ts +1 -1
- package/dist/cjs/protocol/MessageChannel.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageChannel.js +7 -5
- package/dist/cjs/protocol/MessageChannel.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +0 -1
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +6 -17
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts.map +1 -1
- package/dist/cjs/session/NodeSession.js +3 -3
- package/dist/cjs/session/NodeSession.js.map +1 -1
- package/dist/cjs/session/SessionIntervals.d.ts +1 -5
- package/dist/cjs/session/SessionIntervals.d.ts.map +1 -1
- package/dist/cjs/session/SessionIntervals.js.map +1 -1
- package/dist/cjs/session/case/CaseMessages.d.ts +18 -9
- package/dist/cjs/session/case/CaseMessages.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseMessages.js.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.d.ts +4 -62
- package/dist/cjs/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseMessenger.js.map +1 -1
- package/dist/cjs/session/case/CaseServer.js.map +1 -1
- package/dist/cjs/session/pase/PaseMessages.d.ts +20 -9
- package/dist/cjs/session/pase/PaseMessages.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseMessages.js +3 -3
- package/dist/cjs/session/pase/PaseMessages.js.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.d.ts +3 -51
- package/dist/cjs/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseMessenger.js.map +1 -1
- package/dist/esm/action/client/ReadScope.d.ts +4 -0
- package/dist/esm/action/client/ReadScope.d.ts.map +1 -1
- package/dist/esm/action/client/ReadScope.js +2 -1
- package/dist/esm/action/client/ReadScope.js.map +1 -1
- package/dist/esm/ble/Ble.d.ts +3 -3
- package/dist/esm/ble/Ble.d.ts.map +1 -1
- package/dist/esm/ble/Ble.js.map +1 -1
- package/dist/esm/common/Scanner.d.ts +2 -2
- package/dist/esm/common/Scanner.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.d.ts +9 -7
- package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.d.ts +1 -0
- package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
- package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
- package/dist/esm/interaction/InteractionClient.d.ts +13 -3
- package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionClient.js +96 -68
- package/dist/esm/interaction/InteractionClient.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts +10 -90
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +98 -22
- package/dist/esm/interaction/InteractionMessenger.js.map +2 -2
- package/dist/esm/interaction/SubscriptionClient.d.ts +2 -2
- package/dist/esm/interaction/SubscriptionClient.d.ts.map +1 -1
- package/dist/esm/interaction/SubscriptionClient.js +1 -1
- package/dist/esm/interaction/SubscriptionClient.js.map +1 -1
- package/dist/esm/mdns/MdnsClient.d.ts +3 -3
- package/dist/esm/mdns/MdnsClient.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsClient.js +28 -14
- package/dist/esm/mdns/MdnsClient.js.map +1 -1
- package/dist/esm/mdns/MdnsServer.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsServer.js +60 -5
- package/dist/esm/mdns/MdnsServer.js.map +1 -1
- package/dist/esm/mdns/MdnsSocket.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsSocket.js +12 -1
- package/dist/esm/mdns/MdnsSocket.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.d.ts +2 -2
- package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +9 -6
- package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
- package/dist/esm/peer/OperationalPeer.d.ts +2 -2
- package/dist/esm/peer/OperationalPeer.d.ts.map +1 -1
- package/dist/esm/peer/PeerAddressStore.d.ts +3 -1
- 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 +3 -3
- package/dist/esm/peer/PeerSet.d.ts.map +1 -1
- package/dist/esm/peer/PeerSet.js +15 -10
- package/dist/esm/peer/PeerSet.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts +2 -2
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +22 -18
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageChannel.d.ts +1 -1
- package/dist/esm/protocol/MessageChannel.d.ts.map +1 -1
- package/dist/esm/protocol/MessageChannel.js +7 -5
- package/dist/esm/protocol/MessageChannel.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +0 -1
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +6 -17
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts.map +1 -1
- package/dist/esm/session/NodeSession.js +4 -3
- package/dist/esm/session/NodeSession.js.map +1 -1
- package/dist/esm/session/SessionIntervals.d.ts +1 -5
- package/dist/esm/session/SessionIntervals.d.ts.map +1 -1
- package/dist/esm/session/SessionIntervals.js.map +1 -1
- package/dist/esm/session/case/CaseMessages.d.ts +18 -9
- package/dist/esm/session/case/CaseMessages.d.ts.map +1 -1
- package/dist/esm/session/case/CaseMessages.js.map +1 -1
- package/dist/esm/session/case/CaseMessenger.d.ts +4 -62
- package/dist/esm/session/case/CaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/case/CaseMessenger.js +6 -1
- package/dist/esm/session/case/CaseMessenger.js.map +1 -1
- package/dist/esm/session/case/CaseServer.js.map +1 -1
- package/dist/esm/session/pase/PaseMessages.d.ts +20 -9
- package/dist/esm/session/pase/PaseMessages.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseMessages.js +3 -3
- package/dist/esm/session/pase/PaseMessages.js.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.d.ts +3 -51
- package/dist/esm/session/pase/PaseMessenger.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseMessenger.js.map +1 -1
- package/package.json +6 -6
- package/src/action/client/ReadScope.ts +7 -0
- package/src/ble/Ble.ts +3 -3
- package/src/common/Scanner.ts +2 -2
- package/src/interaction/AttributeDataDecoder.ts +4 -1
- package/src/interaction/DecodedDataReport.ts +1 -0
- package/src/interaction/InteractionClient.ts +154 -79
- package/src/interaction/InteractionMessenger.ts +126 -22
- package/src/interaction/SubscriptionClient.ts +6 -5
- package/src/mdns/MdnsClient.ts +33 -23
- package/src/mdns/MdnsServer.ts +75 -5
- package/src/mdns/MdnsSocket.ts +16 -1
- package/src/peer/ControllerCommissioner.ts +10 -7
- package/src/peer/OperationalPeer.ts +2 -2
- package/src/peer/PeerAddressStore.ts +3 -1
- package/src/peer/PeerSet.ts +23 -18
- package/src/protocol/ExchangeManager.ts +29 -21
- package/src/protocol/MessageChannel.ts +13 -11
- package/src/protocol/MessageExchange.ts +6 -18
- package/src/session/NodeSession.ts +4 -3
- package/src/session/SessionIntervals.ts +1 -1
- package/src/session/case/CaseMessages.ts +12 -2
- package/src/session/case/CaseMessenger.ts +12 -4
- package/src/session/case/CaseServer.ts +5 -5
- package/src/session/pase/PaseMessages.ts +27 -3
- package/src/session/pase/PaseMessenger.ts +8 -9
|
@@ -16,14 +16,20 @@ import {
|
|
|
16
16
|
NoResponseTimeoutError,
|
|
17
17
|
UnexpectedDataError,
|
|
18
18
|
} from "#general";
|
|
19
|
+
import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
|
|
20
|
+
import { DecodedDataReport } from "#interaction/DecodedDataReport.js";
|
|
19
21
|
import { Specification } from "#model";
|
|
20
22
|
import { ChannelNotConnectedError } from "#protocol/MessageChannel.js";
|
|
21
23
|
import {
|
|
24
|
+
AttributeId,
|
|
25
|
+
ClusterId,
|
|
26
|
+
EndpointNumber,
|
|
22
27
|
ReceivedStatusResponseError,
|
|
23
28
|
Status,
|
|
24
29
|
StatusCode,
|
|
25
30
|
StatusResponseError,
|
|
26
31
|
TlvAny,
|
|
32
|
+
TlvAttributeReport,
|
|
27
33
|
TlvDataReport,
|
|
28
34
|
TlvDataReportForSend,
|
|
29
35
|
TlvDataVersionFilter,
|
|
@@ -799,8 +805,105 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
|
|
|
799
805
|
return message;
|
|
800
806
|
}
|
|
801
807
|
|
|
802
|
-
|
|
803
|
-
|
|
808
|
+
/**
|
|
809
|
+
* Reads data report stream and aggregates them into a single report.
|
|
810
|
+
* Additionally, a callback can be provided that is called for each cluster chunk received.
|
|
811
|
+
*/
|
|
812
|
+
async readAggregateDataReport(
|
|
813
|
+
chunkListener?: (chunk: DecodedAttributeReportValue<any>[]) => Promise<void>,
|
|
814
|
+
expectedSubscriptionIds?: number[],
|
|
815
|
+
): Promise<DecodedDataReport> {
|
|
816
|
+
let result: DecodedDataReport | undefined = undefined;
|
|
817
|
+
let currentEndpointId: EndpointNumber | undefined = undefined;
|
|
818
|
+
let currentClusterId: ClusterId | undefined = undefined;
|
|
819
|
+
const currentClusterChunk = new Array<DecodedAttributeReportValue<any>>();
|
|
820
|
+
let pendingAttributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined = undefined;
|
|
821
|
+
|
|
822
|
+
const handleAttributeReportEntries = (
|
|
823
|
+
attributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined,
|
|
824
|
+
previousPendingAttributeReports: TypeFromSchema<typeof TlvAttributeReport>[] | undefined,
|
|
825
|
+
) => {
|
|
826
|
+
if (previousPendingAttributeReports?.length) {
|
|
827
|
+
attributeReports = attributeReports ?? [];
|
|
828
|
+
attributeReports.unshift(...previousPendingAttributeReports);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
let lastAttributeDataIndex = -1;
|
|
832
|
+
if (attributeReports?.length) {
|
|
833
|
+
let lastEndpointId: EndpointNumber | undefined = undefined;
|
|
834
|
+
let lastClusterId: ClusterId | undefined = undefined;
|
|
835
|
+
let lastAttributeId: AttributeId | undefined = undefined;
|
|
836
|
+
for (let i = attributeReports.length - 1; i >= 0; i--) {
|
|
837
|
+
const attributeReport = attributeReports[i];
|
|
838
|
+
if (attributeReport.attributeData === undefined) {
|
|
839
|
+
break; // No data report, so nothing more to search for
|
|
840
|
+
}
|
|
841
|
+
const {
|
|
842
|
+
path: { endpointId, clusterId, attributeId },
|
|
843
|
+
} = attributeReport.attributeData;
|
|
844
|
+
if (lastEndpointId === undefined && lastClusterId === undefined && lastAttributeId === undefined) {
|
|
845
|
+
// Remember path of the last attribute data entry and check if previous entries match
|
|
846
|
+
lastEndpointId = endpointId;
|
|
847
|
+
lastClusterId = clusterId;
|
|
848
|
+
lastAttributeId = attributeId;
|
|
849
|
+
}
|
|
850
|
+
if (
|
|
851
|
+
endpointId === lastEndpointId &&
|
|
852
|
+
clusterId === lastClusterId &&
|
|
853
|
+
attributeId === lastAttributeId
|
|
854
|
+
) {
|
|
855
|
+
lastAttributeDataIndex = i;
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
break; // We found an attribute that does not match the last one, so we are done
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (lastAttributeDataIndex > 0) {
|
|
862
|
+
return attributeReports.splice(lastAttributeDataIndex);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
const processDecodedReport = async (
|
|
868
|
+
decodedReport: DecodedDataReport,
|
|
869
|
+
result: DecodedDataReport | undefined,
|
|
870
|
+
) => {
|
|
871
|
+
if (!result) {
|
|
872
|
+
result = decodedReport;
|
|
873
|
+
} else {
|
|
874
|
+
if (!result.attributeReports) {
|
|
875
|
+
result.attributeReports = decodedReport.attributeReports;
|
|
876
|
+
} else {
|
|
877
|
+
result.attributeReports.push(...decodedReport.attributeReports);
|
|
878
|
+
}
|
|
879
|
+
if (Array.isArray(decodedReport.eventReports)) {
|
|
880
|
+
if (!result.eventReports) {
|
|
881
|
+
result.eventReports = decodedReport.eventReports;
|
|
882
|
+
} else {
|
|
883
|
+
result.eventReports.push(...decodedReport.eventReports);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
if (chunkListener !== undefined && decodedReport.attributeReports) {
|
|
889
|
+
for (const data of decodedReport.attributeReports) {
|
|
890
|
+
const {
|
|
891
|
+
path: { endpointId, clusterId },
|
|
892
|
+
} = data;
|
|
893
|
+
if (currentEndpointId !== endpointId || currentClusterId !== clusterId) {
|
|
894
|
+
// We switched the cluster, so we need to send the current chunk first
|
|
895
|
+
if (currentClusterChunk.length > 0) {
|
|
896
|
+
await chunkListener(currentClusterChunk);
|
|
897
|
+
currentClusterChunk.length = 0;
|
|
898
|
+
}
|
|
899
|
+
currentEndpointId = endpointId;
|
|
900
|
+
currentClusterId = clusterId;
|
|
901
|
+
}
|
|
902
|
+
currentClusterChunk.push(data);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
return result;
|
|
906
|
+
};
|
|
804
907
|
|
|
805
908
|
for await (const report of this.readDataReports()) {
|
|
806
909
|
if (expectedSubscriptionIds !== undefined) {
|
|
@@ -823,24 +926,25 @@ export class IncomingInteractionClientMessenger extends InteractionMessenger {
|
|
|
823
926
|
throw new UnexpectedDataError(`Invalid subscription ID ${report.subscriptionId} received`);
|
|
824
927
|
}
|
|
825
928
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
929
|
+
report.attributeReports = report.attributeReports ?? [];
|
|
930
|
+
pendingAttributeReports = handleAttributeReportEntries(report.attributeReports, pendingAttributeReports);
|
|
931
|
+
|
|
932
|
+
result = await processDecodedReport(DecodedDataReport(report), result);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
if (pendingAttributeReports?.length && result !== undefined) {
|
|
936
|
+
result = await processDecodedReport(
|
|
937
|
+
DecodedDataReport({
|
|
938
|
+
interactionModelRevision: result.interactionModelRevision,
|
|
939
|
+
attributeReports: pendingAttributeReports,
|
|
940
|
+
}),
|
|
941
|
+
result,
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
if (chunkListener !== undefined && currentClusterChunk.length > 0) {
|
|
946
|
+
await chunkListener(currentClusterChunk);
|
|
947
|
+
currentClusterChunk.length = 0;
|
|
844
948
|
}
|
|
845
949
|
|
|
846
950
|
if (result === undefined) {
|
|
@@ -1010,8 +1114,8 @@ export class InteractionClientMessenger extends IncomingInteractionClientMesseng
|
|
|
1010
1114
|
await this.send(MessageType.SubscribeRequest, request);
|
|
1011
1115
|
}
|
|
1012
1116
|
|
|
1013
|
-
async readAggregateSubscribeResponse() {
|
|
1014
|
-
const report = await this.readAggregateDataReport();
|
|
1117
|
+
async readAggregateSubscribeResponse(chunkListener?: (chunk: DecodedAttributeReportValue<any>[]) => Promise<void>) {
|
|
1118
|
+
const report = await this.readAggregateDataReport(chunkListener);
|
|
1015
1119
|
const { subscriptionId } = report;
|
|
1016
1120
|
|
|
1017
1121
|
if (subscriptionId === undefined) {
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Duration, Environment, Environmental, Logger, MaybePromise, Millis, Time, Timer } from "#general";
|
|
8
|
+
import { DecodedDataReport } from "#interaction/DecodedDataReport.js";
|
|
8
9
|
import { MessageExchange } from "#protocol/MessageExchange.js";
|
|
9
10
|
import { ProtocolHandler } from "#protocol/ProtocolHandler.js";
|
|
10
11
|
import { INTERACTION_PROTOCOL_ID } from "#types";
|
|
11
|
-
import {
|
|
12
|
+
import { IncomingInteractionClientMessenger } from "./InteractionMessenger.js";
|
|
12
13
|
|
|
13
14
|
const logger = Logger.get("SubscriptionClient");
|
|
14
15
|
|
|
@@ -16,7 +17,7 @@ export interface RegisteredSubscription {
|
|
|
16
17
|
id: number;
|
|
17
18
|
maximumPeerResponseTime: Duration;
|
|
18
19
|
maxInterval: Duration;
|
|
19
|
-
onData: (dataReport:
|
|
20
|
+
onData: (dataReport: DecodedDataReport) => MaybePromise<void>;
|
|
20
21
|
onTimeout?: () => void;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -28,7 +29,7 @@ export interface RegisteredSubscription {
|
|
|
28
29
|
export class SubscriptionClient implements ProtocolHandler {
|
|
29
30
|
readonly id = INTERACTION_PROTOCOL_ID;
|
|
30
31
|
readonly requiresSecureSession = true;
|
|
31
|
-
readonly #listeners = new Map<number, (dataReport:
|
|
32
|
+
readonly #listeners = new Map<number, (dataReport: DecodedDataReport) => MaybePromise<void>>();
|
|
32
33
|
readonly #timeouts = new Map<number, Timer>();
|
|
33
34
|
|
|
34
35
|
constructor() {}
|
|
@@ -80,10 +81,10 @@ export class SubscriptionClient implements ProtocolHandler {
|
|
|
80
81
|
async onNewExchange(exchange: MessageExchange) {
|
|
81
82
|
const messenger = new IncomingInteractionClientMessenger(exchange);
|
|
82
83
|
|
|
83
|
-
let dataReport:
|
|
84
|
+
let dataReport: DecodedDataReport;
|
|
84
85
|
try {
|
|
85
86
|
// TODO Adjust this to getting packages as callback when received to handle error cases and checks outside
|
|
86
|
-
dataReport = await messenger.readAggregateDataReport([...this.#listeners.keys()]);
|
|
87
|
+
dataReport = await messenger.readAggregateDataReport(undefined, [...this.#listeners.keys()]);
|
|
87
88
|
} finally {
|
|
88
89
|
messenger.close().catch(error => logger.info("Error closing client messenger", error));
|
|
89
90
|
}
|
package/src/mdns/MdnsClient.ts
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
ObserverGroup,
|
|
27
27
|
Seconds,
|
|
28
28
|
ServerAddress,
|
|
29
|
-
|
|
29
|
+
ServerAddressUdp,
|
|
30
30
|
SrvRecordValue,
|
|
31
31
|
Time,
|
|
32
32
|
Timer,
|
|
@@ -60,7 +60,7 @@ const logger = Logger.get("MdnsClient");
|
|
|
60
60
|
|
|
61
61
|
const MDNS_EXPIRY_GRACE_PERIOD_FACTOR = 1.05;
|
|
62
62
|
|
|
63
|
-
type MatterServerRecordWithExpire =
|
|
63
|
+
type MatterServerRecordWithExpire = ServerAddressUdp & Lifespan;
|
|
64
64
|
|
|
65
65
|
/** Type for commissionable Device records including Lifespan details. */
|
|
66
66
|
type CommissionableDeviceRecordWithExpire = Omit<CommissionableDevice, "addresses"> &
|
|
@@ -140,7 +140,8 @@ export class MdnsClient implements Scanner {
|
|
|
140
140
|
readonly #recordWaiters = new Map<
|
|
141
141
|
string,
|
|
142
142
|
{
|
|
143
|
-
resolver: () => void;
|
|
143
|
+
resolver: (value: any) => void;
|
|
144
|
+
responder?: () => any;
|
|
144
145
|
timer?: Timer;
|
|
145
146
|
resolveOnUpdatedRecords: boolean;
|
|
146
147
|
cancelResolver?: (value: void) => void;
|
|
@@ -354,7 +355,7 @@ export class MdnsClient implements Scanner {
|
|
|
354
355
|
ip,
|
|
355
356
|
port,
|
|
356
357
|
type: "udp",
|
|
357
|
-
})) as
|
|
358
|
+
})) as ServerAddressUdp[],
|
|
358
359
|
};
|
|
359
360
|
}
|
|
360
361
|
|
|
@@ -400,14 +401,15 @@ export class MdnsClient implements Scanner {
|
|
|
400
401
|
* Registers a deferred promise for a specific queryId together with a timeout and return the promise.
|
|
401
402
|
* The promise will be resolved when the timer runs out latest.
|
|
402
403
|
*/
|
|
403
|
-
async #registerWaiterPromise(
|
|
404
|
+
async #registerWaiterPromise<T = void>(
|
|
404
405
|
queryId: string,
|
|
405
406
|
commissionable: boolean,
|
|
406
|
-
timeout
|
|
407
|
+
timeout: Duration | undefined,
|
|
408
|
+
responder?: () => T,
|
|
407
409
|
resolveOnUpdatedRecords = true,
|
|
408
410
|
cancelResolver?: (value: void) => void,
|
|
409
|
-
) {
|
|
410
|
-
const { promise, resolver } = createPromise<
|
|
411
|
+
): Promise<T> {
|
|
412
|
+
const { promise, resolver } = createPromise<T>();
|
|
411
413
|
const timer =
|
|
412
414
|
timeout !== undefined
|
|
413
415
|
? Time.getTimer("MDNS timeout", timeout, () => {
|
|
@@ -416,7 +418,14 @@ export class MdnsClient implements Scanner {
|
|
|
416
418
|
}).start()
|
|
417
419
|
: undefined;
|
|
418
420
|
this.#listening = true;
|
|
419
|
-
this.#recordWaiters.set(queryId, {
|
|
421
|
+
this.#recordWaiters.set(queryId, {
|
|
422
|
+
resolver,
|
|
423
|
+
responder,
|
|
424
|
+
timer,
|
|
425
|
+
resolveOnUpdatedRecords,
|
|
426
|
+
cancelResolver,
|
|
427
|
+
commissionable,
|
|
428
|
+
});
|
|
420
429
|
this.#hasCommissionableWaiters = this.#hasCommissionableWaiters || commissionable;
|
|
421
430
|
if (!commissionable) {
|
|
422
431
|
this.#registerOperationalQuery(queryId);
|
|
@@ -426,7 +435,7 @@ export class MdnsClient implements Scanner {
|
|
|
426
435
|
timeout !== undefined ? `timeout ${timeout}` : "no timeout"
|
|
427
436
|
}${resolveOnUpdatedRecords ? "" : " (not resolving on updated records)"}`,
|
|
428
437
|
);
|
|
429
|
-
await promise;
|
|
438
|
+
return await promise;
|
|
430
439
|
}
|
|
431
440
|
|
|
432
441
|
/**
|
|
@@ -436,12 +445,12 @@ export class MdnsClient implements Scanner {
|
|
|
436
445
|
#finishWaiter(queryId: string, resolvePromise: boolean, isUpdatedRecord = false) {
|
|
437
446
|
const waiter = this.#recordWaiters.get(queryId);
|
|
438
447
|
if (waiter === undefined) return;
|
|
439
|
-
const { timer, resolver, resolveOnUpdatedRecords, commissionable } = waiter;
|
|
448
|
+
const { timer, resolver, responder, resolveOnUpdatedRecords, commissionable } = waiter;
|
|
440
449
|
if (isUpdatedRecord && !resolveOnUpdatedRecords) return;
|
|
441
450
|
logger.debug(`Finishing waiter for query ${queryId}, resolving: ${resolvePromise}`);
|
|
442
451
|
timer?.stop();
|
|
443
452
|
if (resolvePromise) {
|
|
444
|
-
resolver();
|
|
453
|
+
resolver(responder?.());
|
|
445
454
|
}
|
|
446
455
|
this.#recordWaiters.delete(queryId);
|
|
447
456
|
this.#removeQuery(queryId);
|
|
@@ -500,7 +509,9 @@ export class MdnsClient implements Scanner {
|
|
|
500
509
|
|
|
501
510
|
let storedDevice = ignoreExistingRecords ? undefined : this.#getOperationalDeviceRecords(deviceMatterQname);
|
|
502
511
|
if (storedDevice === undefined) {
|
|
503
|
-
const promise = this.#registerWaiterPromise(deviceMatterQname, false, timeout)
|
|
512
|
+
const promise = this.#registerWaiterPromise(deviceMatterQname, false, timeout, () =>
|
|
513
|
+
this.#getOperationalDeviceRecords(deviceMatterQname),
|
|
514
|
+
);
|
|
504
515
|
|
|
505
516
|
this.#setQueryRecords(deviceMatterQname, [
|
|
506
517
|
{
|
|
@@ -510,8 +521,7 @@ export class MdnsClient implements Scanner {
|
|
|
510
521
|
},
|
|
511
522
|
]);
|
|
512
523
|
|
|
513
|
-
await promise;
|
|
514
|
-
storedDevice = this.#getOperationalDeviceRecords(deviceMatterQname);
|
|
524
|
+
storedDevice = await promise;
|
|
515
525
|
}
|
|
516
526
|
return storedDevice;
|
|
517
527
|
}
|
|
@@ -570,7 +580,7 @@ export class MdnsClient implements Scanner {
|
|
|
570
580
|
ip,
|
|
571
581
|
port,
|
|
572
582
|
type: "udp",
|
|
573
|
-
})) as
|
|
583
|
+
})) as ServerAddressUdp[],
|
|
574
584
|
discoveredAt: undefined,
|
|
575
585
|
ttl: undefined,
|
|
576
586
|
};
|
|
@@ -727,12 +737,13 @@ export class MdnsClient implements Scanner {
|
|
|
727
737
|
: this.#getCommissionableDeviceRecords(identifier).filter(({ addresses }) => addresses.length > 0);
|
|
728
738
|
if (storedRecords.length === 0) {
|
|
729
739
|
const queryId = this.#buildCommissionableQueryIdentifier(identifier);
|
|
730
|
-
const promise = this.#registerWaiterPromise(queryId, true, timeout)
|
|
740
|
+
const promise = this.#registerWaiterPromise(queryId, true, timeout, () =>
|
|
741
|
+
this.#getCommissionableDeviceRecords(identifier),
|
|
742
|
+
);
|
|
731
743
|
|
|
732
744
|
this.#setQueryRecords(queryId, this.#getCommissionableQueryRecords(identifier));
|
|
733
745
|
|
|
734
|
-
await promise;
|
|
735
|
-
storedRecords = this.#getCommissionableDeviceRecords(identifier);
|
|
746
|
+
storedRecords = await promise;
|
|
736
747
|
}
|
|
737
748
|
|
|
738
749
|
return storedRecords;
|
|
@@ -791,7 +802,7 @@ export class MdnsClient implements Scanner {
|
|
|
791
802
|
break;
|
|
792
803
|
}
|
|
793
804
|
}
|
|
794
|
-
await this.#registerWaiterPromise(queryId, true, remainingTime, false, queryResolver);
|
|
805
|
+
await this.#registerWaiterPromise(queryId, true, remainingTime, undefined, false, queryResolver);
|
|
795
806
|
}
|
|
796
807
|
return this.#getCommissionableDeviceRecords(identifier);
|
|
797
808
|
}
|
|
@@ -981,8 +992,7 @@ export class MdnsClient implements Scanner {
|
|
|
981
992
|
if (this.#closing) return;
|
|
982
993
|
|
|
983
994
|
if (message === undefined) return; // The message cannot be parsed
|
|
984
|
-
if (
|
|
985
|
-
return;
|
|
995
|
+
if (!DnsMessageType.isResponse(message.messageType)) return;
|
|
986
996
|
|
|
987
997
|
const answers = this.#structureAnswers([...message.answers, ...message.additionalRecords]);
|
|
988
998
|
|
|
@@ -1458,7 +1468,7 @@ export class MdnsClient implements Scanner {
|
|
|
1458
1468
|
});
|
|
1459
1469
|
}
|
|
1460
1470
|
if (now > expires && !addresses.size) {
|
|
1461
|
-
// device expired and also has no
|
|
1471
|
+
// device expired and also has no addresses anymore
|
|
1462
1472
|
this.#operationalDeviceRecords.delete(recordKey);
|
|
1463
1473
|
}
|
|
1464
1474
|
});
|
package/src/mdns/MdnsServer.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import {
|
|
8
8
|
AsyncCache,
|
|
9
9
|
DnsMessageType,
|
|
10
|
+
DnsMessageTypeFlag,
|
|
10
11
|
DnsRecord,
|
|
11
12
|
DnsRecordType,
|
|
12
13
|
Instant,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
NetworkInterfaceDetails,
|
|
19
20
|
ObserverGroup,
|
|
20
21
|
Time,
|
|
22
|
+
Timer,
|
|
21
23
|
} from "#general";
|
|
22
24
|
import { MdnsSocket } from "./MdnsSocket.js";
|
|
23
25
|
|
|
@@ -44,6 +46,7 @@ export class MdnsServer {
|
|
|
44
46
|
Minutes(15) /* matches maximum standard commissioning window time */,
|
|
45
47
|
);
|
|
46
48
|
readonly #recordLastSentAsMulticastAnswer = new Map<string, number>();
|
|
49
|
+
readonly #truncatedQueryCache = new Map<string, { message: MdnsSocket.Message; timer: Timer }>();
|
|
47
50
|
|
|
48
51
|
readonly #socket: MdnsSocket;
|
|
49
52
|
|
|
@@ -64,15 +67,19 @@ export class MdnsServer {
|
|
|
64
67
|
return `${record.name}-${record.recordClass}-${record.recordType}-${netInterface}-${unicastTarget}`;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
async #handleMessage(
|
|
68
|
-
const records = await this.#records.get(
|
|
70
|
+
async #handleMessage(incomingMessage: MdnsSocket.Message) {
|
|
71
|
+
const records = await this.#records.get(incomingMessage.sourceIntf);
|
|
69
72
|
|
|
70
73
|
// Ignore if we have no records for interface
|
|
71
74
|
if (records.size === 0) return;
|
|
72
75
|
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
+
const message = this.#prepareMessage(incomingMessage);
|
|
77
|
+
if (message === undefined) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { sourceIntf, sourceIp, transactionId, queries, answers: knownAnswers } = message;
|
|
82
|
+
|
|
76
83
|
for (const portRecords of records.values()) {
|
|
77
84
|
let answers = queries.flatMap(query => this.#queryRecords(query, portRecords));
|
|
78
85
|
if (answers.length === 0) continue;
|
|
@@ -213,6 +220,10 @@ export class MdnsServer {
|
|
|
213
220
|
async close() {
|
|
214
221
|
this.#observers.close();
|
|
215
222
|
await this.#records.close();
|
|
223
|
+
for (const { timer } of this.#truncatedQueryCache.values()) {
|
|
224
|
+
timer.stop();
|
|
225
|
+
}
|
|
226
|
+
this.#truncatedQueryCache.clear();
|
|
216
227
|
this.#recordLastSentAsMulticastAnswer.clear();
|
|
217
228
|
}
|
|
218
229
|
|
|
@@ -228,6 +239,65 @@ export class MdnsServer {
|
|
|
228
239
|
return records.filter(record => record.name === name && record.recordType === recordType);
|
|
229
240
|
}
|
|
230
241
|
}
|
|
242
|
+
|
|
243
|
+
async #processTruncatedQuery(key: string) {
|
|
244
|
+
const { message, timer } = this.#truncatedQueryCache.get(key) ?? {};
|
|
245
|
+
this.#truncatedQueryCache.delete(key);
|
|
246
|
+
timer?.stop();
|
|
247
|
+
if (message) {
|
|
248
|
+
if (message.queries.length === 0) {
|
|
249
|
+
// Should not happen but ignore if it does
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
message.messageType &= ~DnsMessageTypeFlag.TC; // Clear TC flag
|
|
253
|
+
await this.#handleMessage(message);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Delays processing of truncated messages to allow combining multiple parts or combines them if possible
|
|
259
|
+
*/
|
|
260
|
+
#prepareMessage(newMessage: MdnsSocket.Message): MdnsSocket.Message | undefined {
|
|
261
|
+
const { messageType, transactionId, sourceIntf, sourceIp } = newMessage;
|
|
262
|
+
|
|
263
|
+
if (!DnsMessageType.isQuery(messageType)) {
|
|
264
|
+
// We are only interested in queries
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const key = `${transactionId}-${sourceIntf}-${sourceIp}`;
|
|
269
|
+
const { message: existingMessage, timer } = this.#truncatedQueryCache.get(key) ?? {};
|
|
270
|
+
this.#truncatedQueryCache.delete(key);
|
|
271
|
+
timer?.stop();
|
|
272
|
+
|
|
273
|
+
const message = existingMessage
|
|
274
|
+
? {
|
|
275
|
+
...existingMessage,
|
|
276
|
+
queries: [...existingMessage.queries, ...newMessage.queries],
|
|
277
|
+
answers: [...existingMessage.answers, ...newMessage.answers],
|
|
278
|
+
additionalRecords: [...existingMessage.additionalRecords, ...newMessage.additionalRecords],
|
|
279
|
+
messageType: newMessage.messageType, // Keep TC flag as is from the latest message
|
|
280
|
+
}
|
|
281
|
+
: newMessage;
|
|
282
|
+
|
|
283
|
+
// Message was not truncated, or we have now received all details, process it
|
|
284
|
+
if ((messageType & DnsMessageTypeFlag.TC) === 0) {
|
|
285
|
+
if (message.queries.length === 0) {
|
|
286
|
+
// Should not happen but ignore if it does
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
return message;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// We have stored a new or updated truncated message - store and wait for next part
|
|
293
|
+
// Delay should be max 400-500ms as per RFC 6762 section 7.2
|
|
294
|
+
this.#truncatedQueryCache.set(key, {
|
|
295
|
+
message,
|
|
296
|
+
timer: Time.getTimer(`Truncated MDNS message ${key}`, Millis(400 + Math.floor(Math.random() * 100)), () =>
|
|
297
|
+
this.#processTruncatedQuery(key),
|
|
298
|
+
).start(),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
231
301
|
}
|
|
232
302
|
|
|
233
303
|
export namespace MdnsServer {
|
package/src/mdns/MdnsSocket.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
DnsMessage,
|
|
13
13
|
DnsMessagePartiallyPreEncoded,
|
|
14
14
|
DnsMessageType,
|
|
15
|
+
DnsMessageTypeFlag,
|
|
15
16
|
Logger,
|
|
16
17
|
MatterAggregateError,
|
|
17
18
|
MAX_MDNS_MESSAGE_SIZE,
|
|
@@ -71,6 +72,12 @@ export class MdnsSocket {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
async send(message: Partial<DnsMessage> & { messageType: DnsMessageType }, intf?: string, unicastDest?: string) {
|
|
75
|
+
const { messageType } = message;
|
|
76
|
+
// When we send Queries that are too long they need to have the Truncated flag set
|
|
77
|
+
const truncatedMessageType = DnsMessageType.isQuery(messageType)
|
|
78
|
+
? messageType | DnsMessageTypeFlag.TC
|
|
79
|
+
: messageType;
|
|
80
|
+
|
|
74
81
|
const chunk: DnsMessagePartiallyPreEncoded = {
|
|
75
82
|
transactionId: 0,
|
|
76
83
|
queries: [],
|
|
@@ -101,7 +108,15 @@ export class MdnsSocket {
|
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
// New answer does not fit anymore, send out the message
|
|
104
|
-
|
|
111
|
+
// When sending a query, we set the Truncated flag to indicate more answers are available
|
|
112
|
+
await this.#send(
|
|
113
|
+
{
|
|
114
|
+
...chunk,
|
|
115
|
+
messageType: truncatedMessageType,
|
|
116
|
+
},
|
|
117
|
+
intf,
|
|
118
|
+
unicastDest,
|
|
119
|
+
);
|
|
105
120
|
|
|
106
121
|
// Reset the message, length counter and included answers to count for next message
|
|
107
122
|
if (chunk.queries.length) {
|
|
@@ -13,15 +13,16 @@ import {
|
|
|
13
13
|
Channel,
|
|
14
14
|
ChannelType,
|
|
15
15
|
ClassExtends,
|
|
16
|
+
ConnectionlessTransportSet,
|
|
16
17
|
Diagnostic,
|
|
17
18
|
Duration,
|
|
18
19
|
Environment,
|
|
19
20
|
Environmental,
|
|
21
|
+
ImplementationError,
|
|
20
22
|
isIPv6,
|
|
21
23
|
Logger,
|
|
22
24
|
Millis,
|
|
23
25
|
Minutes,
|
|
24
|
-
NetInterfaceSet,
|
|
25
26
|
NoResponseTimeoutError,
|
|
26
27
|
Seconds,
|
|
27
28
|
ServerAddress,
|
|
@@ -129,7 +130,7 @@ export interface ControllerCommissionerContext {
|
|
|
129
130
|
peers: PeerSet;
|
|
130
131
|
clients: InteractionClientProvider;
|
|
131
132
|
scanners: ScannerSet;
|
|
132
|
-
|
|
133
|
+
transports: ConnectionlessTransportSet;
|
|
133
134
|
sessions: SessionManager;
|
|
134
135
|
exchanges: ExchangeManager;
|
|
135
136
|
ca: CertificateAuthority;
|
|
@@ -152,7 +153,7 @@ export class ControllerCommissioner {
|
|
|
152
153
|
peers: env.get(PeerSet),
|
|
153
154
|
clients: env.get(InteractionClientProvider),
|
|
154
155
|
scanners: env.get(ScannerSet),
|
|
155
|
-
|
|
156
|
+
transports: env.get(ConnectionlessTransportSet),
|
|
156
157
|
sessions: env.get(SessionManager),
|
|
157
158
|
exchanges: env.get(ExchangeManager),
|
|
158
159
|
ca: env.get(CertificateAuthority),
|
|
@@ -213,7 +214,7 @@ export class ControllerCommissioner {
|
|
|
213
214
|
|
|
214
215
|
if (
|
|
215
216
|
this.#context.scanners.hasScannerFor(ChannelType.UDP) &&
|
|
216
|
-
this.#context.
|
|
217
|
+
this.#context.transports.hasInterfaceFor(ChannelType.UDP, "::") !== undefined
|
|
217
218
|
) {
|
|
218
219
|
discoveryCapabilities.onIpNetwork = true; // We always discover on network as defined by specs
|
|
219
220
|
}
|
|
@@ -316,7 +317,7 @@ export class ControllerCommissioner {
|
|
|
316
317
|
const { ip } = address;
|
|
317
318
|
|
|
318
319
|
const isIpv6Address = isIPv6(ip);
|
|
319
|
-
const paseInterface = this.#context.
|
|
320
|
+
const paseInterface = this.#context.transports.interfaceFor(
|
|
320
321
|
ChannelType.UDP,
|
|
321
322
|
isIpv6Address ? "::" : "0.0.0.0",
|
|
322
323
|
);
|
|
@@ -327,8 +328,8 @@ export class ControllerCommissioner {
|
|
|
327
328
|
);
|
|
328
329
|
}
|
|
329
330
|
paseChannel = await paseInterface.openChannel(address);
|
|
330
|
-
} else {
|
|
331
|
-
const ble = this.#context.
|
|
331
|
+
} else if (address.type === "ble") {
|
|
332
|
+
const ble = this.#context.transports.interfaceFor(ChannelType.BLE);
|
|
332
333
|
if (!ble) {
|
|
333
334
|
throw new PairRetransmissionLimitReachedError(
|
|
334
335
|
`BLE interface not initialized. Cannot use ${address.peripheralAddress} for commissioning.`,
|
|
@@ -336,6 +337,8 @@ export class ControllerCommissioner {
|
|
|
336
337
|
}
|
|
337
338
|
// TODO Have a Timeout mechanism here for connections
|
|
338
339
|
paseChannel = await ble.openChannel(address);
|
|
340
|
+
} else {
|
|
341
|
+
throw new ImplementationError(`Unsupported PASE address type ${address.type}`);
|
|
339
342
|
}
|
|
340
343
|
|
|
341
344
|
// Do PASE paring
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { DiscoveryData } from "#common/Scanner.js";
|
|
8
|
-
import {
|
|
8
|
+
import { ServerAddressUdp } from "#general";
|
|
9
9
|
import type { PeerDataStore } from "#peer/PeerAddressStore.js";
|
|
10
10
|
import { SessionParameters } from "#session/Session.js";
|
|
11
11
|
import { PeerAddress } from "./PeerAddress.js";
|
|
@@ -24,7 +24,7 @@ export interface OperationalPeer {
|
|
|
24
24
|
/**
|
|
25
25
|
* A physical address the peer may be accessed at, if known.
|
|
26
26
|
*/
|
|
27
|
-
operationalAddress?:
|
|
27
|
+
operationalAddress?: ServerAddressUdp;
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* The peer's session parameters reported during discovery.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { ReadScope } from "#action/client/ReadScope.js";
|
|
7
8
|
import { Construction, MaybePromise } from "#general";
|
|
8
9
|
import { DecodedAttributeReportValue } from "#interaction/AttributeDataDecoder.js";
|
|
9
10
|
import { AttributeId, ClusterId, EndpointNumber, EventNumber } from "#types";
|
|
@@ -27,7 +28,7 @@ export abstract class PeerDataStore {
|
|
|
27
28
|
abstract maxEventNumber: EventNumber;
|
|
28
29
|
abstract updateLastEventNumber(eventNumber: EventNumber): MaybePromise<void>;
|
|
29
30
|
|
|
30
|
-
abstract persistAttributes(attributes: DecodedAttributeReportValue<any>[]): MaybePromise<void>;
|
|
31
|
+
abstract persistAttributes(attributes: DecodedAttributeReportValue<any>[], scope: ReadScope): MaybePromise<void>;
|
|
31
32
|
|
|
32
33
|
// TODO: Find a maybe better way to achieve this without functions
|
|
33
34
|
abstract retrieveAttribute(
|
|
@@ -41,4 +42,5 @@ export abstract class PeerDataStore {
|
|
|
41
42
|
filterEndpointId?: EndpointNumber,
|
|
42
43
|
filterClusterId?: ClusterId,
|
|
43
44
|
): { endpointId: EndpointNumber; clusterId: ClusterId; dataVersion: number }[];
|
|
45
|
+
abstract cleanupAttributeData(endpointId: EndpointNumber, clusterIds?: ClusterId[]): MaybePromise<void>;
|
|
44
46
|
}
|