@matter/protocol 0.13.1-alpha.0-20250508-047aa0277 → 0.13.1-alpha.0-20250511-74ef153aa
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/protocols.d.ts +59 -2
- package/dist/cjs/action/protocols.d.ts.map +1 -1
- package/dist/cjs/action/request/Read.d.ts +2 -2
- package/dist/cjs/action/request/Read.d.ts.map +1 -1
- package/dist/cjs/action/request/Read.js +4 -4
- package/dist/cjs/action/request/Read.js.map +1 -1
- package/dist/cjs/action/response/ReadResult.d.ts +6 -2
- package/dist/cjs/action/response/ReadResult.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeResponse.d.ts +46 -17
- package/dist/cjs/action/server/AttributeResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeResponse.js +128 -110
- package/dist/cjs/action/server/AttributeResponse.js.map +2 -2
- package/dist/cjs/action/server/AttributeSubscriptionResponse.d.ts +36 -0
- package/dist/cjs/action/server/AttributeSubscriptionResponse.d.ts.map +1 -0
- package/dist/cjs/action/server/AttributeSubscriptionResponse.js +86 -0
- package/dist/cjs/action/server/AttributeSubscriptionResponse.js.map +6 -0
- package/dist/cjs/action/server/DataResponse.d.ts +45 -0
- package/dist/cjs/action/server/DataResponse.d.ts.map +1 -0
- package/dist/cjs/action/server/DataResponse.js +69 -0
- package/dist/cjs/action/server/DataResponse.js.map +6 -0
- package/dist/cjs/action/server/EventResponse.d.ts +28 -0
- package/dist/cjs/action/server/EventResponse.d.ts.map +1 -0
- package/dist/cjs/action/server/EventResponse.js +318 -0
- package/dist/cjs/action/server/EventResponse.js.map +6 -0
- package/dist/cjs/action/server/ServerInteraction.d.ts.map +1 -1
- package/dist/cjs/action/server/ServerInteraction.js +15 -2
- package/dist/cjs/action/server/ServerInteraction.js.map +1 -1
- package/dist/cjs/action/server/index.d.ts +3 -0
- package/dist/cjs/action/server/index.d.ts.map +1 -1
- package/dist/cjs/action/server/index.js +3 -0
- package/dist/cjs/action/server/index.js.map +1 -1
- package/dist/cjs/events/OccurrenceManager.d.ts +20 -11
- package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/cjs/events/OccurrenceManager.js +113 -74
- package/dist/cjs/events/OccurrenceManager.js.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.d.ts +14 -2
- package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/cjs/interaction/InteractionMessenger.js +87 -3
- package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
- package/dist/cjs/interaction/index.d.ts +0 -1
- package/dist/cjs/interaction/index.d.ts.map +1 -1
- package/dist/cjs/interaction/index.js +0 -1
- package/dist/cjs/interaction/index.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.js +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +11 -1
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/action/protocols.d.ts +59 -2
- package/dist/esm/action/protocols.d.ts.map +1 -1
- package/dist/esm/action/request/Read.d.ts +2 -2
- package/dist/esm/action/request/Read.d.ts.map +1 -1
- package/dist/esm/action/request/Read.js +4 -4
- package/dist/esm/action/request/Read.js.map +1 -1
- package/dist/esm/action/response/ReadResult.d.ts +6 -2
- package/dist/esm/action/response/ReadResult.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeResponse.d.ts +46 -17
- package/dist/esm/action/server/AttributeResponse.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeResponse.js +129 -113
- package/dist/esm/action/server/AttributeResponse.js.map +1 -1
- package/dist/esm/action/server/AttributeSubscriptionResponse.d.ts +36 -0
- package/dist/esm/action/server/AttributeSubscriptionResponse.d.ts.map +1 -0
- package/dist/esm/action/server/AttributeSubscriptionResponse.js +66 -0
- package/dist/esm/action/server/AttributeSubscriptionResponse.js.map +6 -0
- package/dist/esm/action/server/DataResponse.d.ts +45 -0
- package/dist/esm/action/server/DataResponse.d.ts.map +1 -0
- package/dist/esm/action/server/DataResponse.js +49 -0
- package/dist/esm/action/server/DataResponse.js.map +6 -0
- package/dist/esm/action/server/EventResponse.d.ts +28 -0
- package/dist/esm/action/server/EventResponse.d.ts.map +1 -0
- package/dist/esm/action/server/EventResponse.js +305 -0
- package/dist/esm/action/server/EventResponse.js.map +6 -0
- package/dist/esm/action/server/ServerInteraction.d.ts.map +1 -1
- package/dist/esm/action/server/ServerInteraction.js +16 -3
- package/dist/esm/action/server/ServerInteraction.js.map +1 -1
- package/dist/esm/action/server/index.d.ts +3 -0
- package/dist/esm/action/server/index.d.ts.map +1 -1
- package/dist/esm/action/server/index.js +3 -0
- package/dist/esm/action/server/index.js.map +1 -1
- package/dist/esm/events/OccurrenceManager.d.ts +20 -11
- package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/esm/events/OccurrenceManager.js +117 -80
- package/dist/esm/events/OccurrenceManager.js.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.d.ts +14 -2
- package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
- package/dist/esm/interaction/InteractionMessenger.js +87 -3
- package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
- package/dist/esm/interaction/index.d.ts +0 -1
- package/dist/esm/interaction/index.d.ts.map +1 -1
- package/dist/esm/interaction/index.js +0 -1
- package/dist/esm/interaction/index.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.js +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +11 -1
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/package.json +6 -6
- package/src/action/protocols.ts +68 -2
- package/src/action/request/Read.ts +2 -2
- package/src/action/response/ReadResult.ts +8 -1
- package/src/action/server/AttributeResponse.ts +145 -118
- package/src/action/server/AttributeSubscriptionResponse.ts +90 -0
- package/src/action/server/DataResponse.ts +70 -0
- package/src/action/server/EventResponse.ts +381 -0
- package/src/action/server/ServerInteraction.ts +18 -4
- package/src/action/server/index.ts +3 -0
- package/src/events/OccurrenceManager.ts +126 -100
- package/src/interaction/InteractionMessenger.ts +93 -8
- package/src/interaction/index.ts +0 -1
- package/src/peer/ControllerCommissioningFlow.ts +1 -1
- package/src/protocol/MessageExchange.ts +13 -1
- package/dist/cjs/interaction/ServerSubscription.d.ts +0 -116
- package/dist/cjs/interaction/ServerSubscription.d.ts.map +0 -1
- package/dist/cjs/interaction/ServerSubscription.js +0 -778
- package/dist/cjs/interaction/ServerSubscription.js.map +0 -6
- package/dist/esm/interaction/ServerSubscription.d.ts +0 -116
- package/dist/esm/interaction/ServerSubscription.d.ts.map +0 -1
- package/dist/esm/interaction/ServerSubscription.js +0 -778
- package/dist/esm/interaction/ServerSubscription.js.map +0 -6
- package/src/interaction/ServerSubscription.ts +0 -1038
|
@@ -9,20 +9,14 @@ import {
|
|
|
9
9
|
Construction,
|
|
10
10
|
Diagnostic,
|
|
11
11
|
ImplementationError,
|
|
12
|
+
InternalError,
|
|
12
13
|
isObject,
|
|
13
14
|
Logger,
|
|
14
15
|
MatterAggregateError,
|
|
15
16
|
MaybePromise,
|
|
17
|
+
Observable,
|
|
16
18
|
} from "#general";
|
|
17
|
-
import {
|
|
18
|
-
EventNumber,
|
|
19
|
-
EventPriority,
|
|
20
|
-
FabricIndex,
|
|
21
|
-
resolveEventName,
|
|
22
|
-
TlvEventFilter,
|
|
23
|
-
TlvEventPath,
|
|
24
|
-
TypeFromSchema,
|
|
25
|
-
} from "#types";
|
|
19
|
+
import { EventNumber, FabricIndex, resolveEventName, TlvEventFilter, TlvEventPath, TypeFromSchema } from "#types";
|
|
26
20
|
import { EventStore, OccurrenceSummary } from "./EventStore.js";
|
|
27
21
|
import { NumberedOccurrence, Occurrence } from "./Occurrence.js";
|
|
28
22
|
|
|
@@ -50,14 +44,12 @@ export class OccurrenceManager {
|
|
|
50
44
|
#storedEventCount = 0;
|
|
51
45
|
#bufferConfig: OccurrenceManager.BufferConfig;
|
|
52
46
|
#cull?: Promise<void>;
|
|
47
|
+
#iteratingValuesInProgress = false;
|
|
48
|
+
#added = new Observable<[occurrence: NumberedOccurrence]>();
|
|
53
49
|
|
|
54
50
|
// As we don't (yet) have storage with secondary indices we currently maintain indices in memory regardless of
|
|
55
51
|
// whether underlying store is volatile
|
|
56
|
-
readonly #occurrences =
|
|
57
|
-
[EventPriority.Critical]: new Array<OccurrenceSummary>(),
|
|
58
|
-
[EventPriority.Info]: new Array<OccurrenceSummary>(),
|
|
59
|
-
[EventPriority.Debug]: new Array<OccurrenceSummary>(),
|
|
60
|
-
};
|
|
52
|
+
readonly #occurrences = new Array<OccurrenceSummary>();
|
|
61
53
|
|
|
62
54
|
#construction: Construction<OccurrenceManager>;
|
|
63
55
|
|
|
@@ -82,70 +74,105 @@ export class OccurrenceManager {
|
|
|
82
74
|
);
|
|
83
75
|
}
|
|
84
76
|
|
|
85
|
-
const totalPriorityAllowance = Object.values(bufferConfig.minPriorityEventAllowance).reduce(
|
|
86
|
-
(sum, value) => sum + value,
|
|
87
|
-
0,
|
|
88
|
-
);
|
|
89
|
-
if (totalPriorityAllowance > minEventAllowance) {
|
|
90
|
-
throw new ImplementationError(
|
|
91
|
-
`Total priority allowance ${totalPriorityAllowance} is greater than minimum allowance of ${minEventAllowance}`,
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
77
|
this.#store = store;
|
|
96
78
|
this.#bufferConfig = bufferConfig;
|
|
97
79
|
|
|
98
80
|
this.#construction = Construction(this, () => {
|
|
99
81
|
return MaybePromise.then(this.#store.load(), index => {
|
|
100
82
|
this.#storedEventCount = index.length;
|
|
101
|
-
|
|
102
|
-
|
|
83
|
+
// To be sure, sort the entries by number
|
|
84
|
+
index.sort(
|
|
85
|
+
// sort that way because Bigint & Number mix
|
|
86
|
+
({ number: numberA }, { number: numberB }) => (numberA < numberB ? -1 : numberA > numberB ? 1 : 0),
|
|
87
|
+
);
|
|
88
|
+
this.#occurrences.push(...index);
|
|
89
|
+
if (this.#occurrences.length > this.#bufferConfig.minEventAllowance) {
|
|
90
|
+
this.#startCull();
|
|
103
91
|
}
|
|
104
92
|
});
|
|
105
93
|
});
|
|
106
94
|
}
|
|
107
95
|
|
|
96
|
+
get added() {
|
|
97
|
+
return this.#added;
|
|
98
|
+
}
|
|
99
|
+
|
|
108
100
|
async clear() {
|
|
109
101
|
await this.construction;
|
|
110
102
|
await this.#store.clear();
|
|
111
103
|
this.#storedEventCount = 0;
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
this.#occurrences.length = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Find the index of the first event number in the list that is greater than or equal to eventMin to optimize
|
|
109
|
+
* searching.
|
|
110
|
+
*/
|
|
111
|
+
#findMinEventNumberIndex(eventMin: EventNumber) {
|
|
112
|
+
// if the list is empty or the eventMin is less than the last event number, no entry is relevant
|
|
113
|
+
|
|
114
|
+
if (this.#occurrences.length === 0 || eventMin > this.#occurrences[this.#occurrences.length - 1].number) {
|
|
115
|
+
return -1;
|
|
116
|
+
}
|
|
117
|
+
if (eventMin <= this.#occurrences[0].number) {
|
|
118
|
+
return 0; // The first event number is greater than or equal to eventMin, so all entries are relevant
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let low = this.#occurrences.length - 1;
|
|
122
|
+
let high = low;
|
|
123
|
+
let step = 1;
|
|
124
|
+
|
|
125
|
+
// Because it is more likely that events we want are in the upper ranges we first fine a starting point from there
|
|
126
|
+
while (low > 0 && this.#occurrences[low].number >= eventMin) {
|
|
127
|
+
high = low;
|
|
128
|
+
low = Math.max(0, low - step);
|
|
129
|
+
step *= 2; // increase the step size to skip more entries
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
while (low <= high) {
|
|
133
|
+
const mid = Math.floor((low + high) / 2);
|
|
134
|
+
if (this.#occurrences[mid].number < eventMin) {
|
|
135
|
+
low = mid + 1;
|
|
136
|
+
} else {
|
|
137
|
+
high = mid - 1;
|
|
138
|
+
}
|
|
114
139
|
}
|
|
140
|
+
|
|
141
|
+
return low; // The index of the first event number that is greater than or equal to eventMin
|
|
115
142
|
}
|
|
116
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Query the event store for events matching the given path and filters.
|
|
146
|
+
* @deprecated
|
|
147
|
+
*/
|
|
117
148
|
query(
|
|
118
149
|
eventPath: TypeFromSchema<typeof TlvEventPath>,
|
|
119
150
|
filters?: TypeFromSchema<typeof TlvEventFilter>[],
|
|
120
151
|
filterForFabricIndex?: FabricIndex,
|
|
121
152
|
): MaybePromise<NumberedOccurrence[]> {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
filters.some(
|
|
126
|
-
filter => filter.eventMin !== undefined && event.number >= EventNumber(filter.eventMin),
|
|
127
|
-
)
|
|
128
|
-
: undefined; // TODO - filter on node ID too?
|
|
129
|
-
|
|
153
|
+
if (filters !== undefined && filters.length > 1) {
|
|
154
|
+
throw new InternalError("Multiple filters not supported");
|
|
155
|
+
}
|
|
130
156
|
// Search the index and load applicable events
|
|
157
|
+
const startIndex = filters?.length ? this.#findMinEventNumberIndex(EventNumber(filters[0].eventMin)) : 0;
|
|
158
|
+
if (startIndex === -1) {
|
|
159
|
+
return []; // No entry matches the filter
|
|
160
|
+
}
|
|
161
|
+
|
|
131
162
|
let isAsyncLoad = false;
|
|
132
|
-
const occurrences = new Array<MaybePromise<NumberedOccurrence>>();
|
|
133
163
|
const { endpointId, clusterId, eventId } = eventPath;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
isAsyncLoad = true;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
164
|
+
const occurrences = new Array<MaybePromise<NumberedOccurrence>>();
|
|
165
|
+
for (let i = startIndex; i < this.#occurrences.length; i++) {
|
|
166
|
+
const entry = this.#occurrences[i];
|
|
167
|
+
if (endpointId === entry.endpointId && clusterId === entry.clusterId && eventId === entry.eventId) {
|
|
168
|
+
let occurrence = this.#store.get(entry.number) as MaybePromise<NumberedOccurrence>;
|
|
169
|
+
occurrence = MaybePromise.then(occurrence, occurrence => {
|
|
170
|
+
occurrence.number = entry.number;
|
|
171
|
+
return occurrence;
|
|
172
|
+
});
|
|
173
|
+
occurrences.push(occurrence);
|
|
174
|
+
if (MaybePromise.is(occurrence)) {
|
|
175
|
+
isAsyncLoad = true;
|
|
149
176
|
}
|
|
150
177
|
}
|
|
151
178
|
}
|
|
@@ -205,6 +232,40 @@ export class OccurrenceManager {
|
|
|
205
232
|
return result;
|
|
206
233
|
}
|
|
207
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Return an iterator over all occurrences in the store that are bigger or equal to the minimum eventNumber,
|
|
237
|
+
* if provided.
|
|
238
|
+
*/
|
|
239
|
+
async *get(eventMin?: EventNumber) {
|
|
240
|
+
if (this.#cull) {
|
|
241
|
+
await this.#cull;
|
|
242
|
+
}
|
|
243
|
+
const startIndex = eventMin === undefined ? 0 : this.#findMinEventNumberIndex(eventMin);
|
|
244
|
+
if (startIndex === -1) {
|
|
245
|
+
return; // No entry matches the filter
|
|
246
|
+
}
|
|
247
|
+
this.#iteratingValuesInProgress = true;
|
|
248
|
+
try {
|
|
249
|
+
for (let i = startIndex; i < this.#occurrences.length; i++) {
|
|
250
|
+
const eventNumber = this.#occurrences[i].number;
|
|
251
|
+
const occurrence = this.#store.get(eventNumber);
|
|
252
|
+
if (MaybePromise.is(occurrence)) {
|
|
253
|
+
yield {
|
|
254
|
+
...(await occurrence),
|
|
255
|
+
number: eventNumber,
|
|
256
|
+
};
|
|
257
|
+
} else {
|
|
258
|
+
yield {
|
|
259
|
+
...occurrence,
|
|
260
|
+
number: eventNumber,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
} finally {
|
|
265
|
+
this.#iteratingValuesInProgress = false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
208
269
|
close(): MaybePromise<void> {
|
|
209
270
|
MaybePromise.then(this.#cull, () => this.#store.close());
|
|
210
271
|
}
|
|
@@ -212,20 +273,22 @@ export class OccurrenceManager {
|
|
|
212
273
|
add(occurrence: Occurrence): MaybePromise<NumberedOccurrence> {
|
|
213
274
|
return MaybePromise.then(this.#store.add(occurrence), entry => {
|
|
214
275
|
logger.debug(`Recorded event #${entry.number}: ${Diagnostic.json(occurrence)}`);
|
|
215
|
-
this.#occurrences
|
|
276
|
+
this.#occurrences.push(entry);
|
|
216
277
|
this.#storedEventCount++;
|
|
217
278
|
if (this.#storedEventCount > this.#bufferConfig.maxEventAllowance) {
|
|
218
279
|
this.#startCull();
|
|
219
280
|
}
|
|
220
|
-
|
|
281
|
+
const numberedOccurrence = {
|
|
221
282
|
number: entry.number,
|
|
222
283
|
...occurrence,
|
|
223
284
|
};
|
|
285
|
+
this.#added.emit(numberedOccurrence);
|
|
286
|
+
return numberedOccurrence;
|
|
224
287
|
});
|
|
225
288
|
}
|
|
226
289
|
|
|
227
290
|
#startCull() {
|
|
228
|
-
if (this.#cull) {
|
|
291
|
+
if (this.#cull || this.#iteratingValuesInProgress) {
|
|
229
292
|
return;
|
|
230
293
|
}
|
|
231
294
|
const cull = this.#dropOldOccurrences();
|
|
@@ -235,7 +298,7 @@ export class OccurrenceManager {
|
|
|
235
298
|
}
|
|
236
299
|
|
|
237
300
|
#dropOldOccurrences() {
|
|
238
|
-
|
|
301
|
+
const count = this.#storedEventCount - this.#bufferConfig.minEventAllowance;
|
|
239
302
|
if (count <= 0) {
|
|
240
303
|
return;
|
|
241
304
|
}
|
|
@@ -244,31 +307,15 @@ export class OccurrenceManager {
|
|
|
244
307
|
|
|
245
308
|
const asyncDrops = Array<PromiseLike<void>>();
|
|
246
309
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
count--;
|
|
254
|
-
countThisPriority++;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
totalCulled += countThisPriority;
|
|
258
|
-
for (const entry of occurrences.splice(0, countThisPriority)) {
|
|
259
|
-
const drop = MaybePromise.catch(this.#store.delete(entry.number), error =>
|
|
260
|
-
logger.warn(`Error dropping occurrence #${entry}: ${error}`),
|
|
261
|
-
);
|
|
262
|
-
if (MaybePromise.is(drop)) {
|
|
263
|
-
asyncDrops.push(drop);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (!count) {
|
|
268
|
-
break;
|
|
310
|
+
for (const entry of this.#occurrences.splice(0, count)) {
|
|
311
|
+
const drop = MaybePromise.catch(this.#store.delete(entry.number), error =>
|
|
312
|
+
logger.warn(`Error dropping occurrence #${entry}: ${error}`),
|
|
313
|
+
);
|
|
314
|
+
if (MaybePromise.is(drop)) {
|
|
315
|
+
asyncDrops.push(drop);
|
|
269
316
|
}
|
|
270
317
|
}
|
|
271
|
-
this.#storedEventCount
|
|
318
|
+
this.#storedEventCount = this.#occurrences.length;
|
|
272
319
|
|
|
273
320
|
if (asyncDrops.length) {
|
|
274
321
|
return MatterAggregateError.allSettled(asyncDrops, "Error dropping occurrences")
|
|
@@ -278,12 +325,6 @@ export class OccurrenceManager {
|
|
|
278
325
|
}
|
|
279
326
|
}
|
|
280
327
|
|
|
281
|
-
const PriorityNames = {
|
|
282
|
-
[EventPriority.Critical]: "critical",
|
|
283
|
-
[EventPriority.Info]: "info",
|
|
284
|
-
[EventPriority.Debug]: "debug",
|
|
285
|
-
} as const;
|
|
286
|
-
|
|
287
328
|
export namespace OccurrenceManager {
|
|
288
329
|
/**
|
|
289
330
|
* Buffer management configuration. Controls
|
|
@@ -301,25 +342,10 @@ export namespace OccurrenceManager {
|
|
|
301
342
|
* {@link minimumEventAllowance}.
|
|
302
343
|
*/
|
|
303
344
|
maxEventAllowance: number;
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Minimum allowances by priority. This ensures a minimum number of events for each priority avoid LRU
|
|
307
|
-
* harvesting.
|
|
308
|
-
*/
|
|
309
|
-
minPriorityEventAllowance: {
|
|
310
|
-
critical: number;
|
|
311
|
-
info: number;
|
|
312
|
-
debug: number;
|
|
313
|
-
};
|
|
314
345
|
}
|
|
315
346
|
|
|
316
347
|
export const DefaultBufferConfig: BufferConfig = {
|
|
317
348
|
minEventAllowance: 10_000,
|
|
318
349
|
maxEventAllowance: 11_000,
|
|
319
|
-
minPriorityEventAllowance: {
|
|
320
|
-
critical: 2_000,
|
|
321
|
-
info: 2_000,
|
|
322
|
-
debug: 2_000,
|
|
323
|
-
},
|
|
324
350
|
};
|
|
325
351
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { ReadResult } from "#action/index.js";
|
|
7
8
|
import {
|
|
8
9
|
Diagnostic,
|
|
9
10
|
InternalError,
|
|
@@ -244,7 +245,11 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
244
245
|
);
|
|
245
246
|
|
|
246
247
|
// This potentially sends multiple DataReport Messages
|
|
247
|
-
await this.sendDataReport(
|
|
248
|
+
await this.sendDataReport({
|
|
249
|
+
baseDataReport: dataReport,
|
|
250
|
+
forFabricFilteredRead: readRequest.isFabricFiltered,
|
|
251
|
+
payload,
|
|
252
|
+
});
|
|
248
253
|
break;
|
|
249
254
|
}
|
|
250
255
|
case MessageType.WriteRequest: {
|
|
@@ -306,12 +311,20 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
306
311
|
* Handle a DataReport with a Payload Iterator for a DataReport to send, split them into multiple DataReport
|
|
307
312
|
* messages and send them out based on the size.
|
|
308
313
|
*/
|
|
309
|
-
async sendDataReport(
|
|
310
|
-
baseDataReport: BaseDataReport
|
|
311
|
-
forFabricFilteredRead: boolean
|
|
312
|
-
payload?: DataReportPayloadIterator
|
|
313
|
-
waitForAck
|
|
314
|
-
|
|
314
|
+
async sendDataReport(options: {
|
|
315
|
+
baseDataReport: BaseDataReport;
|
|
316
|
+
forFabricFilteredRead: boolean;
|
|
317
|
+
payload?: DataReportPayloadIterator;
|
|
318
|
+
waitForAck?: boolean;
|
|
319
|
+
suppressEmptyReport?: boolean;
|
|
320
|
+
}) {
|
|
321
|
+
const {
|
|
322
|
+
baseDataReport,
|
|
323
|
+
forFabricFilteredRead,
|
|
324
|
+
payload,
|
|
325
|
+
waitForAck = true,
|
|
326
|
+
suppressEmptyReport = false,
|
|
327
|
+
} = options;
|
|
315
328
|
const { subscriptionId, suppressResponse, interactionModelRevision } = baseDataReport;
|
|
316
329
|
|
|
317
330
|
const dataReport: TypeFromSchema<typeof TlvDataReportForSend> = {
|
|
@@ -622,7 +635,9 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
622
635
|
}
|
|
623
636
|
}
|
|
624
637
|
|
|
625
|
-
|
|
638
|
+
if (!suppressEmptyReport || dataReport.attributeReports?.length || dataReport.eventReports?.length) {
|
|
639
|
+
await this.sendDataReportMessage(dataReport, waitForAck);
|
|
640
|
+
}
|
|
626
641
|
}
|
|
627
642
|
|
|
628
643
|
async sendDataReportMessage(dataReport: TypeFromSchema<typeof TlvDataReportForSend>, waitForAck = true) {
|
|
@@ -673,6 +688,76 @@ export class InteractionServerMessenger extends InteractionMessenger {
|
|
|
673
688
|
await this.waitForSuccess("DataReport", { timeoutMs: waitForAck ? undefined : 500 });
|
|
674
689
|
}
|
|
675
690
|
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Convert a server interaction report to a DataReport entry
|
|
694
|
+
* TODO remove when anything is migrated completely
|
|
695
|
+
*/
|
|
696
|
+
static convertServerInteractionReport(report: ReadResult.Report) {
|
|
697
|
+
switch (report.kind) {
|
|
698
|
+
case "attr-value": {
|
|
699
|
+
const { path, value: payload, version: dataVersion, tlv: schema } = report;
|
|
700
|
+
if (schema === undefined) {
|
|
701
|
+
throw new InternalError(`Attribute ${path.clusterId}/${path.attributeId} not found`);
|
|
702
|
+
}
|
|
703
|
+
const data: AttributeReportPayload = {
|
|
704
|
+
attributeData: {
|
|
705
|
+
path,
|
|
706
|
+
payload,
|
|
707
|
+
schema,
|
|
708
|
+
dataVersion,
|
|
709
|
+
},
|
|
710
|
+
hasFabricSensitiveData: true, // With this we disable the validation for missing data in encoding, we trust behavior logic
|
|
711
|
+
};
|
|
712
|
+
return data;
|
|
713
|
+
}
|
|
714
|
+
case "attr-status": {
|
|
715
|
+
const { path, status } = report;
|
|
716
|
+
const statusReport: AttributeReportPayload = {
|
|
717
|
+
attributeStatus: {
|
|
718
|
+
path,
|
|
719
|
+
status: { status },
|
|
720
|
+
},
|
|
721
|
+
hasFabricSensitiveData: false,
|
|
722
|
+
};
|
|
723
|
+
return statusReport;
|
|
724
|
+
}
|
|
725
|
+
case "event-value": {
|
|
726
|
+
const {
|
|
727
|
+
path,
|
|
728
|
+
value: payload,
|
|
729
|
+
number: eventNumber,
|
|
730
|
+
priority,
|
|
731
|
+
timestamp: epochTimestamp,
|
|
732
|
+
tlv: schema,
|
|
733
|
+
} = report;
|
|
734
|
+
const data: EventReportPayload = {
|
|
735
|
+
eventData: {
|
|
736
|
+
path,
|
|
737
|
+
eventNumber,
|
|
738
|
+
priority,
|
|
739
|
+
epochTimestamp,
|
|
740
|
+
payload,
|
|
741
|
+
schema,
|
|
742
|
+
},
|
|
743
|
+
hasFabricSensitiveData: true, // There are no Fabric sensitive events as of now. If ever added sanitizing needs to be added
|
|
744
|
+
};
|
|
745
|
+
return data;
|
|
746
|
+
}
|
|
747
|
+
case "event-status": {
|
|
748
|
+
const { path, status } = report;
|
|
749
|
+
const statusReport: EventReportPayload = {
|
|
750
|
+
eventStatus: {
|
|
751
|
+
path,
|
|
752
|
+
status: { status },
|
|
753
|
+
},
|
|
754
|
+
hasFabricSensitiveData: false,
|
|
755
|
+
};
|
|
756
|
+
return statusReport;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
throw new InternalError(`Unknown report type: ${report.kind}`);
|
|
760
|
+
}
|
|
676
761
|
}
|
|
677
762
|
|
|
678
763
|
export class IncomingInteractionClientMessenger extends InteractionMessenger {
|
package/src/interaction/index.ts
CHANGED
|
@@ -11,6 +11,5 @@ export * from "./EventDataDecoder.js";
|
|
|
11
11
|
export * from "./InteractionClient.js";
|
|
12
12
|
export * from "./InteractionEndpointStructure.js";
|
|
13
13
|
export * from "./InteractionMessenger.js";
|
|
14
|
-
export * from "./ServerSubscription.js";
|
|
15
14
|
export * from "./Subscription.js";
|
|
16
15
|
export * from "./SubscriptionClient.js";
|
|
@@ -250,7 +250,7 @@ export class ControllerCommissioningFlow {
|
|
|
250
250
|
}
|
|
251
251
|
} catch (error) {
|
|
252
252
|
if (error instanceof RecoverableCommissioningError) {
|
|
253
|
-
logger.
|
|
253
|
+
logger.warn(
|
|
254
254
|
`Commissioning step ${step.stepNumber}.${step.subStepNumber}: ${step.name} failed with recoverable error: ${error.message} ... Continuing with process`,
|
|
255
255
|
);
|
|
256
256
|
} else if (error instanceof CommissioningError || error instanceof StatusResponseError) {
|
|
@@ -186,6 +186,7 @@ export class MessageExchange {
|
|
|
186
186
|
#closeTimer: Timer | undefined;
|
|
187
187
|
#isClosing = false;
|
|
188
188
|
#timedInteractionTimer: Timer | undefined;
|
|
189
|
+
#used: boolean;
|
|
189
190
|
|
|
190
191
|
readonly #peerSessionId: number;
|
|
191
192
|
readonly #nodeId: NodeId | undefined;
|
|
@@ -221,6 +222,7 @@ export class MessageExchange {
|
|
|
221
222
|
|
|
222
223
|
// When the session is supporting MRP and the channel is not reliable, use MRP handling
|
|
223
224
|
this.#useMRP = session.supportsMRP && !channel.isReliable;
|
|
225
|
+
this.#used = !isInitiator; // If we are the initiator then exchange was not used yet, so track it
|
|
224
226
|
|
|
225
227
|
logger.debug(
|
|
226
228
|
"New exchange",
|
|
@@ -390,6 +392,7 @@ export class MessageExchange {
|
|
|
390
392
|
if (this.#sentMessageToAck !== undefined && messageType !== SecureMessageType.StandaloneAck)
|
|
391
393
|
throw new MatterFlowError("The previous message has not been acked yet, cannot send a new message.");
|
|
392
394
|
|
|
395
|
+
this.#used = true;
|
|
393
396
|
this.session.notifyActivity(false);
|
|
394
397
|
|
|
395
398
|
let ackedMessageId = includeAcknowledgeMessageId;
|
|
@@ -660,6 +663,12 @@ export class MessageExchange {
|
|
|
660
663
|
// close was already called, so let retries happen because close not forced
|
|
661
664
|
return;
|
|
662
665
|
}
|
|
666
|
+
if (!this.#used) {
|
|
667
|
+
// The exchange was never in use, so we can close it directly
|
|
668
|
+
// If we see that in the wild we should fix the reasons
|
|
669
|
+
logger.info(`Exchange ${this.session.name} / ${this.#exchangeId} was never used, closing directly`);
|
|
670
|
+
return this.#close();
|
|
671
|
+
}
|
|
663
672
|
this.#isClosing = true;
|
|
664
673
|
|
|
665
674
|
if (this.#receivedMessageToAck !== undefined) {
|
|
@@ -669,7 +678,10 @@ export class MessageExchange {
|
|
|
669
678
|
try {
|
|
670
679
|
await this.sendStandaloneAckForMessage(messageToAck);
|
|
671
680
|
} catch (error) {
|
|
672
|
-
logger.error(
|
|
681
|
+
logger.error(
|
|
682
|
+
`An error happened when closing the exchange ${this.session.name} / ${this.#exchangeId}`,
|
|
683
|
+
error,
|
|
684
|
+
);
|
|
673
685
|
}
|
|
674
686
|
if (force) {
|
|
675
687
|
// We have sent the Ack, so close here, no retries because close is forced
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
-
*/
|
|
6
|
-
import { NumberedOccurrence } from "#events/Occurrence.js";
|
|
7
|
-
import { MaybePromise } from "#general";
|
|
8
|
-
import { PeerAddress } from "#peer/PeerAddress.js";
|
|
9
|
-
import type { MessageExchange } from "#protocol/MessageExchange.js";
|
|
10
|
-
import { SecureSession } from "#session/SecureSession.js";
|
|
11
|
-
import { TlvEventFilter, TlvSchema, TypeFromSchema } from "#types";
|
|
12
|
-
import { AnyAttributeServer } from "../cluster/server/AttributeServer.js";
|
|
13
|
-
import { AnyEventServer } from "../cluster/server/EventServer.js";
|
|
14
|
-
import { AttributePath, EventPath, InteractionEndpointStructure } from "./InteractionEndpointStructure.js";
|
|
15
|
-
import { InteractionServerMessenger } from "./InteractionMessenger.js";
|
|
16
|
-
import { Subscription, SubscriptionCriteria } from "./Subscription.js";
|
|
17
|
-
export declare const MAX_INTERVAL_PUBLISHER_LIMIT_S: number; /** 1 hour */
|
|
18
|
-
export declare const INTERNAL_INTERVAL_PUBLISHER_LIMIT_S: number; /** 3 min */
|
|
19
|
-
export declare const MIN_INTERVAL_S = 2;
|
|
20
|
-
export declare const DEFAULT_RANDOMIZATION_WINDOW_S = 10;
|
|
21
|
-
/**
|
|
22
|
-
* Server options that control subscription handling.
|
|
23
|
-
*/
|
|
24
|
-
export interface ServerSubscriptionConfig {
|
|
25
|
-
/**
|
|
26
|
-
* Optional maximum subscription interval to use for sending subscription reports. It will be used if not too
|
|
27
|
-
* low and inside the range requested by the connected controller.
|
|
28
|
-
*/
|
|
29
|
-
maxIntervalSeconds: number;
|
|
30
|
-
/**
|
|
31
|
-
* Optional minimum subscription interval to use for sending subscription reports. It will be used when other
|
|
32
|
-
* calculated values are smaller than it. Use this to make sure your device hardware can handle the load and to
|
|
33
|
-
* set limits.
|
|
34
|
-
*/
|
|
35
|
-
minIntervalSeconds: number;
|
|
36
|
-
/**
|
|
37
|
-
* Optional subscription randomization window to use for sending subscription reports. This specifies a window
|
|
38
|
-
* in seconds from which a random part is added to the calculated maximum interval to make sure that devices
|
|
39
|
-
* that get powered on in parallel not all send at the same timepoint.
|
|
40
|
-
*/
|
|
41
|
-
randomizationWindowSeconds: number;
|
|
42
|
-
}
|
|
43
|
-
export declare namespace ServerSubscriptionConfig {
|
|
44
|
-
/**
|
|
45
|
-
* Validate options and set defaults.
|
|
46
|
-
*
|
|
47
|
-
* @returns the resulting options
|
|
48
|
-
*/
|
|
49
|
-
function of(options?: Partial<ServerSubscriptionConfig>): {
|
|
50
|
-
maxIntervalSeconds: number;
|
|
51
|
-
minIntervalSeconds: number;
|
|
52
|
-
randomizationWindowSeconds: number;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Interface between {@link ServerSubscription} and the local Matter environment.
|
|
57
|
-
*/
|
|
58
|
-
export interface ServerSubscriptionContext {
|
|
59
|
-
session: SecureSession;
|
|
60
|
-
structure: InteractionEndpointStructure;
|
|
61
|
-
readAttribute(path: AttributePath, attribute: AnyAttributeServer<unknown>, offline?: boolean): {
|
|
62
|
-
version: number;
|
|
63
|
-
value: unknown;
|
|
64
|
-
};
|
|
65
|
-
readEndpointAttributesForSubscription(attributes: {
|
|
66
|
-
path: AttributePath;
|
|
67
|
-
attribute: AnyAttributeServer<unknown>;
|
|
68
|
-
offline?: boolean;
|
|
69
|
-
}[]): {
|
|
70
|
-
path: AttributePath;
|
|
71
|
-
attribute: AnyAttributeServer<unknown>;
|
|
72
|
-
version: number;
|
|
73
|
-
value: unknown;
|
|
74
|
-
}[];
|
|
75
|
-
readEvent(path: EventPath, event: AnyEventServer<any, any>, eventFilters: TypeFromSchema<typeof TlvEventFilter>[] | undefined): Promise<NumberedOccurrence[]>;
|
|
76
|
-
initiateExchange(address: PeerAddress, protocolId: number): MessageExchange;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Implements the server side of a single subscription.
|
|
80
|
-
*/
|
|
81
|
-
export declare class ServerSubscription extends Subscription {
|
|
82
|
-
#private;
|
|
83
|
-
constructor(options: {
|
|
84
|
-
id: number;
|
|
85
|
-
context: ServerSubscriptionContext;
|
|
86
|
-
criteria: SubscriptionCriteria;
|
|
87
|
-
minIntervalFloorSeconds: number;
|
|
88
|
-
maxIntervalCeilingSeconds: number;
|
|
89
|
-
subscriptionOptions: ServerSubscriptionConfig;
|
|
90
|
-
useAsMaxInterval?: number;
|
|
91
|
-
useAsSendInterval?: number;
|
|
92
|
-
});
|
|
93
|
-
unregisterAttributeListeners(list: Array<string>): void;
|
|
94
|
-
unregisterEventListeners(list: Array<string>): void;
|
|
95
|
-
/**
|
|
96
|
-
* Update the session after an endpoint structure change. The method will initialize all missing new attributes and
|
|
97
|
-
* events and will remove listeners no longer needed.
|
|
98
|
-
* Newly added attributes are then treated as "changed values" and will be sent as subscription data update to the
|
|
99
|
-
* controller. The data of newly added events are not sent automatically.
|
|
100
|
-
*/
|
|
101
|
-
updateSubscription(): Promise<void>;
|
|
102
|
-
get sendInterval(): number;
|
|
103
|
-
get minIntervalFloorSeconds(): number;
|
|
104
|
-
get maxIntervalCeilingSeconds(): number;
|
|
105
|
-
activate(): void;
|
|
106
|
-
sendInitialReport(messenger: InteractionServerMessenger): Promise<void>;
|
|
107
|
-
attributeChangeListener<T>(path: AttributePath, schema: TlvSchema<T>, version: number, value: T): void;
|
|
108
|
-
attributeChangeHandler<T>(path: AttributePath, schema: TlvSchema<T>, version: number, value: T): MaybePromise<void>;
|
|
109
|
-
eventChangeListener<T>(path: EventPath, schema: TlvSchema<T>, newEvent: NumberedOccurrence): void;
|
|
110
|
-
protected destroy(): Promise<void>;
|
|
111
|
-
/**
|
|
112
|
-
* Closes the subscription and flushes all outstanding data updates if requested.
|
|
113
|
-
*/
|
|
114
|
-
close(graceful?: boolean, cancelledByPeer?: boolean): Promise<void>;
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=ServerSubscription.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ServerSubscription.d.ts","sourceRoot":"","sources":["../../../src/interaction/ServerSubscription.ts"],"names":[],"mappings":"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"}
|