@matter/protocol 0.16.0-alpha.0-20251104-8c3166ea3 → 0.16.0-alpha.0-20251107-6bcb5baf4

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.
Files changed (158) hide show
  1. package/dist/cjs/action/client/ClientInteraction.d.ts +1 -0
  2. package/dist/cjs/action/client/ClientInteraction.d.ts.map +1 -1
  3. package/dist/cjs/action/client/ClientInteraction.js +3 -0
  4. package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
  5. package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js +2 -4
  6. package/dist/cjs/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
  7. package/dist/cjs/advertisement/PairingHintBitmap.d.ts +2 -2
  8. package/dist/cjs/advertisement/PairingHintBitmap.js +1 -1
  9. package/dist/cjs/advertisement/PairingHintBitmap.js.map +1 -1
  10. package/dist/cjs/advertisement/mdns/CommissionableMdnsAdvertisement.d.ts.map +1 -1
  11. package/dist/cjs/advertisement/mdns/CommissionableMdnsAdvertisement.js +22 -4
  12. package/dist/cjs/advertisement/mdns/CommissionableMdnsAdvertisement.js.map +1 -1
  13. package/dist/cjs/certificate/index.d.ts +1 -0
  14. package/dist/cjs/certificate/index.d.ts.map +1 -1
  15. package/dist/cjs/certificate/index.js +1 -0
  16. package/dist/cjs/certificate/index.js.map +1 -1
  17. package/dist/cjs/certificate/kinds/Icac.d.ts +2 -0
  18. package/dist/cjs/certificate/kinds/Icac.d.ts.map +1 -1
  19. package/dist/cjs/certificate/kinds/Icac.js +9 -0
  20. package/dist/cjs/certificate/kinds/Icac.js.map +1 -1
  21. package/dist/cjs/certificate/kinds/Noc.d.ts +2 -0
  22. package/dist/cjs/certificate/kinds/Noc.d.ts.map +1 -1
  23. package/dist/cjs/certificate/kinds/Noc.js +9 -0
  24. package/dist/cjs/certificate/kinds/Noc.js.map +1 -1
  25. package/dist/cjs/certificate/kinds/OperationalBase.d.ts +6 -1
  26. package/dist/cjs/certificate/kinds/OperationalBase.d.ts.map +1 -1
  27. package/dist/cjs/certificate/kinds/OperationalBase.js +14 -0
  28. package/dist/cjs/certificate/kinds/OperationalBase.js.map +1 -1
  29. package/dist/cjs/certificate/kinds/Rcac.d.ts +2 -0
  30. package/dist/cjs/certificate/kinds/Rcac.d.ts.map +1 -1
  31. package/dist/cjs/certificate/kinds/Rcac.js +9 -0
  32. package/dist/cjs/certificate/kinds/Rcac.js.map +1 -1
  33. package/dist/cjs/certificate/kinds/Vvsc.d.ts +29 -0
  34. package/dist/cjs/certificate/kinds/Vvsc.d.ts.map +1 -0
  35. package/dist/cjs/certificate/kinds/Vvsc.js +79 -0
  36. package/dist/cjs/certificate/kinds/Vvsc.js.map +6 -0
  37. package/dist/cjs/certificate/kinds/X509Base.d.ts +10 -3
  38. package/dist/cjs/certificate/kinds/X509Base.d.ts.map +1 -1
  39. package/dist/cjs/certificate/kinds/X509Base.js +304 -13
  40. package/dist/cjs/certificate/kinds/X509Base.js.map +2 -2
  41. package/dist/cjs/certificate/kinds/definitions/asn.d.ts +15 -0
  42. package/dist/cjs/certificate/kinds/definitions/asn.d.ts.map +1 -1
  43. package/dist/cjs/certificate/kinds/definitions/asn.js +33 -21
  44. package/dist/cjs/certificate/kinds/definitions/asn.js.map +2 -2
  45. package/dist/cjs/certificate/kinds/definitions/operational.d.ts +121 -12
  46. package/dist/cjs/certificate/kinds/definitions/operational.d.ts.map +1 -1
  47. package/dist/cjs/certificate/kinds/definitions/operational.js +8 -2
  48. package/dist/cjs/certificate/kinds/definitions/operational.js.map +1 -1
  49. package/dist/cjs/certificate/kinds/index.d.ts +1 -0
  50. package/dist/cjs/certificate/kinds/index.d.ts.map +1 -1
  51. package/dist/cjs/certificate/kinds/index.js +1 -0
  52. package/dist/cjs/certificate/kinds/index.js.map +1 -1
  53. package/dist/cjs/fabric/Fabric.d.ts +6 -1
  54. package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
  55. package/dist/cjs/fabric/Fabric.js +53 -2
  56. package/dist/cjs/fabric/Fabric.js.map +1 -1
  57. package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
  58. package/dist/cjs/fabric/FabricManager.js +24 -9
  59. package/dist/cjs/fabric/FabricManager.js.map +1 -1
  60. package/dist/cjs/mdns/MdnsConsts.d.ts +1 -1
  61. package/dist/cjs/mdns/MdnsConsts.d.ts.map +1 -1
  62. package/dist/cjs/mdns/MdnsConsts.js +1 -1
  63. package/dist/cjs/peer/PhysicalDeviceProperties.d.ts +11 -7
  64. package/dist/cjs/peer/PhysicalDeviceProperties.d.ts.map +1 -1
  65. package/dist/cjs/peer/PhysicalDeviceProperties.js +34 -25
  66. package/dist/cjs/peer/PhysicalDeviceProperties.js.map +1 -1
  67. package/dist/cjs/protocol/DeviceAdvertiser.d.ts.map +1 -1
  68. package/dist/cjs/protocol/DeviceAdvertiser.js +17 -0
  69. package/dist/cjs/protocol/DeviceAdvertiser.js.map +1 -1
  70. package/dist/esm/action/client/ClientInteraction.d.ts +1 -0
  71. package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
  72. package/dist/esm/action/client/ClientInteraction.js +3 -0
  73. package/dist/esm/action/client/ClientInteraction.js.map +1 -1
  74. package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js +2 -4
  75. package/dist/esm/action/client/subscription/ClientSubscriptionHandler.js.map +1 -1
  76. package/dist/esm/advertisement/PairingHintBitmap.d.ts +2 -2
  77. package/dist/esm/advertisement/PairingHintBitmap.js +1 -1
  78. package/dist/esm/advertisement/PairingHintBitmap.js.map +1 -1
  79. package/dist/esm/advertisement/mdns/CommissionableMdnsAdvertisement.d.ts.map +1 -1
  80. package/dist/esm/advertisement/mdns/CommissionableMdnsAdvertisement.js +22 -4
  81. package/dist/esm/advertisement/mdns/CommissionableMdnsAdvertisement.js.map +1 -1
  82. package/dist/esm/certificate/index.d.ts +1 -0
  83. package/dist/esm/certificate/index.d.ts.map +1 -1
  84. package/dist/esm/certificate/index.js +1 -0
  85. package/dist/esm/certificate/index.js.map +1 -1
  86. package/dist/esm/certificate/kinds/Icac.d.ts +2 -0
  87. package/dist/esm/certificate/kinds/Icac.d.ts.map +1 -1
  88. package/dist/esm/certificate/kinds/Icac.js +9 -0
  89. package/dist/esm/certificate/kinds/Icac.js.map +1 -1
  90. package/dist/esm/certificate/kinds/Noc.d.ts +2 -0
  91. package/dist/esm/certificate/kinds/Noc.d.ts.map +1 -1
  92. package/dist/esm/certificate/kinds/Noc.js +9 -0
  93. package/dist/esm/certificate/kinds/Noc.js.map +1 -1
  94. package/dist/esm/certificate/kinds/OperationalBase.d.ts +6 -1
  95. package/dist/esm/certificate/kinds/OperationalBase.d.ts.map +1 -1
  96. package/dist/esm/certificate/kinds/OperationalBase.js +16 -2
  97. package/dist/esm/certificate/kinds/OperationalBase.js.map +1 -1
  98. package/dist/esm/certificate/kinds/Rcac.d.ts +2 -0
  99. package/dist/esm/certificate/kinds/Rcac.d.ts.map +1 -1
  100. package/dist/esm/certificate/kinds/Rcac.js +9 -0
  101. package/dist/esm/certificate/kinds/Rcac.js.map +1 -1
  102. package/dist/esm/certificate/kinds/Vvsc.d.ts +29 -0
  103. package/dist/esm/certificate/kinds/Vvsc.d.ts.map +1 -0
  104. package/dist/esm/certificate/kinds/Vvsc.js +59 -0
  105. package/dist/esm/certificate/kinds/Vvsc.js.map +6 -0
  106. package/dist/esm/certificate/kinds/X509Base.d.ts +10 -3
  107. package/dist/esm/certificate/kinds/X509Base.d.ts.map +1 -1
  108. package/dist/esm/certificate/kinds/X509Base.js +308 -14
  109. package/dist/esm/certificate/kinds/X509Base.js.map +2 -2
  110. package/dist/esm/certificate/kinds/definitions/asn.d.ts +15 -0
  111. package/dist/esm/certificate/kinds/definitions/asn.d.ts.map +1 -1
  112. package/dist/esm/certificate/kinds/definitions/asn.js +33 -21
  113. package/dist/esm/certificate/kinds/definitions/asn.js.map +1 -1
  114. package/dist/esm/certificate/kinds/definitions/operational.d.ts +121 -12
  115. package/dist/esm/certificate/kinds/definitions/operational.d.ts.map +1 -1
  116. package/dist/esm/certificate/kinds/definitions/operational.js +8 -2
  117. package/dist/esm/certificate/kinds/definitions/operational.js.map +1 -1
  118. package/dist/esm/certificate/kinds/index.d.ts +1 -0
  119. package/dist/esm/certificate/kinds/index.d.ts.map +1 -1
  120. package/dist/esm/certificate/kinds/index.js +1 -0
  121. package/dist/esm/certificate/kinds/index.js.map +1 -1
  122. package/dist/esm/fabric/Fabric.d.ts +6 -1
  123. package/dist/esm/fabric/Fabric.d.ts.map +1 -1
  124. package/dist/esm/fabric/Fabric.js +54 -3
  125. package/dist/esm/fabric/Fabric.js.map +1 -1
  126. package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
  127. package/dist/esm/fabric/FabricManager.js +25 -9
  128. package/dist/esm/fabric/FabricManager.js.map +1 -1
  129. package/dist/esm/mdns/MdnsConsts.d.ts +1 -1
  130. package/dist/esm/mdns/MdnsConsts.d.ts.map +1 -1
  131. package/dist/esm/mdns/MdnsConsts.js +1 -1
  132. package/dist/esm/peer/PhysicalDeviceProperties.d.ts +11 -7
  133. package/dist/esm/peer/PhysicalDeviceProperties.d.ts.map +1 -1
  134. package/dist/esm/peer/PhysicalDeviceProperties.js +35 -26
  135. package/dist/esm/peer/PhysicalDeviceProperties.js.map +1 -1
  136. package/dist/esm/protocol/DeviceAdvertiser.d.ts.map +1 -1
  137. package/dist/esm/protocol/DeviceAdvertiser.js +17 -0
  138. package/dist/esm/protocol/DeviceAdvertiser.js.map +1 -1
  139. package/package.json +6 -6
  140. package/src/action/client/ClientInteraction.ts +5 -1
  141. package/src/action/client/subscription/ClientSubscriptionHandler.ts +2 -4
  142. package/src/advertisement/PairingHintBitmap.ts +1 -1
  143. package/src/advertisement/mdns/CommissionableMdnsAdvertisement.ts +23 -6
  144. package/src/certificate/index.ts +1 -0
  145. package/src/certificate/kinds/Icac.ts +12 -0
  146. package/src/certificate/kinds/Noc.ts +12 -0
  147. package/src/certificate/kinds/OperationalBase.ts +18 -3
  148. package/src/certificate/kinds/Rcac.ts +12 -0
  149. package/src/certificate/kinds/Vvsc.ts +72 -0
  150. package/src/certificate/kinds/X509Base.ts +426 -7
  151. package/src/certificate/kinds/definitions/asn.ts +50 -24
  152. package/src/certificate/kinds/definitions/operational.ts +10 -2
  153. package/src/certificate/kinds/index.ts +1 -0
  154. package/src/fabric/Fabric.ts +66 -3
  155. package/src/fabric/FabricManager.ts +32 -9
  156. package/src/mdns/MdnsConsts.ts +1 -1
  157. package/src/peer/PhysicalDeviceProperties.ts +52 -35
  158. package/src/protocol/DeviceAdvertiser.ts +30 -0
@@ -29,7 +29,7 @@ import { FabricGroups, GROUP_SECURITY_INFO } from "#groups/FabricGroups.js";
29
29
  import { FabricAccessControl } from "#interaction/FabricAccessControl.js";
30
30
  import { PeerAddress } from "#peer/PeerAddress.js";
31
31
  import { Session } from "#session/Session.js";
32
- import { CaseAuthenticatedTag, FabricId, FabricIndex, GroupId, NodeId, VendorId } from "#types";
32
+ import { CaseAuthenticatedTag, FabricId, FabricIndex, GroupId, NodeId, StatusResponse, VendorId } from "#types";
33
33
 
34
34
  const logger = Logger.get("Fabric");
35
35
 
@@ -54,7 +54,7 @@ export class Fabric {
54
54
  readonly rootNodeId: NodeId;
55
55
  readonly operationalId: Bytes;
56
56
  readonly rootPublicKey: Bytes;
57
- readonly rootVendorId: VendorId;
57
+ #rootVendorId: VendorId;
58
58
  readonly rootCert: Bytes;
59
59
  readonly identityProtectionKey: Bytes;
60
60
  readonly operationalIdentityProtectionKey: Bytes;
@@ -64,6 +64,8 @@ export class Fabric {
64
64
  readonly #sessions = new Set<Session>();
65
65
  readonly #groups: FabricGroups;
66
66
  readonly #accessControl: FabricAccessControl;
67
+ #vidVerificationStatement?: Bytes;
68
+ #vvsc?: Bytes;
67
69
  #label: string;
68
70
  #removeCallbacks = new Array<() => MaybePromise<void>>();
69
71
  #persistCallback: ((isUpdate?: boolean) => MaybePromise<void>) | undefined;
@@ -77,12 +79,14 @@ export class Fabric {
77
79
  this.rootNodeId = config.rootNodeId;
78
80
  this.operationalId = config.operationalId;
79
81
  this.rootPublicKey = config.rootPublicKey;
80
- this.rootVendorId = config.rootVendorId;
82
+ this.#rootVendorId = config.rootVendorId;
81
83
  this.rootCert = config.rootCert;
82
84
  this.identityProtectionKey = config.identityProtectionKey;
83
85
  this.operationalIdentityProtectionKey = config.operationalIdentityProtectionKey;
84
86
  this.intermediateCACert = config.intermediateCACert;
85
87
  this.operationalCert = config.operationalCert;
88
+ this.#vidVerificationStatement = config.vidVerificationStatement;
89
+ this.#vvsc = config.vvsc;
86
90
  this.#label = config.label;
87
91
  this.#keyPair = PrivateKey(config.keyPair);
88
92
  this.#accessControl = new FabricAccessControl(this);
@@ -108,6 +112,7 @@ export class Fabric {
108
112
  operationalIdentityProtectionKey: this.operationalIdentityProtectionKey,
109
113
  intermediateCACert: this.intermediateCACert,
110
114
  operationalCert: this.operationalCert,
115
+ vidVerificationStatement: this.vidVerificationStatement,
111
116
  label: this.#label,
112
117
  };
113
118
  }
@@ -127,6 +132,56 @@ export class Fabric {
127
132
  await this.persist();
128
133
  }
129
134
 
135
+ get vidVerificationStatement() {
136
+ return this.#vidVerificationStatement;
137
+ }
138
+
139
+ async updateVendorVerificationData(
140
+ vendorId: VendorId | undefined,
141
+ vidVerificationStatement: Bytes | undefined,
142
+ vvsc: Bytes | undefined,
143
+ ) {
144
+ if (vvsc !== undefined && this.intermediateCACert !== undefined) {
145
+ throw new StatusResponse.InvalidCommandError("A VVSC is only allowed without an ICAC.");
146
+ }
147
+
148
+ if (vidVerificationStatement !== undefined) {
149
+ if (vidVerificationStatement.byteLength === 0) {
150
+ this.#vidVerificationStatement = undefined;
151
+ } else if (vidVerificationStatement.byteLength === 85) {
152
+ // VERIFICATION_STATEMENT_SIZE
153
+ this.#vidVerificationStatement = vidVerificationStatement;
154
+ } else {
155
+ throw new StatusResponse.ConstraintErrorError("VID Verification Statement must be 0 or 85 bytes long.");
156
+ }
157
+ }
158
+ if (vendorId !== undefined) {
159
+ this.#rootVendorId = vendorId;
160
+ }
161
+ if (vvsc !== undefined) {
162
+ if (vvsc.byteLength === 0) {
163
+ this.#vvsc = undefined;
164
+ } else {
165
+ this.#vvsc = vvsc;
166
+ }
167
+ }
168
+ logger.info(
169
+ "Updated Vendor Verification Data for Fabric",
170
+ this.#rootVendorId,
171
+ this.#vidVerificationStatement,
172
+ this.#vvsc,
173
+ );
174
+ await this.persist();
175
+ }
176
+
177
+ get vvsc() {
178
+ return this.#vvsc;
179
+ }
180
+
181
+ get rootVendorId() {
182
+ return this.#rootVendorId;
183
+ }
184
+
130
185
  set storage(storage: StorageContext) {
131
186
  this.#storage = storage;
132
187
  this.#groups.storage = storage;
@@ -282,6 +337,8 @@ export class FabricBuilder {
282
337
  #rootNodeId?: NodeId;
283
338
  #rootPublicKey?: Bytes;
284
339
  #identityProtectionKey?: Bytes;
340
+ #vidVerificationStatement?: Bytes;
341
+ #vvsc?: Bytes;
285
342
  #fabricIndex?: FabricIndex;
286
343
  #label = "";
287
344
 
@@ -387,6 +444,8 @@ export class FabricBuilder {
387
444
  this.#identityProtectionKey = fabric.identityProtectionKey;
388
445
  this.#rootCert = fabric.rootCert;
389
446
  this.#rootPublicKey = fabric.rootPublicKey;
447
+ this.#vidVerificationStatement = fabric.vidVerificationStatement;
448
+ this.#vvsc = fabric.vvsc;
390
449
  this.#label = fabric.label;
391
450
  }
392
451
 
@@ -447,6 +506,8 @@ export class FabricBuilder {
447
506
  ),
448
507
  intermediateCACert: this.#intermediateCACert,
449
508
  operationalCert: this.#operationalCert,
509
+ vidVerificationStatement: this.#vidVerificationStatement,
510
+ vvsc: this.#vvsc,
450
511
  label: this.#label,
451
512
  });
452
513
  }
@@ -464,6 +525,8 @@ export namespace Fabric {
464
525
  rootVendorId: VendorId;
465
526
  rootCert: Bytes;
466
527
  identityProtectionKey: Bytes;
528
+ vidVerificationStatement?: Bytes;
529
+ vvsc?: Bytes;
467
530
  operationalIdentityProtectionKey: Bytes;
468
531
  intermediateCACert: Bytes | undefined;
469
532
  operationalCert: Bytes;
@@ -12,6 +12,7 @@ import {
12
12
  Environmental,
13
13
  ImplementationError,
14
14
  Key,
15
+ Logger,
15
16
  MatterError,
16
17
  MatterFlowError,
17
18
  MaybePromise,
@@ -23,6 +24,8 @@ import { PeerAddress } from "#peer/PeerAddress.js";
23
24
  import { FabricIndex } from "#types";
24
25
  import { Fabric } from "./Fabric.js";
25
26
 
27
+ const logger = Logger.get("FabricManager");
28
+
26
29
  /** Specific Error for when a fabric is not found. */
27
30
  export class FabricNotFoundError extends MatterError {}
28
31
  export class FabricTableFullError extends MatterError {}
@@ -63,7 +66,7 @@ export class FabricManager {
63
66
 
64
67
  const fabrics = await this.#storage.get<Fabric.Config[]>("fabrics", []);
65
68
  for (const fabricConfig of fabrics) {
66
- this.#addFabric(new Fabric(crypto, fabricConfig));
69
+ this.#addNewFabric(new Fabric(crypto, fabricConfig));
67
70
  }
68
71
 
69
72
  this.#nextFabricIndex = await this.#storage.get("nextFabricIndex", this.#nextFabricIndex);
@@ -156,18 +159,34 @@ export class FabricManager {
156
159
 
157
160
  addFabric(fabric: Fabric) {
158
161
  this.#construction.assert();
159
- this.#addFabric(fabric);
162
+ this.#addNewFabric(fabric);
160
163
  }
161
164
 
162
- #addFabric(fabric: Fabric) {
165
+ #addNewFabric(fabric: Fabric) {
163
166
  const { fabricIndex } = fabric;
164
167
  if (this.#fabrics.has(fabricIndex)) {
165
168
  throw new MatterFlowError(`Fabric with index ${fabricIndex} already exists.`);
166
169
  }
170
+
171
+ this.#addOrUpdateFabricEntry(fabric);
172
+
173
+ if (this.#initializationDone) {
174
+ this.#events.added.emit(fabric);
175
+ }
176
+ }
177
+
178
+ /** Insert Fabric into the manager without emitting events */
179
+ #addOrUpdateFabricEntry(fabric: Fabric) {
180
+ const { fabricIndex } = fabric;
167
181
  this.#fabrics.set(fabricIndex, fabric);
168
182
  fabric.addRemoveCallback(async () => this.removeFabric(fabricIndex));
169
183
  fabric.persistCallback = (isUpdate = true) => {
170
184
  if (!this.#storage) {
185
+ if (isUpdate) {
186
+ logger.warn(
187
+ "Fabric can not be persisted because FabricManager has no storage but it is a fabric update.",
188
+ );
189
+ }
171
190
  return;
172
191
  }
173
192
  const persistResult = this.persistFabrics();
@@ -177,12 +196,9 @@ export class FabricManager {
177
196
  }
178
197
  });
179
198
  };
180
- if (this.#storage !== undefined) {
199
+ if (this.#storage !== undefined && fabric.storage === undefined) {
181
200
  fabric.storage = this.#storage.createContext(`fabric-${fabricIndex}`);
182
201
  }
183
- if (this.#initializationDone) {
184
- this.#events.added.emit(fabric);
185
- }
186
202
  }
187
203
 
188
204
  async removeFabric(fabricIndex: FabricIndex) {
@@ -259,12 +275,19 @@ export class FabricManager {
259
275
  await this.#construction;
260
276
 
261
277
  const { fabricIndex } = fabric;
262
- if (!this.#fabrics.has(fabricIndex)) {
278
+ const existingFabric = this.#fabrics.get(fabricIndex);
279
+ if (existingFabric === undefined) {
263
280
  throw new FabricNotFoundError(
264
281
  `Fabric with index ${fabricIndex} cannot be updated because it does not exist.`,
265
282
  );
266
283
  }
267
- this.#fabrics.set(fabricIndex, fabric);
284
+ if (existingFabric === fabric) {
285
+ // Nothing changed, so it is a restore without any change
286
+ return;
287
+ }
288
+
289
+ this.#addOrUpdateFabricEntry(fabric);
290
+
268
291
  if (this.#storage) {
269
292
  await this.persistFabrics();
270
293
  }
@@ -23,7 +23,7 @@ export const DEFAULT_PAIRING_HINT = {
23
23
 
24
24
  export const PAIRING_HINTS_REQUIRING_INSTRUCTION = Array<keyof typeof PairingHintBitmap>(
25
25
  "customInstruction",
26
- "pressRestButtonForNumberOfSeconds",
26
+ "pressResetButtonForNumberOfSeconds",
27
27
  "pressResetButtonUntilLightBlinks",
28
28
  "pressResetButtonForNumberOfSecondsWithApplicationOfPower",
29
29
  "pressResetButtonUntilLightBlinksWithApplicationOfPower",
@@ -4,77 +4,94 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Logger } from "#general";
7
+ import { Duration, Instant, Logger, Minutes, Seconds } from "#general";
8
8
 
9
9
  const logger = Logger.get("PhysicalDeviceProperties");
10
10
 
11
- const DEFAULT_SUBSCRIPTION_FLOOR_DEFAULT_S = 1;
12
- const DEFAULT_SUBSCRIPTION_FLOOR_ICD_S = 0;
13
- const DEFAULT_SUBSCRIPTION_CEILING_WIFI_S = 60;
14
- const DEFAULT_SUBSCRIPTION_CEILING_THREAD_S = 60;
15
- const DEFAULT_SUBSCRIPTION_CEILING_THREAD_SLEEPY_S = 180;
16
- const DEFAULT_SUBSCRIPTION_CEILING_BATTERY_POWERED_S = 600;
11
+ const DEFAULT_SUBSCRIPTION_FLOOR_DEFAULT = Seconds(1);
12
+ const DEFAULT_SUBSCRIPTION_FLOOR_ICD = Instant;
13
+ const DEFAULT_SUBSCRIPTION_CEILING_WIFI = Minutes(1);
14
+ const DEFAULT_SUBSCRIPTION_CEILING_THREAD = Minutes(1);
15
+ const DEFAULT_SUBSCRIPTION_CEILING_THREAD_SLEEPY = Minutes(3);
16
+ const DEFAULT_SUBSCRIPTION_CEILING_BATTERY_POWERED = Minutes(10);
17
17
 
18
18
  export interface PhysicalDeviceProperties {
19
19
  threadConnected: boolean;
20
20
  wifiConnected: boolean;
21
21
  ethernetConnected: boolean;
22
22
  rootEndpointServerList: number[];
23
+ isMainsPowered: boolean;
23
24
  isBatteryPowered: boolean;
24
25
  isIntermittentlyConnected: boolean;
25
26
  isThreadSleepyEndDevice: boolean;
26
27
  }
27
28
 
28
29
  export namespace PhysicalDeviceProperties {
29
- export function determineSubscriptionParameters(options?: {
30
+ export function subscriptionIntervalBoundsFor(options?: {
30
31
  properties?: PhysicalDeviceProperties;
31
32
  description?: string;
32
- subscribeMinIntervalFloorSeconds?: number;
33
- subscribeMaxIntervalCeilingSeconds?: number;
34
- }) {
35
- const { properties } = options ?? {};
33
+ request?: Partial<PhysicalDeviceProperties.IntervalBounds>;
34
+ }): PhysicalDeviceProperties.IntervalBounds {
35
+ const { properties, request } = options ?? {};
36
36
 
37
- let {
38
- description,
39
- subscribeMinIntervalFloorSeconds: minIntervalFloorSeconds,
40
- subscribeMaxIntervalCeilingSeconds: maxIntervalCeilingSeconds,
41
- } = options ?? {};
37
+ let { description } = options ?? {};
38
+
39
+ let minIntervalFloor, maxIntervalCeiling;
40
+ if (request) {
41
+ ({ minIntervalFloor, maxIntervalCeiling } = request);
42
+ }
42
43
 
43
44
  if (description === undefined) {
44
45
  description = "Node";
45
46
  }
46
47
 
47
- const { isBatteryPowered, isIntermittentlyConnected, threadConnected, isThreadSleepyEndDevice } =
48
- properties ?? {};
48
+ const {
49
+ isMainsPowered,
50
+ isBatteryPowered,
51
+ isIntermittentlyConnected,
52
+ threadConnected,
53
+ isThreadSleepyEndDevice,
54
+ } = properties ?? {};
49
55
 
50
56
  if (isIntermittentlyConnected) {
51
- if (minIntervalFloorSeconds !== undefined && minIntervalFloorSeconds !== DEFAULT_SUBSCRIPTION_FLOOR_ICD_S) {
57
+ if (minIntervalFloor !== undefined && minIntervalFloor !== DEFAULT_SUBSCRIPTION_FLOOR_ICD) {
52
58
  logger.info(
53
- `${description}: Overwriting minIntervalFloorSeconds for intermittently connected device to ${DEFAULT_SUBSCRIPTION_FLOOR_ICD_S}`,
59
+ `${description}: Overwriting minIntervalFloorSeconds for intermittently connected device to ${Duration.format(DEFAULT_SUBSCRIPTION_FLOOR_ICD)}`,
54
60
  );
55
- minIntervalFloorSeconds = DEFAULT_SUBSCRIPTION_FLOOR_ICD_S;
61
+ minIntervalFloor = DEFAULT_SUBSCRIPTION_FLOOR_ICD;
56
62
  }
57
63
  }
64
+ if (minIntervalFloor === undefined) {
65
+ minIntervalFloor = DEFAULT_SUBSCRIPTION_FLOOR_DEFAULT;
66
+ }
58
67
 
59
- const defaultCeiling = isBatteryPowered
60
- ? DEFAULT_SUBSCRIPTION_CEILING_BATTERY_POWERED_S
61
- : isThreadSleepyEndDevice
62
- ? DEFAULT_SUBSCRIPTION_CEILING_THREAD_SLEEPY_S
63
- : threadConnected
64
- ? DEFAULT_SUBSCRIPTION_CEILING_THREAD_S
65
- : DEFAULT_SUBSCRIPTION_CEILING_WIFI_S;
66
- if (maxIntervalCeilingSeconds === undefined) {
67
- maxIntervalCeilingSeconds = defaultCeiling;
68
+ const defaultCeiling =
69
+ isBatteryPowered && !isMainsPowered
70
+ ? DEFAULT_SUBSCRIPTION_CEILING_BATTERY_POWERED
71
+ : isThreadSleepyEndDevice
72
+ ? DEFAULT_SUBSCRIPTION_CEILING_THREAD_SLEEPY
73
+ : threadConnected
74
+ ? DEFAULT_SUBSCRIPTION_CEILING_THREAD
75
+ : DEFAULT_SUBSCRIPTION_CEILING_WIFI;
76
+ if (maxIntervalCeiling === undefined) {
77
+ maxIntervalCeiling = defaultCeiling;
68
78
  }
69
- if (maxIntervalCeilingSeconds < defaultCeiling) {
79
+ if (maxIntervalCeiling < defaultCeiling) {
70
80
  logger.debug(
71
- `${description}: maxIntervalCeilingSeconds ideally is ${defaultCeiling}s instead of ${maxIntervalCeilingSeconds}s due to device type`,
81
+ `${description}: maxIntervalCeilingSeconds ideally is ${defaultCeiling}s instead of ${maxIntervalCeiling}s due to device type`,
72
82
  );
73
83
  }
74
84
 
75
85
  return {
76
- minIntervalFloorSeconds: minIntervalFloorSeconds ?? DEFAULT_SUBSCRIPTION_FLOOR_DEFAULT_S,
77
- maxIntervalCeilingSeconds,
86
+ minIntervalFloor,
87
+ maxIntervalCeiling,
78
88
  };
79
89
  }
80
90
  }
91
+
92
+ export namespace PhysicalDeviceProperties {
93
+ export interface IntervalBounds {
94
+ minIntervalFloor: Duration;
95
+ maxIntervalCeiling: Duration;
96
+ }
97
+ }
@@ -47,6 +47,36 @@ export class DeviceAdvertiser {
47
47
  this.#advertiseFabric(fabric, "startup");
48
48
  });
49
49
 
50
+ // When a fabric is updated we might need to adjust announcements
51
+ this.#observers.on(fabrics.events.updated, async fabric => {
52
+ if (!this.#isOperational) {
53
+ return;
54
+ }
55
+
56
+ // Look for update for this fabricIndex because other Ids might have changed and object is different
57
+ const fabricIndexAdvertisements = this.#advertisements(
58
+ ad => ad.isOperational() && ad.description.fabric.fabricIndex === fabric.fabricIndex,
59
+ );
60
+
61
+ // If the announcement relevant IDs are unchanged, do nothing
62
+ if (
63
+ fabricIndexAdvertisements.every(
64
+ ad =>
65
+ ad.isOperational() &&
66
+ ad.description.fabric.operationalId === fabric.operationalId &&
67
+ ad.description.fabric.nodeId === fabric.nodeId,
68
+ )
69
+ ) {
70
+ return;
71
+ }
72
+
73
+ for (const ad of fabricIndexAdvertisements) {
74
+ await ad.close();
75
+ }
76
+
77
+ this.#advertiseFabric(fabric, "startup");
78
+ });
79
+
50
80
  // When a fabric is deleted, cancel any active advertisement
51
81
  this.#observers.on(fabrics.events.deleted, fabric => {
52
82
  Advertisement.cancelAll(this.#advertisements(ad => ad.isOperational() && ad.description.fabric === fabric));