diff --git a/Generator/ClusterGenerator.cs b/Generator/ClusterGenerator.cs
index ccb0866..3d070f2 100644
--- a/Generator/ClusterGenerator.cs
+++ b/Generator/ClusterGenerator.cs
@@ -79,7 +79,10 @@ private static void WriteClass(Cluster cluster, StreamWriter writer)
writer.WriteLine(" // Attributes");
foreach (var attribute in cluster.attributes)
- WriteAttribute(attribute, writer);
+ {
+ if (attribute.type != null)
+ WriteAttribute(attribute, writer);
+ }
writer.WriteLine(" }");
writer.Write("}");
@@ -93,10 +96,12 @@ private static void WriteStruct(clusterCommand command, bool toServer, StreamWri
writer.WriteLine($" {(toServer ? "private record" : "public struct")} " + GeneratorUtil.SanitizeName(command.name) + (toServer ? "Payload : TLVPayload {" : " {"));
foreach (clusterCommandField field in command.field)
{
+ if (field.type == null) //Reserved/removed fields
+ continue;
writer.Write(" public ");
if (field.optionalConform == null)
writer.Write("required ");
- WriteType(field.type, null, writer);
+ WriteType(field.type, field.entry?.type, writer);
if (field.optionalConform != null)
writer.Write("?");
if (field.name == GeneratorUtil.SanitizeName(command.name))
@@ -208,9 +213,9 @@ private static void WriteStructType(bool optional, string type, byte id, string
case "uint56":
case "uint64":
case "epoch-us":
- case "posix-ms":
+ case "ref_DataTypePosixMs":
case "systime-us":
- case "systime-ms":
+ case "ref_DataTypeSystemTimeMs":
case "fabric-id":
case "node-id":
case "EUI64":
@@ -225,11 +230,11 @@ private static void WriteStructType(bool optional, string type, byte id, string
writer.WriteLine($"{totalIndent}writer.WriteDouble({id}, {name});");
break;
case "octstr":
- case "ipadr":
- case "ipv4adr":
- case "ipv6adr":
+ case "ref_IpAdr":
+ case "ref_Ipv4Adr":
+ case "ref_Ipv6Adr":
case "ipv6pre":
- case "hwadr":
+ case "Hardware Address":
writer.WriteLine($"{totalIndent}writer.WriteBytes({id}, {name});");
break;
case "string":
@@ -274,8 +279,12 @@ private static void WriteCommands(Cluster cluster, StreamWriter writer)
{
foreach (var field in cmd.field)
{
+ if (field.type == null)
+ continue;
writer.Write(", ");
- WriteType(field.type, null, writer);
+ WriteType(field.type, field.entry?.type, writer);
+ if (field.optionalConform != null)
+ writer.Write('?');
writer.Write(" " + field.name);
}
}
@@ -290,7 +299,7 @@ private static void WriteCommands(Cluster cluster, StreamWriter writer)
}
else
{
- if (cmd.response != "N")
+ if (cmd.response == "N")
writer.WriteLine(" await InteractionManager.SendCommand(session, endPoint, CLUSTER_ID, " + cmd.id + ");");
else
writer.WriteLine(" InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, " + cmd.id + ");");
@@ -308,7 +317,7 @@ private static void WriteCommands(Cluster cluster, StreamWriter writer)
foreach (var field in response.field)
{
writer.Write(" " + field.name + " = (");
- WriteType(field.type, null, writer);
+ WriteType(field.type, field.entry?.type, writer);
if (field.optionalConform != null)
writer.WriteLine($"?)GetOptionalField(resp, {field.id}),");
else
@@ -439,9 +448,9 @@ private static void WriteType(string type, string? entryType, StreamWriter write
case "uint56":
case "uint64":
case "epoch-us":
- case "posix-ms":
+ case "ref_DataTypePosixMs":
case "systime-us":
- case "systime-ms":
+ case "ref_DataTypeSystemTimeMs":
case "fabric-id":
case "node-id":
case "EUI64":
@@ -479,11 +488,11 @@ private static void WriteType(string type, string? entryType, StreamWriter write
writer.Write("float");
break;
case "octstr":
- case "ipadr":
- case "ipv4adr":
- case "ipv6adr":
+ case "ref_IpAdr":
+ case "ref_Ipv4Adr":
+ case "ref_Ipv6Adr":
case "ipv6pre":
- case "hwadr":
+ case "Hardware Address":
writer.Write("byte[]");
break;
case "bool":
diff --git a/Generator/Clusters/DiagnosticsGeneral.xml b/Generator/Clusters/DiagnosticsGeneral.xml
new file mode 100644
index 0000000..0fea7a0
--- /dev/null
+++ b/Generator/Clusters/DiagnosticsGeneral.xml
@@ -0,0 +1,373 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Generator/Clusters/Group-Key-Management-Cluster.xml b/Generator/Clusters/Group-Key-Management-Cluster.xml
new file mode 100644
index 0000000..14c7685
--- /dev/null
+++ b/Generator/Clusters/Group-Key-Management-Cluster.xml
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Generator/Schema/Cluster.cs b/Generator/Schema/Cluster.cs
index b4c8038..4fbbe78 100644
--- a/Generator/Schema/Cluster.cs
+++ b/Generator/Schema/Cluster.cs
@@ -1663,6 +1663,20 @@ public partial class clusterCommandField
private bool defaultFieldSpecified;
+ private clusterAttributeEntry? entryField;
+
+ public clusterAttributeEntry? entry
+ {
+ get
+ {
+ return this.entryField;
+ }
+ set
+ {
+ this.entryField = value;
+ }
+ }
+
///
public object optionalConform
{
diff --git a/MatterDotNet/Clusters/GeneralCommissioningCluster.cs b/MatterDotNet/Clusters/GeneralCommissioningCluster.cs
index 131cb74..28aafb6 100644
--- a/MatterDotNet/Clusters/GeneralCommissioningCluster.cs
+++ b/MatterDotNet/Clusters/GeneralCommissioningCluster.cs
@@ -12,7 +12,6 @@
//
// WARNING: This file was auto-generated. Do not edit.
-
using MatterDotNet.Messages.InteractionModel;
using MatterDotNet.Protocol;
using MatterDotNet.Protocol.Parsers;
@@ -65,7 +64,7 @@ public enum RegulatoryLocationTypeEnum {
IndoorOutdoor = 2,
}
- public record BasicCommissioningInfoStruct : TLVPayload {
+ public record BasicCommissioningInfo : TLVPayload {
public required ushort FailSafeExpiryLengthSeconds { get; set; }
public required ushort MaxCumulativeFailsafeSeconds { get; set; }
public override void Serialize(TLVWriter writer, long structNumber = -1) {
@@ -88,8 +87,8 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
}
public struct ArmFailSafeResponse {
- public CommissioningErrorEnum ErrorCode { get; set; }
- public string DebugText { get; set; }
+ public required CommissioningErrorEnum ErrorCode { get; set; }
+ public required string DebugText { get; set; }
}
private record SetRegulatoryConfigPayload : TLVPayload {
@@ -107,7 +106,7 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
public struct SetRegulatoryConfigResponse {
public required CommissioningErrorEnum ErrorCode { get; set; }
- public required String DebugText { get; set; }
+ public required string DebugText { get; set; }
}
public struct CommissioningCompleteResponse {
@@ -125,7 +124,6 @@ public struct CommissioningCompleteResponse {
if (!validateResponse(resp))
return null;
return new ArmFailSafeResponse() {
-
ErrorCode = (CommissioningErrorEnum)(byte)GetField(resp, 0),
DebugText = (string)GetField(resp, 1),
};
@@ -158,7 +156,7 @@ public struct CommissioningCompleteResponse {
// Attributes
public ulong Breadcrumb { get; set; } = 0;
- public BasicCommissioningInfoStruct BasicCommissioningInfo { get; }
+ public BasicCommissioningInfo BasicCommissioningInfoField { get; }
public RegulatoryLocationTypeEnum RegulatoryConfig { get; } = RegulatoryLocationTypeEnum.IndoorOutdoor;
public RegulatoryLocationTypeEnum LocationCapability { get; } = RegulatoryLocationTypeEnum.IndoorOutdoor;
public bool SupportsConcurrentConnection { get; } = true;
diff --git a/MatterDotNet/Clusters/NodeOperationalCredentialsCluster.cs b/MatterDotNet/Clusters/NodeOperationalCredentialsCluster.cs
index 3ff6706..009cf58 100644
--- a/MatterDotNet/Clusters/NodeOperationalCredentialsCluster.cs
+++ b/MatterDotNet/Clusters/NodeOperationalCredentialsCluster.cs
@@ -13,6 +13,7 @@
// WARNING: This file was auto-generated. Do not edit.
using MatterDotNet.Messages.InteractionModel;
+using MatterDotNet.PKI;
using MatterDotNet.Protocol;
using MatterDotNet.Protocol.Parsers;
using MatterDotNet.Protocol.Payloads;
@@ -250,7 +251,7 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
};
}
- public async Task CSRRequest (SecureSession session, byte[] CSRNonce, bool IsForUpdateNOC) {
+ public async Task CSRRequest (SecureSession session, byte[] CSRNonce, bool? IsForUpdateNOC) {
CSRRequestPayload requestFields = new CSRRequestPayload() {
CSRNonce = CSRNonce,
IsForUpdateNOC = IsForUpdateNOC,
@@ -264,7 +265,7 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
};
}
- public async Task AddNOC (SecureSession session, byte[] NOCValue, byte[] ICACValue, byte[] IPKValue, ulong CaseAdminSubject, ushort AdminVendorId) {
+ public async Task AddNOC (SecureSession session, byte[] NOCValue, byte[]? ICACValue, byte[] IPKValue, ulong CaseAdminSubject, ushort AdminVendorId) {
AddNOCPayload requestFields = new AddNOCPayload() {
NOCValue = NOCValue,
ICACValue = ICACValue,
@@ -276,13 +277,13 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
if (!validateResponse(resp))
return null;
return new NOCResponse() {
- StatusCode = (NodeOperationalCertStatusEnum)GetField(resp, 0),
+ StatusCode = (NodeOperationalCertStatusEnum)(byte)GetField(resp, 0),
FabricIndex = (byte?)GetOptionalField(resp, 1),
DebugText = (string?)GetOptionalField(resp, 2),
};
}
- public async Task UpdateNOC (SecureSession session, byte[] NOCValue, byte[] ICACValue) {
+ public async Task UpdateNOC (SecureSession session, byte[] NOCValue, byte[]? ICACValue) {
UpdateNOCPayload requestFields = new UpdateNOCPayload() {
NOCValue = NOCValue,
ICACValue = ICACValue,
@@ -325,6 +326,13 @@ public override void Serialize(TLVWriter writer, long structNumber = -1) {
};
}
+ public Task AddTrustedRootCertificate(SecureSession session, OperationalCertificate RootCACertificate)
+ {
+ PayloadWriter payload = new PayloadWriter(600);
+ RootCACertificate.ToMatterCertificate().Serialize(payload);
+ return AddTrustedRootCertificate(session, payload.GetPayload().ToArray());
+ }
+
public async Task AddTrustedRootCertificate (SecureSession session, byte[] RootCACertificate) {
AddTrustedRootCertificatePayload requestFields = new AddTrustedRootCertificatePayload() {
RootCACertificate = RootCACertificate,
diff --git a/MatterDotNet/PKI/Fabric.cs b/MatterDotNet/PKI/Fabric.cs
index 11ac190..b7ef6a0 100644
--- a/MatterDotNet/PKI/Fabric.cs
+++ b/MatterDotNet/PKI/Fabric.cs
@@ -88,7 +88,7 @@ public OperationalCertificate Sign(CertificateRequest nocsr)
collection.Add(new Oid("1.3.6.1.5.5.7.3.2"));
signingCSR.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(collection, true));
signingCSR.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(nocsr.PublicKey, false));
- signingCSR.CertificateExtensions.Add(cert.Extensions.First(e => e is X509AuthorityKeyIdentifierExtension));
+ signingCSR.CertificateExtensions.Add(X509AuthorityKeyIdentifierExtension.CreateFromCertificate(cert, true, false));
byte[] serial = new byte[20];
Random.Shared.NextBytes(serial);
OperationalCertificate ret = new OperationalCertificate(signingCSR.Create(cert, DateTime.Now.Subtract(TimeSpan.FromSeconds(30)), DateTime.Now.AddYears(1), serial));
@@ -111,7 +111,7 @@ public OperationalCertificate Sign(byte[] publicKey, byte[] privateKey)
collection.Add(new Oid("1.3.6.1.5.5.7.3.2"));
signingCSR.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(collection, true));
signingCSR.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(key.ExportSubjectPublicKeyInfo(), false));
- signingCSR.CertificateExtensions.Add(cert.Extensions.First(e => e is X509AuthorityKeyIdentifierExtension));
+ signingCSR.CertificateExtensions.Add(X509AuthorityKeyIdentifierExtension.CreateFromCertificate(cert, true, false));
byte[] serial = new byte[20];
Random.Shared.NextBytes(serial);
OperationalCertificate ret = new OperationalCertificate(signingCSR.Create(cert, DateTime.Now.Subtract(TimeSpan.FromSeconds(30)), DateTime.Now.AddYears(1), serial));
diff --git a/MatterDotNet/Protocol/InteractionManager.cs b/MatterDotNet/Protocol/InteractionManager.cs
index e4ecdb5..f945521 100644
--- a/MatterDotNet/Protocol/InteractionManager.cs
+++ b/MatterDotNet/Protocol/InteractionManager.cs
@@ -88,6 +88,12 @@ public static async Task GetAttribute(SecureSession session,
}
}
+ public static Task SendCommand(SecureSession session, ushort endpoint, uint cluster, uint command, TLVPayload? payload = null)
+ {
+ using (Exchange exchange = session.CreateExchange())
+ return SendCommand(exchange, endpoint, cluster, command, payload);
+ }
+
public static async Task SendCommand(Exchange exchange, ushort endpoint, uint cluster, uint command, TLVPayload? payload = null)
{
InvokeRequestMessage run = new InvokeRequestMessage()
diff --git a/MatterDotNet/Protocol/TLV/TLVReader.cs b/MatterDotNet/Protocol/TLV/TLVReader.cs
index 1b63c6b..f505a52 100644
--- a/MatterDotNet/Protocol/TLV/TLVReader.cs
+++ b/MatterDotNet/Protocol/TLV/TLVReader.cs
@@ -351,7 +351,11 @@ public void EndContainer()
if (control == TLVControl.Anonymous)
structure.Add(GetAny(-1)!);
else
- structure.Insert((int)this.tagNumber, GetAny(this.tagNumber)!);
+ {
+ while (this.tagNumber > structure.Count)
+ structure.Add(null!);
+ structure.Add(GetAny(this.tagNumber)!);
+ }
}
EndContainer();
return structure.ToArray();
diff --git a/README.md b/README.md
index 738c160..25dbb0b 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,10 @@
* Framing & TLV Parsing / Generation
* Sessions & Exchanges
* QR Code / MDNS Payload Parsing
+* Device Commissioning
#### What's In Progress:
-* Device Commissioning
+* Cluster generation
#### Coming Soon
* Matter 1.3 Standard Implementation