@matter/protocol 0.13.0-alpha.0-20250318-c1aa38b08 → 0.13.0-alpha.0-20250323-770919c6a

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 (173) hide show
  1. package/dist/cjs/ble/BtpSessionHandler.js +2 -2
  2. package/dist/cjs/ble/BtpSessionHandler.js.map +1 -1
  3. package/dist/cjs/certificate/CertificateAuthority.d.ts +1 -0
  4. package/dist/cjs/certificate/CertificateAuthority.d.ts.map +1 -1
  5. package/dist/cjs/certificate/CertificateAuthority.js.map +1 -1
  6. package/dist/cjs/certificate/CertificateManager.d.ts.map +1 -1
  7. package/dist/cjs/certificate/CertificateManager.js +21 -19
  8. package/dist/cjs/certificate/CertificateManager.js.map +1 -1
  9. package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
  10. package/dist/cjs/cluster/client/ClusterClient.js +3 -0
  11. package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
  12. package/dist/cjs/cluster/server/AttributeServer.d.ts.map +1 -1
  13. package/dist/cjs/cluster/server/AttributeServer.js +5 -5
  14. package/dist/cjs/cluster/server/AttributeServer.js.map +1 -1
  15. package/dist/cjs/cluster/server/CommandServer.js +2 -2
  16. package/dist/cjs/cluster/server/CommandServer.js.map +1 -1
  17. package/dist/cjs/common/FailsafeContext.js +1 -1
  18. package/dist/cjs/common/FailsafeContext.js.map +1 -1
  19. package/dist/cjs/endpoint/EndpointStructureLogger.js +1 -1
  20. package/dist/cjs/endpoint/EndpointStructureLogger.js.map +1 -1
  21. package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
  22. package/dist/cjs/events/OccurrenceManager.js +2 -2
  23. package/dist/cjs/events/OccurrenceManager.js.map +1 -1
  24. package/dist/cjs/interaction/AttributeDataDecoder.d.ts +21 -4
  25. package/dist/cjs/interaction/AttributeDataDecoder.d.ts.map +1 -1
  26. package/dist/cjs/interaction/AttributeDataDecoder.js +41 -2
  27. package/dist/cjs/interaction/AttributeDataDecoder.js.map +1 -1
  28. package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
  29. package/dist/cjs/interaction/AttributeDataEncoder.js +3 -3
  30. package/dist/cjs/interaction/AttributeDataEncoder.js.map +1 -1
  31. package/dist/cjs/interaction/DecodedDataReport.d.ts +4 -2
  32. package/dist/cjs/interaction/DecodedDataReport.d.ts.map +1 -1
  33. package/dist/cjs/interaction/DecodedDataReport.js +6 -2
  34. package/dist/cjs/interaction/DecodedDataReport.js.map +1 -1
  35. package/dist/cjs/interaction/EventDataDecoder.d.ts +15 -3
  36. package/dist/cjs/interaction/EventDataDecoder.d.ts.map +1 -1
  37. package/dist/cjs/interaction/EventDataDecoder.js +39 -2
  38. package/dist/cjs/interaction/EventDataDecoder.js.map +1 -1
  39. package/dist/cjs/interaction/InteractionClient.d.ts +44 -4
  40. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  41. package/dist/cjs/interaction/InteractionClient.js +71 -18
  42. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  43. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  44. package/dist/cjs/interaction/InteractionMessenger.js +7 -4
  45. package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
  46. package/dist/cjs/interaction/InteractionServer.d.ts.map +1 -1
  47. package/dist/cjs/interaction/InteractionServer.js +7 -7
  48. package/dist/cjs/interaction/InteractionServer.js.map +1 -1
  49. package/dist/cjs/interaction/ServerSubscription.d.ts.map +1 -1
  50. package/dist/cjs/interaction/ServerSubscription.js +1 -1
  51. package/dist/cjs/interaction/ServerSubscription.js.map +1 -1
  52. package/dist/cjs/mdns/MdnsScanner.js +2 -2
  53. package/dist/cjs/mdns/MdnsScanner.js.map +1 -1
  54. package/dist/cjs/peer/ControllerCommissioner.d.ts +15 -3
  55. package/dist/cjs/peer/ControllerCommissioner.d.ts.map +1 -1
  56. package/dist/cjs/peer/ControllerCommissioner.js +17 -6
  57. package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
  58. package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +47 -1
  59. package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
  60. package/dist/cjs/peer/ControllerCommissioningFlow.js +136 -136
  61. package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
  62. package/dist/cjs/peer/ControllerDiscovery.d.ts.map +1 -1
  63. package/dist/cjs/peer/ControllerDiscovery.js +4 -4
  64. package/dist/cjs/peer/ControllerDiscovery.js.map +1 -1
  65. package/dist/cjs/peer/PeerSet.d.ts +2 -2
  66. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  67. package/dist/cjs/peer/PeerSet.js +6 -1
  68. package/dist/cjs/peer/PeerSet.js.map +1 -1
  69. package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
  70. package/dist/cjs/protocol/ChannelManager.js +11 -4
  71. package/dist/cjs/protocol/ChannelManager.js.map +1 -1
  72. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  73. package/dist/cjs/protocol/ExchangeManager.js +1 -2
  74. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  75. package/dist/esm/ble/BtpSessionHandler.js +2 -2
  76. package/dist/esm/ble/BtpSessionHandler.js.map +1 -1
  77. package/dist/esm/certificate/CertificateAuthority.d.ts +1 -0
  78. package/dist/esm/certificate/CertificateAuthority.d.ts.map +1 -1
  79. package/dist/esm/certificate/CertificateAuthority.js.map +1 -1
  80. package/dist/esm/certificate/CertificateManager.d.ts.map +1 -1
  81. package/dist/esm/certificate/CertificateManager.js +22 -19
  82. package/dist/esm/certificate/CertificateManager.js.map +1 -1
  83. package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
  84. package/dist/esm/cluster/client/ClusterClient.js +3 -0
  85. package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
  86. package/dist/esm/cluster/server/AttributeServer.d.ts.map +1 -1
  87. package/dist/esm/cluster/server/AttributeServer.js +15 -6
  88. package/dist/esm/cluster/server/AttributeServer.js.map +1 -1
  89. package/dist/esm/cluster/server/CommandServer.js +3 -3
  90. package/dist/esm/cluster/server/CommandServer.js.map +1 -1
  91. package/dist/esm/common/FailsafeContext.js +1 -1
  92. package/dist/esm/common/FailsafeContext.js.map +1 -1
  93. package/dist/esm/endpoint/EndpointStructureLogger.js +1 -1
  94. package/dist/esm/endpoint/EndpointStructureLogger.js.map +1 -1
  95. package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
  96. package/dist/esm/events/OccurrenceManager.js +3 -2
  97. package/dist/esm/events/OccurrenceManager.js.map +1 -1
  98. package/dist/esm/interaction/AttributeDataDecoder.d.ts +21 -4
  99. package/dist/esm/interaction/AttributeDataDecoder.d.ts.map +1 -1
  100. package/dist/esm/interaction/AttributeDataDecoder.js +41 -2
  101. package/dist/esm/interaction/AttributeDataDecoder.js.map +1 -1
  102. package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
  103. package/dist/esm/interaction/AttributeDataEncoder.js +4 -4
  104. package/dist/esm/interaction/AttributeDataEncoder.js.map +1 -1
  105. package/dist/esm/interaction/DecodedDataReport.d.ts +4 -2
  106. package/dist/esm/interaction/DecodedDataReport.d.ts.map +1 -1
  107. package/dist/esm/interaction/DecodedDataReport.js +12 -4
  108. package/dist/esm/interaction/DecodedDataReport.js.map +1 -1
  109. package/dist/esm/interaction/EventDataDecoder.d.ts +15 -3
  110. package/dist/esm/interaction/EventDataDecoder.d.ts.map +1 -1
  111. package/dist/esm/interaction/EventDataDecoder.js +39 -2
  112. package/dist/esm/interaction/EventDataDecoder.js.map +1 -1
  113. package/dist/esm/interaction/InteractionClient.d.ts +44 -4
  114. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  115. package/dist/esm/interaction/InteractionClient.js +74 -18
  116. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  117. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  118. package/dist/esm/interaction/InteractionMessenger.js +8 -4
  119. package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
  120. package/dist/esm/interaction/InteractionServer.d.ts.map +1 -1
  121. package/dist/esm/interaction/InteractionServer.js +17 -8
  122. package/dist/esm/interaction/InteractionServer.js.map +1 -1
  123. package/dist/esm/interaction/ServerSubscription.d.ts.map +1 -1
  124. package/dist/esm/interaction/ServerSubscription.js +2 -1
  125. package/dist/esm/interaction/ServerSubscription.js.map +1 -1
  126. package/dist/esm/mdns/MdnsScanner.js +2 -2
  127. package/dist/esm/mdns/MdnsScanner.js.map +1 -1
  128. package/dist/esm/peer/ControllerCommissioner.d.ts +15 -3
  129. package/dist/esm/peer/ControllerCommissioner.d.ts.map +1 -1
  130. package/dist/esm/peer/ControllerCommissioner.js +18 -6
  131. package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
  132. package/dist/esm/peer/ControllerCommissioningFlow.d.ts +47 -1
  133. package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
  134. package/dist/esm/peer/ControllerCommissioningFlow.js +147 -137
  135. package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
  136. package/dist/esm/peer/ControllerDiscovery.d.ts.map +1 -1
  137. package/dist/esm/peer/ControllerDiscovery.js +5 -5
  138. package/dist/esm/peer/ControllerDiscovery.js.map +1 -1
  139. package/dist/esm/peer/PeerSet.d.ts +2 -2
  140. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  141. package/dist/esm/peer/PeerSet.js +7 -2
  142. package/dist/esm/peer/PeerSet.js.map +1 -1
  143. package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
  144. package/dist/esm/protocol/ChannelManager.js +11 -4
  145. package/dist/esm/protocol/ChannelManager.js.map +1 -1
  146. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  147. package/dist/esm/protocol/ExchangeManager.js +2 -2
  148. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  149. package/package.json +6 -6
  150. package/src/ble/BtpSessionHandler.ts +2 -2
  151. package/src/certificate/CertificateAuthority.ts +1 -0
  152. package/src/certificate/CertificateManager.ts +22 -19
  153. package/src/cluster/client/ClusterClient.ts +3 -0
  154. package/src/cluster/server/AttributeServer.ts +15 -6
  155. package/src/cluster/server/CommandServer.ts +3 -3
  156. package/src/common/FailsafeContext.ts +1 -1
  157. package/src/endpoint/EndpointStructureLogger.ts +1 -1
  158. package/src/events/OccurrenceManager.ts +3 -2
  159. package/src/interaction/AttributeDataDecoder.ts +67 -7
  160. package/src/interaction/AttributeDataEncoder.ts +4 -4
  161. package/src/interaction/DecodedDataReport.ts +24 -5
  162. package/src/interaction/EventDataDecoder.ts +57 -5
  163. package/src/interaction/InteractionClient.ts +112 -18
  164. package/src/interaction/InteractionMessenger.ts +8 -4
  165. package/src/interaction/InteractionServer.ts +19 -9
  166. package/src/interaction/ServerSubscription.ts +2 -1
  167. package/src/mdns/MdnsScanner.ts +2 -2
  168. package/src/peer/ControllerCommissioner.ts +32 -7
  169. package/src/peer/ControllerCommissioningFlow.ts +160 -146
  170. package/src/peer/ControllerDiscovery.ts +5 -5
  171. package/src/peer/PeerSet.ts +7 -2
  172. package/src/protocol/ChannelManager.ts +11 -4
  173. package/src/protocol/ExchangeManager.ts +2 -2
@@ -15,6 +15,7 @@ import {
15
15
  DerKey,
16
16
  DerObject,
17
17
  DerType,
18
+ Diagnostic,
18
19
  ImplementationError,
19
20
  Key,
20
21
  Logger,
@@ -788,13 +789,13 @@ export namespace CertificateManager {
788
789
  if (rootCert.subject.fabricId !== undefined) {
789
790
  if (Array.isArray(rootCert.subject.fabricId)) {
790
791
  throw new CertificateError(
791
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(rootCert.subject.fabricId)}`,
792
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(rootCert.subject.fabricId)}`,
792
793
  );
793
794
  }
794
795
  // If present, the matter-fabric-id attribute’s value SHALL NOT be 0
795
796
  if (rootCert.subject.fabricId === FabricId(0)) {
796
797
  throw new CertificateError(
797
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(rootCert.subject.fabricId)}`,
798
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(rootCert.subject.fabricId)}`,
798
799
  );
799
800
  }
800
801
  }
@@ -806,7 +807,9 @@ export namespace CertificateManager {
806
807
 
807
808
  // The subject DN SHALL encode exactly one matter-rcac-id attribute.
808
809
  if (rootCert.subject.rcacId === undefined || Array.isArray(rootCert.subject.rcacId)) {
809
- throw new CertificateError(`Invalid rcacId in Root certificate: ${Logger.toJSON(rootCert.subject.rcacId)}`);
810
+ throw new CertificateError(
811
+ `Invalid rcacId in Root certificate: ${Diagnostic.json(rootCert.subject.rcacId)}`,
812
+ );
810
813
  }
811
814
 
812
815
  // The subject DN SHALL NOT encode any matter-noc-cat attribute.
@@ -874,23 +877,23 @@ export namespace CertificateManager {
874
877
 
875
878
  // The subject DN SHALL encode exactly one matter-node-id attribute.
876
879
  if (nocCert.subject.nodeId === undefined || Array.isArray(nocCert.subject.nodeId)) {
877
- throw new CertificateError(`Invalid nodeId in NoC certificate: ${Logger.toJSON(nocCert.subject.nodeId)}`);
880
+ throw new CertificateError(`Invalid nodeId in NoC certificate: ${Diagnostic.json(nocCert.subject.nodeId)}`);
878
881
  }
879
882
  // The matter-node-id attribute’s value SHALL be in the Operational Node ID
880
883
  if (!NodeId.isOperationalNodeId(nocCert.subject.nodeId)) {
881
- throw new CertificateError(`Invalid nodeId in NoC certificate: ${Logger.toJSON(nocCert.subject.nodeId)}`);
884
+ throw new CertificateError(`Invalid nodeId in NoC certificate: ${Diagnostic.json(nocCert.subject.nodeId)}`);
882
885
  }
883
886
 
884
887
  // The subject DN SHALL encode exactly one matter-fabric-id attribute.
885
888
  if (nocCert.subject.fabricId === undefined || Array.isArray(nocCert.subject.fabricId)) {
886
889
  throw new CertificateError(
887
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(nocCert.subject.fabricId)}`,
890
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(nocCert.subject.fabricId)}`,
888
891
  );
889
892
  }
890
893
  // The matter-fabric-id attribute’s value SHALL NOT be 0
891
894
  if (nocCert.subject.fabricId === FabricId(0)) {
892
895
  throw new CertificateError(
893
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(nocCert.subject.fabricId)}`,
896
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(nocCert.subject.fabricId)}`,
894
897
  );
895
898
  }
896
899
 
@@ -914,9 +917,9 @@ export namespace CertificateManager {
914
917
  // the same certificate chain.
915
918
  if (rootCert.subject.fabricId !== undefined && rootCert.subject.fabricId !== nocCert.subject.fabricId) {
916
919
  throw new CertificateError(
917
- `FabricId in NoC certificate does not match the fabricId in the parent certificate. ${Logger.toJSON(
920
+ `FabricId in NoC certificate does not match the fabricId in the parent certificate. ${Diagnostic.json(
918
921
  rootCert.subject.fabricId,
919
- )} !== ${Logger.toJSON(nocCert.subject.fabricId)}`,
922
+ )} !== ${Diagnostic.json(nocCert.subject.fabricId)}`,
920
923
  );
921
924
  }
922
925
  if (
@@ -925,9 +928,9 @@ export namespace CertificateManager {
925
928
  icaCert.subject.fabricId !== nocCert.subject.fabricId
926
929
  ) {
927
930
  throw new CertificateError(
928
- `FabricId in NoC certificate does not match the fabricId in the parent certificate. ${Logger.toJSON(
931
+ `FabricId in NoC certificate does not match the fabricId in the parent certificate. ${Diagnostic.json(
929
932
  icaCert.subject.fabricId,
930
- )} !== ${Logger.toJSON(nocCert.subject.fabricId)}`,
933
+ )} !== ${Diagnostic.json(nocCert.subject.fabricId)}`,
931
934
  );
932
935
  }
933
936
 
@@ -950,7 +953,7 @@ export namespace CertificateManager {
950
953
  (!nocCert.extensions.extendedKeyUsage.includes(1) && !nocCert.extensions.extendedKeyUsage.includes(2))
951
954
  ) {
952
955
  throw new CertificateError(
953
- `Noc certificate must have extendedKeyUsage with serverAuth and clientAuth: ${Logger.toJSON(nocCert.extensions.extendedKeyUsage)}`,
956
+ `Noc certificate must have extendedKeyUsage with serverAuth and clientAuth: ${Diagnostic.json(nocCert.extensions.extendedKeyUsage)}`,
954
957
  );
955
958
  }
956
959
 
@@ -1005,20 +1008,20 @@ export namespace CertificateManager {
1005
1008
  if (icaCert.subject.fabricId !== undefined) {
1006
1009
  if (Array.isArray(icaCert.subject.fabricId)) {
1007
1010
  throw new CertificateError(
1008
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(icaCert.subject.fabricId)}`,
1011
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(icaCert.subject.fabricId)}`,
1009
1012
  );
1010
1013
  }
1011
1014
  // If present, the matter-fabric-id attribute’s value SHALL NOT be 0
1012
1015
  if (icaCert.subject.fabricId === FabricId(0)) {
1013
1016
  throw new CertificateError(
1014
- `Invalid fabricId in NoC certificate: ${Logger.toJSON(icaCert.subject.fabricId)}`,
1017
+ `Invalid fabricId in NoC certificate: ${Diagnostic.json(icaCert.subject.fabricId)}`,
1015
1018
  );
1016
1019
  }
1017
1020
  }
1018
1021
 
1019
1022
  // The subject DN SHALL encode exactly one matter-icac-id attribute.
1020
1023
  if (icaCert.subject.icacId === undefined || Array.isArray(icaCert.subject.icacId)) {
1021
- throw new CertificateError(`Invalid icacId in Ica certificate: ${Logger.toJSON(icaCert.subject.icacId)}`);
1024
+ throw new CertificateError(`Invalid icacId in Ica certificate: ${Diagnostic.json(icaCert.subject.icacId)}`);
1022
1025
  }
1023
1026
 
1024
1027
  // The subject DN SHALL NOT encode any matter-rcac-id attribute.
@@ -1041,18 +1044,18 @@ export namespace CertificateManager {
1041
1044
  rootCert.subject.fabricId !== icaCert.subject.fabricId
1042
1045
  ) {
1043
1046
  throw new CertificateError(
1044
- `FabricId in Ica certificate does not match the fabricId in the parent certificate. ${Logger.toJSON(
1047
+ `FabricId in Ica certificate does not match the fabricId in the parent certificate. ${Diagnostic.json(
1045
1048
  rootCert.subject.fabricId,
1046
- )} !== ${Logger.toJSON(icaCert.subject.fabricId)}`,
1049
+ )} !== ${Diagnostic.json(icaCert.subject.fabricId)}`,
1047
1050
  );
1048
1051
  }
1049
1052
 
1050
1053
  // Verify the certificate chain by checking rcac ids in subject and issuer
1051
1054
  if (rootCert.subject.rcacId !== icaCert.issuer.rcacId) {
1052
1055
  throw new CertificateError(
1053
- `RcacId in Ica certificate does not match the rcacId in the parent certificate. ${Logger.toJSON(
1056
+ `RcacId in Ica certificate does not match the rcacId in the parent certificate. ${Diagnostic.json(
1054
1057
  rootCert.subject.rcacId,
1055
- )} !== ${Logger.toJSON(icaCert.issuer.rcacId)}`,
1058
+ )} !== ${Diagnostic.json(icaCert.issuer.rcacId)}`,
1056
1059
  );
1057
1060
  }
1058
1061
 
@@ -52,6 +52,7 @@ export function ClusterClient<const T extends ClusterType>(
52
52
  interactionClient,
53
53
  !!globalAttributeValues?.attributeList?.includes(attribute.id),
54
54
  );
55
+ (attributes as any)[attribute.id] = (attributes as any)[attributeName];
55
56
  attributeToId[attribute.id] = attributeName;
56
57
  const capitalizedAttributeName = capitalize(attributeName);
57
58
  result[`get${capitalizedAttributeName}Attribute`] = async (
@@ -94,6 +95,7 @@ export function ClusterClient<const T extends ClusterType>(
94
95
 
95
96
  function addEventToResult(event: Event<any, any>, eventName: string) {
96
97
  (events as any)[eventName] = createEventClient(event, eventName, endpointId, clusterId, interactionClient);
98
+ (events as any)[event.id] = (events as any)[eventName];
97
99
  eventToId[event.id] = eventName;
98
100
  const capitalizedEventName = capitalize(eventName);
99
101
  result[`get${capitalizedEventName}Event`] = async (
@@ -316,6 +318,7 @@ export function ClusterClient<const T extends ClusterType>(
316
318
  useExtendedFailSafeMessageResponseTimeout,
317
319
  });
318
320
  };
321
+ commands[requestId as unknown as keyof T["commands"]] = commands[commandName as keyof T["commands"]];
319
322
  result[commandName] = result.commands[commandName];
320
323
  }
321
324
  if (globalAttributeValues?.acceptedCommandList !== undefined) {
@@ -4,7 +4,16 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { ImplementationError, InternalError, Logger, MatterError, MaybePromise, camelize, isDeepEqual } from "#general";
7
+ import {
8
+ Diagnostic,
9
+ ImplementationError,
10
+ InternalError,
11
+ Logger,
12
+ MatterError,
13
+ MaybePromise,
14
+ camelize,
15
+ isDeepEqual,
16
+ } from "#general";
8
17
  import { AccessLevel, AttributeModel, ClusterModel, DatatypeModel, FabricIndex, MatterModel } from "#model";
9
18
  import {
10
19
  Attribute,
@@ -165,9 +174,9 @@ export abstract class BaseAttributeServer<T> {
165
174
  this.value = initValue;
166
175
  } catch (error) {
167
176
  logger.warn(
168
- `Attribute value to initialize for ${name} has an invalid value ${Logger.toJSON(
177
+ `Attribute value to initialize for ${name} has an invalid value ${Diagnostic.json(
169
178
  initValue,
170
- )}. Restore to default ${Logger.toJSON(defaultValue)}`,
179
+ )}. Restore to default ${Diagnostic.json(defaultValue)}`,
171
180
  );
172
181
  if (defaultValue === undefined) {
173
182
  throw new ImplementationError(`Attribute value to initialize for ${name} cannot be undefined.`);
@@ -524,7 +533,7 @@ export class AttributeServer<T> extends FixedAttributeServer<T> {
524
533
  newValue: value,
525
534
  changed: !!this.delayedChangeData?.changed || valueChanged, // We combine the changed flag
526
535
  };
527
- logger.info(`Delay change for attribute "${this.name}" with value ${Logger.toJSON(value)}`);
536
+ logger.info(`Delay change for attribute "${this.name}" with value ${Diagnostic.json(value)}`);
528
537
  } else {
529
538
  this.handleVersionAndTriggerListeners(value, oldValue, valueChanged);
530
539
  }
@@ -534,7 +543,7 @@ export class AttributeServer<T> extends FixedAttributeServer<T> {
534
543
  if (this.delayedChangeData !== undefined) {
535
544
  const { oldValue, newValue, changed } = this.delayedChangeData;
536
545
  this.delayedChangeData = undefined;
537
- logger.info(`Trigger delayed change for attribute "${this.name}" with value ${Logger.toJSON(newValue)}`);
546
+ logger.info(`Trigger delayed change for attribute "${this.name}" with value ${Diagnostic.json(newValue)}`);
538
547
  this.handleVersionAndTriggerListeners(newValue, oldValue, changed);
539
548
  }
540
549
  }
@@ -909,7 +918,7 @@ export class FabricScopedAttributeServer<T> extends AttributeServer<T> {
909
918
  () => !preserveFabricIndex, // No one should send any index and if we simply SHALL ignore it, but internally we might need it
910
919
  );
911
920
  logger.info(
912
- `Set remote value for fabric scoped attribute "${this.name}" to ${Logger.toJSON(value)} (delayed=${delayChangeEvents})`,
921
+ `Set remote value for fabric scoped attribute "${this.name}" to ${Diagnostic.json(value)} (delayed=${delayChangeEvents})`,
913
922
  );
914
923
 
915
924
  super.setRemote(value, session, message, delayChangeEvents);
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- import { Logger } from "#general";
7
+ import { Diagnostic, Logger } from "#general";
8
8
  import { AccessLevel, FabricIndex } from "#model";
9
9
  import { CommandId, StatusCode, TlvSchema, TlvStream } from "#types";
10
10
  import { Message } from "../../codec/MessageCodec.js";
@@ -69,9 +69,9 @@ export class CommandServer<RequestT = any, ResponseT = any> {
69
69
  }
70
70
 
71
71
  this.requestSchema.validate(request);
72
- this.debug(`Invoke ${this.name} with data ${Logger.toJSON(request)}`);
72
+ this.debug(`Invoke ${this.name} with data ${Diagnostic.json(request)}`);
73
73
  const response = await this.handler(request, session, message, endpoint);
74
- this.debug(`Invoke ${this.name} response : ${Logger.toJSON(response)}`);
74
+ this.debug(`Invoke ${this.name} response : ${Diagnostic.json(response)}`);
75
75
  return {
76
76
  code: StatusCode.Success,
77
77
  responseId: this.responseId,
@@ -249,7 +249,7 @@ export abstract class FailsafeContext {
249
249
  }
250
250
 
251
251
  async #failSafeExpired() {
252
- logger.info("Failsafe timer expired, Reset fabric builder.");
252
+ logger.info("Failsafe timer expired; resetting fabric builder");
253
253
 
254
254
  await this.close();
255
255
  }
@@ -52,7 +52,7 @@ function getAttributeServerValue(attribute: AnyAttributeServer<any>, options: En
52
52
  attributeValue !== null &&
53
53
  options.logAttributeObjectValues !== false
54
54
  ) {
55
- value = Logger.toJSON(attributeValue);
55
+ value = Diagnostic.json(attributeValue);
56
56
  }
57
57
  } catch (error) {
58
58
  if (error instanceof FabricScopeError) {
@@ -7,6 +7,7 @@
7
7
  import {
8
8
  asyncNew,
9
9
  Construction,
10
+ Diagnostic,
10
11
  ImplementationError,
11
12
  isObject,
12
13
  Logger,
@@ -151,7 +152,7 @@ export class OccurrenceManager {
151
152
 
152
153
  // TODO - log after fabric filtering and include fabric filter in log message?
153
154
  logger.debug(
154
- `Got ${occurrences.length} events for ${resolveEventName(eventPath)} with filters: ${Logger.toJSON(filters)}`,
155
+ `Got ${occurrences.length} events for ${resolveEventName(eventPath)} with filters: ${Diagnostic.json(filters)}`,
155
156
  );
156
157
 
157
158
  // Convert from MaybePromise[] to MaybePromise<[]>
@@ -210,7 +211,7 @@ export class OccurrenceManager {
210
211
 
211
212
  add(occurrence: Occurrence): MaybePromise<NumberedOccurrence> {
212
213
  return MaybePromise.then(this.#store.add(occurrence), entry => {
213
- logger.debug(`Recorded event #${entry.number}: ${Logger.toJSON(occurrence)}`);
214
+ logger.debug(`Recorded event #${entry.number}: ${Diagnostic.json(occurrence)}`);
214
215
  this.#occurrences[occurrence.priority].push(entry);
215
216
  this.#storedEventCount++;
216
217
  if (this.#storedEventCount > this.#bufferConfig.maxEventAllowance) {
@@ -16,17 +16,18 @@ import {
16
16
  getClusterAttributeById,
17
17
  getClusterById,
18
18
  NodeId,
19
+ Status,
19
20
  TlvAny,
20
21
  TlvAttributeData,
21
22
  TlvAttributeReport,
23
+ TlvAttributeStatus,
22
24
  TlvSchema,
23
25
  TypeFromSchema,
24
26
  } from "#types";
25
27
 
26
28
  const logger = Logger.get("AttributeDataDecoder");
27
29
 
28
- /** Represents a fully qualified and decoded attribute value from a received DataReport */
29
- export type DecodedAttributeReportValue<T> = {
30
+ type DecodedAttributeReportEntry = {
30
31
  path: {
31
32
  nodeId?: NodeId;
32
33
  endpointId: EndpointNumber;
@@ -34,10 +35,20 @@ export type DecodedAttributeReportValue<T> = {
34
35
  attributeId: AttributeId;
35
36
  attributeName: string;
36
37
  };
38
+ };
39
+
40
+ /** Represents a fully qualified and decoded attribute value from a received DataReport */
41
+ export type DecodedAttributeReportValue<T> = DecodedAttributeReportEntry & {
37
42
  version: number;
38
43
  value: T;
39
44
  };
40
45
 
46
+ /** Represents a fully qualified and decoded attribute status from a received DataReport */
47
+ export type DecodedAttributeReportStatus = DecodedAttributeReportEntry & {
48
+ status?: Status;
49
+ clusterStatus?: number;
50
+ };
51
+
41
52
  /** Represents a decoded attribute value from a received DataReport where data version could be optional. */
42
53
  export type DecodedAttributeValue<T> = Omit<DecodedAttributeReportValue<T>, "version"> & {
43
54
  version?: number;
@@ -46,14 +57,20 @@ export type DecodedAttributeValue<T> = Omit<DecodedAttributeReportValue<T>, "ver
46
57
  /**
47
58
  * Parses, normalizes (e.g. un-chunk arrays and resolve Tag compression if used) and decodes the attribute data from
48
59
  * a received DataReport.
60
+ * TODO: Convert into a Generator function once we migrate Reading Data for controller to also be streaming
49
61
  */
50
- export function normalizeAndDecodeReadAttributeReport(
51
- data: TypeFromSchema<typeof TlvAttributeReport>[],
52
- ): DecodedAttributeReportValue<any>[] {
62
+ export function normalizeAndDecodeReadAttributeReport(data: TypeFromSchema<typeof TlvAttributeReport>[]): {
63
+ attributeData: DecodedAttributeReportValue<any>[];
64
+ attributeStatus: DecodedAttributeReportStatus[];
65
+ } {
53
66
  // TODO Decide how to handle the attribute report status field, right now we ignore it
54
67
  const dataValues = data.flatMap(({ attributeData }) => (attributeData !== undefined ? attributeData : []));
68
+ const dataStatus = data.flatMap(({ attributeStatus }) => (attributeStatus !== undefined ? attributeStatus : []));
55
69
 
56
- return normalizeAndDecodeAttributeData(dataValues) as DecodedAttributeReportValue<any>[]; // dataVersion existing in incoming data, so must also in outgoing data
70
+ return {
71
+ attributeData: normalizeAndDecodeAttributeData(dataValues) as DecodedAttributeReportValue<any>[],
72
+ attributeStatus: normalizeAttributeStatus(dataStatus),
73
+ };
57
74
  }
58
75
 
59
76
  export function expandPathsInAttributeData(
@@ -90,7 +107,7 @@ export function expandPathsInAttributeData(
90
107
  dataVersion: value.dataVersion,
91
108
  };
92
109
  } else if (!acceptWildcardPaths) {
93
- throw new UnexpectedDataError("Tag compression disabled, but path is incomplete: " + Logger.toJSON(path));
110
+ throw new UnexpectedDataError("Tag compression disabled, but path is incomplete: " + Diagnostic.json(path));
94
111
  }
95
112
  });
96
113
  return data;
@@ -121,6 +138,49 @@ export function normalizeAttributeData(
121
138
  return Array.from(responseList.values());
122
139
  }
123
140
 
141
+ /**
142
+ * Normalizes (e.g. un-chunk arrays and resolve Tag compression if used) and decodes the attribute data from a received
143
+ * DataReport.
144
+ */
145
+ export function normalizeAttributeStatus(
146
+ data: TypeFromSchema<typeof TlvAttributeStatus>[],
147
+ ): DecodedAttributeReportStatus[] {
148
+ const result = new Array<DecodedAttributeReportStatus>();
149
+ data.forEach(entry => {
150
+ const {
151
+ path: { nodeId, endpointId, clusterId, attributeId },
152
+ status,
153
+ } = entry;
154
+
155
+ if (endpointId === undefined || clusterId === undefined || attributeId === undefined) {
156
+ throw new UnexpectedDataError(`Invalid attribute path ${endpointId}/${clusterId}/${attributeId}`);
157
+ }
158
+ const cluster = getClusterById(clusterId);
159
+ const attributeDetail = getClusterAttributeById(cluster, attributeId);
160
+ if (attributeDetail === undefined) {
161
+ result.push({
162
+ path: {
163
+ nodeId,
164
+ endpointId,
165
+ clusterId,
166
+ attributeId,
167
+ attributeName: `Unknown (${Diagnostic.hex(attributeId)})`,
168
+ },
169
+ status: status.status,
170
+ clusterStatus: status.clusterStatus,
171
+ });
172
+
173
+ return;
174
+ }
175
+ result.push({
176
+ path: { nodeId, endpointId, clusterId, attributeId, attributeName: attributeDetail.name },
177
+ status: status.status,
178
+ clusterStatus: status.clusterStatus,
179
+ });
180
+ });
181
+ return result;
182
+ }
183
+
124
184
  /**
125
185
  * Normalizes (e.g. un-chunk arrays and resolve Tag compression if used) and decodes the attribute data from a received
126
186
  * DataReport.
@@ -3,7 +3,7 @@
3
3
  * Copyright 2022-2025 Matter.js Authors
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { Logger, MatterFlowError } from "#general";
6
+ import { Diagnostic, MatterFlowError } from "#general";
7
7
  import {
8
8
  ArraySchema,
9
9
  AttributeId,
@@ -77,7 +77,7 @@ export function encodeAttributePayloadData(
77
77
  const { attributeData } = attributePayload;
78
78
  if (attributeData === undefined) {
79
79
  throw new MatterFlowError(
80
- `Cannot encode Attribute Payload data with just a attributeStatus: ${Logger.toJSON(attributePayload)}`,
80
+ `Cannot encode Attribute Payload data with just a attributeStatus: ${Diagnostic.json(attributePayload)}`,
81
81
  );
82
82
  }
83
83
 
@@ -152,13 +152,13 @@ export function chunkAttributePayload(attributePayload: AttributeReportPayload):
152
152
  const { hasFabricSensitiveData, attributeData } = attributePayload;
153
153
  if (attributeData === undefined) {
154
154
  throw new MatterFlowError(
155
- `Cannot chunk an AttributePayload with just a attributeStatus: ${Logger.toJSON(attributePayload)}`,
155
+ `Cannot chunk an AttributePayload with just a attributeStatus: ${Diagnostic.json(attributePayload)}`,
156
156
  );
157
157
  }
158
158
  const { schema, path, dataVersion, payload } = attributeData;
159
159
  if (!(schema instanceof ArraySchema) || !Array.isArray(payload)) {
160
160
  throw new MatterFlowError(
161
- `Cannot chunk an AttributePayload with attributeData that is not an array: ${Logger.toJSON(
161
+ `Cannot chunk an AttributePayload with attributeData that is not an array: ${Diagnostic.json(
162
162
  attributePayload,
163
163
  )}`,
164
164
  );
@@ -5,13 +5,23 @@
5
5
  */
6
6
 
7
7
  import { DataReport } from "#types";
8
- import { DecodedAttributeReportValue, normalizeAndDecodeReadAttributeReport } from "./AttributeDataDecoder.js";
9
- import { DecodedEventReportValue, normalizeAndDecodeReadEventReport } from "./EventDataDecoder.js";
8
+ import {
9
+ DecodedAttributeReportStatus,
10
+ DecodedAttributeReportValue,
11
+ normalizeAndDecodeReadAttributeReport,
12
+ } from "./AttributeDataDecoder.js";
13
+ import {
14
+ DecodedEventReportStatus,
15
+ DecodedEventReportValue,
16
+ normalizeAndDecodeReadEventReport,
17
+ } from "./EventDataDecoder.js";
10
18
 
11
19
  export interface DecodedDataReport extends DataReport {
12
20
  isNormalized: true;
13
21
  attributeReports: DecodedAttributeReportValue<any>[];
22
+ attributeStatus?: DecodedAttributeReportStatus[];
14
23
  eventReports: DecodedEventReportValue<any>[];
24
+ eventStatus?: DecodedEventReportStatus[];
15
25
  }
16
26
 
17
27
  export function DecodedDataReport(report: DataReport): DecodedDataReport {
@@ -19,11 +29,20 @@ export function DecodedDataReport(report: DataReport): DecodedDataReport {
19
29
  return report as DecodedDataReport;
20
30
  }
21
31
 
32
+ const { attributeData: attributeReports, attributeStatus } =
33
+ report.attributeReports === undefined
34
+ ? { attributeData: [] }
35
+ : normalizeAndDecodeReadAttributeReport(report.attributeReports);
36
+
37
+ const { eventData: eventReports, eventStatus } =
38
+ report.eventReports === undefined ? { eventData: [] } : normalizeAndDecodeReadEventReport(report.eventReports);
39
+
22
40
  return {
23
41
  ...report,
24
42
  isNormalized: true,
25
- attributeReports:
26
- report.attributeReports === undefined ? [] : normalizeAndDecodeReadAttributeReport(report.attributeReports),
27
- eventReports: report.eventReports === undefined ? [] : normalizeAndDecodeReadEventReport(report.eventReports),
43
+ attributeReports,
44
+ attributeStatus,
45
+ eventReports,
46
+ eventStatus,
28
47
  };
29
48
  }
@@ -14,9 +14,11 @@ import {
14
14
  getClusterById,
15
15
  getClusterEventById,
16
16
  NodeId,
17
+ Status,
17
18
  TlvAny,
18
19
  TlvEventData,
19
20
  TlvEventReport,
21
+ TlvEventStatus,
20
22
  TlvStream,
21
23
  TypeFromSchema,
22
24
  } from "#types";
@@ -33,7 +35,7 @@ export type DecodedEventData<T> = {
33
35
  data?: T;
34
36
  };
35
37
 
36
- export type DecodedEventReportValue<T> = {
38
+ export type DecodedEventReportEntry = {
37
39
  path: {
38
40
  nodeId?: NodeId;
39
41
  endpointId: EndpointNumber;
@@ -41,16 +43,32 @@ export type DecodedEventReportValue<T> = {
41
43
  eventId: EventId;
42
44
  eventName: string;
43
45
  };
46
+ };
47
+
48
+ /** Represents a fully qualified and decoded attribute value from a received DataReport */
49
+ export type DecodedEventReportValue<T> = DecodedEventReportEntry & {
44
50
  events: DecodedEventData<T>[];
45
51
  };
46
52
 
47
- export function normalizeAndDecodeReadEventReport(
48
- data: TypeFromSchema<typeof TlvEventReport>[],
49
- ): DecodedEventReportValue<any>[] {
53
+ /** Represents a fully qualified and decoded attribute status from a received DataReport */
54
+ export type DecodedEventReportStatus = DecodedEventReportEntry & {
55
+ status?: Status;
56
+ clusterStatus?: number;
57
+ };
58
+
59
+ // TODO: Convert into a Generator function once we migrate Reading Data for controller to also be streaming
60
+ export function normalizeAndDecodeReadEventReport(data: TypeFromSchema<typeof TlvEventReport>[]): {
61
+ eventData: DecodedEventReportValue<any>[];
62
+ eventStatus: DecodedEventReportStatus[];
63
+ } {
50
64
  // TODO Decide how to handle the attribute report status field, right now we ignore it
51
65
  const dataValues = data.flatMap(({ eventData }) => (eventData !== undefined ? eventData : []));
66
+ const dataStatus = data.flatMap(({ eventStatus }) => (eventStatus !== undefined ? eventStatus : []));
52
67
 
53
- return normalizeAndDecodeEventData(dataValues);
68
+ return {
69
+ eventData: normalizeAndDecodeEventData(dataValues),
70
+ eventStatus: normalizeEventStatus(dataStatus),
71
+ };
54
72
  }
55
73
 
56
74
  export function normalizeEventData(
@@ -121,6 +139,40 @@ export function normalizeAndDecodeEventData(
121
139
  return result;
122
140
  }
123
141
 
142
+ export function normalizeEventStatus(data: TypeFromSchema<typeof TlvEventStatus>[]): DecodedEventReportStatus[] {
143
+ const result = new Array<DecodedEventReportStatus>();
144
+ data.forEach(entry => {
145
+ const {
146
+ path: { nodeId, endpointId, clusterId, eventId },
147
+ status,
148
+ } = entry;
149
+
150
+ if (endpointId === undefined || clusterId === undefined || eventId === undefined) {
151
+ throw new UnexpectedDataError(`Invalid event path ${endpointId}/${clusterId}/${eventId}`);
152
+ }
153
+ try {
154
+ const cluster = getClusterById(clusterId);
155
+ const eventDetail = getClusterEventById(cluster, eventId);
156
+ if (eventDetail === undefined) {
157
+ result.push({
158
+ path: { nodeId, endpointId, clusterId, eventId, eventName: `Unknown (${Diagnostic.hex(eventId)})` },
159
+ status: status.status,
160
+ clusterStatus: status.clusterStatus,
161
+ });
162
+ return;
163
+ }
164
+ result.push({
165
+ path: { nodeId, endpointId, clusterId, eventId, eventName: eventDetail.name },
166
+ status: status.status,
167
+ clusterStatus: status.clusterStatus,
168
+ });
169
+ } catch (error: any) {
170
+ logger.error(`Error decoding event ${endpointId}/${clusterId}/${eventId}: ${error.message}`);
171
+ }
172
+ });
173
+ return result;
174
+ }
175
+
124
176
  export function decodeUnknownEventValue(data: TlvStream): any {
125
177
  const schema = TlvAny;
126
178