diff --git a/Generator/ClusterGenerator.cs b/Generator/ClusterGenerator.cs index f2eeb5b..92e9f23 100644 --- a/Generator/ClusterGenerator.cs +++ b/Generator/ClusterGenerator.cs @@ -37,7 +37,7 @@ public static void Generate() if (cluster == null) throw new IOException("Failed to parse cluster " + clusterxml); if (!string.IsNullOrEmpty(cluster.clusterIds.clusterId.id)) - clusterBase.WriteLine($" case {cluster.name.Replace(" ", "").Replace('/', '_')}.CLUSTER_ID:\n return new {cluster.name.Replace(" ", "").Replace('/', '_')}(endPoint);"); + clusterBase.WriteLine($" case {GeneratorUtil.SanitizeClassName(cluster.name)}.CLUSTER_ID:\n return new {GeneratorUtil.SanitizeClassName(cluster.name)}(endPoint);"); WriteClass(cluster); } } @@ -95,7 +95,7 @@ private static void WriteClass(Cluster cluster, TextWriter writer) if (string.IsNullOrEmpty(cluster.classification.baseCluster) && !string.IsNullOrEmpty(cluster.clusterIds.clusterId.id)) writer.WriteLine($" /// \n protected {GeneratorUtil.SanitizeClassName(cluster.name)}(uint cluster, ushort endPoint) : base(cluster, endPoint) {{ }}"); writer.WriteLine(); - if (cluster.dataTypes?.@enum != null || (cluster.features != null && cluster.features.Length > 0)) + if (cluster.dataTypes?.@enum != null || cluster.dataTypes?.bitmap != null || (cluster.features != null && cluster.features.Length > 0)) { writer.WriteLine(" #region Enums"); bool firstEnum=true; @@ -174,7 +174,7 @@ private static void WriteClass(Cluster cluster, TextWriter writer) WriteCommands(cluster, writer); } - if (cluster.attributes.Length > 0 || (cluster.features != null && cluster.features.Length > 0)) + if ((cluster.attributes != null && cluster.attributes.Length > 0) || (cluster.features != null && cluster.features.Length > 0)) { writer.WriteLine(" #region Attributes"); bool firstAttribute = true; @@ -183,15 +183,18 @@ private static void WriteClass(Cluster cluster, TextWriter writer) firstAttribute = false; WriteFeatureFunctions(writer); } - foreach (var attribute in cluster.attributes) + if (cluster.attributes != null && cluster.attributes.Length > 0) { - if (attribute.type != null) + foreach (var attribute in cluster.attributes) { - if (firstAttribute) - firstAttribute = false; - else - writer.WriteLine(); - WriteAttribute(cluster, attribute, writer); + if (attribute.type != null && attribute?.mandatoryConform?.condition?.name != "Zigbee") + { + if (firstAttribute) + firstAttribute = false; + else + writer.WriteLine(); + WriteAttribute(cluster, attribute, writer); + } } } writer.WriteLine(" #endregion Attributes"); @@ -231,7 +234,7 @@ private static void WriteStruct(clusterCommand command, bool toServer, TextWrite if (field.type.EndsWith("Enum")) writer.WriteLine(" = " + field.type + "." + field.@default + ";"); else - writer.WriteLine(" = " + SanitizeDefault(field.@default, field.type) + ";"); + writer.WriteLine(" = " + SanitizeDefault(field.@default, field.type, field.entry?.type) + ";"); } else writer.WriteLine(); @@ -375,6 +378,7 @@ private static void WriteStructType(bool optional, bool nullable, string type, s case "namespace": case "fabric-idx": case "action-id": + case "percent": writer.Write($"{totalIndent}writer.WriteByte({id}, {name}"); if (to != null) writer.Write($", {to.Value}"); @@ -521,11 +525,13 @@ private static void WriteStructType(bool optional, bool nullable, string type, s case "ref_IpAdr": case "ref_Ipv4Adr": case "ref_Ipv6Adr": + case "ipv6adr": if (nullable && !optional) writer.Write($"{totalIndent}if ({name} == null)\n{totalIndent} writer.WriteNull({id});\n{totalIndent}else\n "); writer.WriteLine($"{totalIndent}writer.WriteBytes({id}, {name}.GetAddressBytes());"); return; case "Hardware Address": + case "hwadr": if (nullable && !optional) writer.Write($"{totalIndent}if ({name} == null)\n{totalIndent} writer.WriteNull({id});\n{totalIndent}else\n "); writer.WriteLine($"{totalIndent}writer.WriteBytes({id}, {name}.GetAddressBytes());"); @@ -623,6 +629,7 @@ private static void WriteFieldReader(bool optional, bool nullable, string type, case "namespace": case "fabric-idx": case "action-id": + case "percent": writer.Write($"reader.GetByte({id}"); break; case "uint16": @@ -672,9 +679,11 @@ private static void WriteFieldReader(bool optional, bool nullable, string type, writer.WriteLine($"new IPAddress(reader.GetBytes({id}, {(optional ? "true" : "false")}, 4, 4{(id == "-1" || id == "i" ? ")!))" : ")!)")};"); return; case "ref_Ipv6Adr": + case "ipv6adr": writer.WriteLine($"new IPAddress(reader.GetBytes({id}, {(optional ? "true" : "false")}, 16, 16{(id == "-1" || id == "i" ? ")!))" : ")!)")};"); return; case "Hardware Address": + case "hwadr": writer.WriteLine($"new PhysicalAddress(reader.GetBytes({id}, {(optional ? "true" : "false")}, 8, 6{(id == "-1" || id == "i" ? ")!))" : ")!)")};"); return; case "epoch-s": @@ -764,7 +773,7 @@ private static void WriteFieldReader(bool optional, bool nullable, string type, else if (id == "i") writer.WriteLine("(reader.GetStruct(i)!));"); else - writer.WriteLine($"fields[{id}]);"); + writer.WriteLine($"((object[])fields[{id}]);"); } return; } @@ -786,7 +795,7 @@ private static void WriteFieldReader(bool optional, bool nullable, string type, private static bool HasEnum(Cluster cluster, string name) { - if (cluster.dataTypes.@enum == null) + if (cluster.dataTypes?.@enum == null) return false; foreach (clusterDataTypesEnum enumType in cluster.dataTypes.@enum) { @@ -798,7 +807,7 @@ private static bool HasEnum(Cluster cluster, string name) private static bool HasEnumValue(Cluster cluster, string name, string value) { - if (cluster.dataTypes.@enum == null) + if (cluster.dataTypes?.@enum == null) return false; foreach (clusterDataTypesEnum enumType in cluster.dataTypes.@enum) { @@ -816,7 +825,7 @@ private static bool HasEnumValue(Cluster cluster, string name, string value) private static bool HasBitmap(Cluster cluster, string name) { - if (cluster.dataTypes.bitmap == null) + if (cluster.dataTypes?.bitmap == null) return false; foreach (clusterDataTypesBitfield bitfieldType in cluster.dataTypes.bitmap) { @@ -828,7 +837,7 @@ private static bool HasBitmap(Cluster cluster, string name) private static bool HasBitmapValue(Cluster cluster, string name, string value) { - if (cluster.dataTypes.bitmap == null) + if (cluster.dataTypes?.bitmap == null) return false; foreach (clusterDataTypesBitfield bitfieldType in cluster.dataTypes.bitmap) { @@ -846,7 +855,7 @@ private static bool HasBitmapValue(Cluster cluster, string name, string value) private static bool HasStruct(Cluster cluster, string name) { - if (cluster.dataTypes.@struct == null) + if (cluster.dataTypes?.@struct == null) return false; foreach (clusterDataTypesStruct structType in cluster.dataTypes.@struct) { @@ -1024,7 +1033,7 @@ private static void WriteRecord(clusterDataTypesStruct structType, Cluster clust if (HasEnum(cluster, field.type) || HasBitmap(cluster, field.type)) writer.WriteLine(" = " + field.type + "." + field.@default + ";"); else - writer.WriteLine(" = " + SanitizeDefault(field.@default!, field.type) + ";"); + writer.WriteLine(" = " + SanitizeDefault(field.@default!, field.type, field.entry?.type) + ";"); } else writer.WriteLine(); @@ -1079,9 +1088,12 @@ private static void WriteEnum(clusterDataTypesEnum enumType, TextWriter writer) writer.WriteLine(" public enum " + GeneratorUtil.SanitizeName(enumType.name) + " {"); foreach (clusterDataTypesEnumItem item in enumType.item) { - if (item.summary != null) - writer.WriteLine(" /// \n /// " + item.summary.Replace("[[ref_", "") + "\n /// "); - writer.WriteLine(" " + item.name + " = " + item.value + ","); + if (!string.IsNullOrWhiteSpace(item.value)) + { + if (item.summary != null) + writer.WriteLine(" /// \n /// " + item.summary.Replace("[[ref_", "") + "\n /// "); + writer.WriteLine(" " + GeneratorUtil.SanitizeName(item.name) + " = " + item.value + ","); + } } writer.WriteLine(" }"); } @@ -1097,7 +1109,7 @@ private static void WriteBitfield(clusterDataTypesBitfield enumType, TextWriter { if (item.summary != null) writer.WriteLine(" /// \n /// " + item.summary.Replace("[[ref_", "") + "\n /// "); - writer.WriteLine(" " + item.name + " = " + (1< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/ApplicationBasic.xml b/Generator/Clusters/ApplicationBasic.xml new file mode 100644 index 0000000..dffdea1 --- /dev/null +++ b/Generator/Clusters/ApplicationBasic.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/ApplicationLauncher.xml b/Generator/Clusters/ApplicationLauncher.xml new file mode 100644 index 0000000..e6dd0f1 --- /dev/null +++ b/Generator/Clusters/ApplicationLauncher.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/AudioOutput.xml b/Generator/Clusters/AudioOutput.xml new file mode 100644 index 0000000..1faf674 --- /dev/null +++ b/Generator/Clusters/AudioOutput.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/BallastConfiguration.xml b/Generator/Clusters/BallastConfiguration.xml new file mode 100644 index 0000000..f95fdd1 --- /dev/null +++ b/Generator/Clusters/BallastConfiguration.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/Binding-Cluster.xml b/Generator/Clusters/Binding-Cluster.xml new file mode 100644 index 0000000..b3dbcb3 --- /dev/null +++ b/Generator/Clusters/Binding-Cluster.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/BooleanState.xml b/Generator/Clusters/BooleanState.xml new file mode 100644 index 0000000..481ac3b --- /dev/null +++ b/Generator/Clusters/BooleanState.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/BooleanStateConfiguration.xml b/Generator/Clusters/BooleanStateConfiguration.xml new file mode 100644 index 0000000..668c6f8 --- /dev/null +++ b/Generator/Clusters/BooleanStateConfiguration.xml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/ConcentrationMeasurement.xml b/Generator/Clusters/ConcentrationMeasurement.xml new file mode 100644 index 0000000..e10fd8c --- /dev/null +++ b/Generator/Clusters/ConcentrationMeasurement.xml @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/DiagnosticsEthernet.xml b/Generator/Clusters/DiagnosticsEthernet.xml new file mode 100644 index 0000000..d8784cf --- /dev/null +++ b/Generator/Clusters/DiagnosticsEthernet.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/DiagnosticsSoftware.xml b/Generator/Clusters/DiagnosticsSoftware.xml new file mode 100644 index 0000000..992a61e --- /dev/null +++ b/Generator/Clusters/DiagnosticsSoftware.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/DiagnosticsThread.xml b/Generator/Clusters/DiagnosticsThread.xml new file mode 100644 index 0000000..82cba98 --- /dev/null +++ b/Generator/Clusters/DiagnosticsThread.xml @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/DiagnosticsWiFi.xml b/Generator/Clusters/DiagnosticsWiFi.xml new file mode 100644 index 0000000..ebbcd33 --- /dev/null +++ b/Generator/Clusters/DiagnosticsWiFi.xml @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/FanControl.xml b/Generator/Clusters/FanControl.xml new file mode 100644 index 0000000..b139691 --- /dev/null +++ b/Generator/Clusters/FanControl.xml @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/FlowMeasurement.xml b/Generator/Clusters/FlowMeasurement.xml new file mode 100644 index 0000000..7df2761 --- /dev/null +++ b/Generator/Clusters/FlowMeasurement.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/IlluminanceMeasurement.xml b/Generator/Clusters/IlluminanceMeasurement.xml new file mode 100644 index 0000000..0440901 --- /dev/null +++ b/Generator/Clusters/IlluminanceMeasurement.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/LowPower.xml b/Generator/Clusters/LowPower.xml new file mode 100644 index 0000000..a7e0ec0 --- /dev/null +++ b/Generator/Clusters/LowPower.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/NetworkCommissioningCluster.xml b/Generator/Clusters/NetworkCommissioningCluster.xml new file mode 100644 index 0000000..aa45dbe --- /dev/null +++ b/Generator/Clusters/NetworkCommissioningCluster.xml @@ -0,0 +1,513 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/OccupancySensing.xml b/Generator/Clusters/OccupancySensing.xml new file mode 100644 index 0000000..2e3fc57 --- /dev/null +++ b/Generator/Clusters/OccupancySensing.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/Switch.xml b/Generator/Clusters/Switch.xml new file mode 100644 index 0000000..1995226 --- /dev/null +++ b/Generator/Clusters/Switch.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/WakeOnLAN.xml b/Generator/Clusters/WakeOnLAN.xml new file mode 100644 index 0000000..0481c0e --- /dev/null +++ b/Generator/Clusters/WakeOnLAN.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/WaterContentMeasurement.xml b/Generator/Clusters/WaterContentMeasurement.xml new file mode 100644 index 0000000..0fbb6b4 --- /dev/null +++ b/Generator/Clusters/WaterContentMeasurement.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/Clusters/bridge-clusters-ActionsCluster.xml b/Generator/Clusters/bridge-clusters-ActionsCluster.xml new file mode 100644 index 0000000..a4ce24b --- /dev/null +++ b/Generator/Clusters/bridge-clusters-ActionsCluster.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Generator/GeneratorUtil.cs b/Generator/GeneratorUtil.cs index 6b9d9ce..4740869 100644 --- a/Generator/GeneratorUtil.cs +++ b/Generator/GeneratorUtil.cs @@ -22,6 +22,8 @@ public static string SanitizeName(string name) name = name.Substring(0, name.Length - 6); bool cap = true; StringBuilder ret = new StringBuilder(name.Length); + if (name.Length > 0 && Char.IsNumber(name[0])) + ret.Append('_'); foreach (char c in name) { if (c == ' ' || c == '-') @@ -61,7 +63,7 @@ public static string FieldNameToComment(string name) ret.Append(name[i]); } - return ret.ToString(); + return ret.ToString().Replace("Wi Fi", "WiFi"); } } } diff --git a/Generator/Schema/Cluster.cs b/Generator/Schema/Cluster.cs index 30c4e57..d37f008 100644 --- a/Generator/Schema/Cluster.cs +++ b/Generator/Schema/Cluster.cs @@ -654,6 +654,53 @@ public string name } } + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class attributeMandatoryConform + { + + private attributeMandatoryConformCondition conditionField; + + /// + public attributeMandatoryConformCondition condition + { + get + { + return this.conditionField; + } + set + { + this.conditionField = value; + } + } + } + + /// + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] + public partial class attributeMandatoryConformCondition + { + + private string nameField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + } + /// [System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] @@ -661,7 +708,7 @@ public string name public partial class clusterDataTypesBitfieldItem { - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private int bitField; @@ -670,7 +717,7 @@ public partial class clusterDataTypesBitfieldItem private string summaryField; /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { @@ -732,7 +779,7 @@ public string summary public partial class clusterDataTypesEnumItem { - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private string valueField; @@ -741,7 +788,7 @@ public partial class clusterDataTypesEnumItem private string summaryField; /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { @@ -863,7 +910,7 @@ public partial class clusterDataTypesStructField private clusterDataTypesStructFieldQuality qualityField; - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private clusterDataTypesStructFieldConstraint constraintField; @@ -915,7 +962,7 @@ public clusterDataTypesStructFieldQuality quality } /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { @@ -1198,7 +1245,7 @@ public partial class clusterAttribute private clusterAttributeQuality qualityField; - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private clusterAttributeConstraint constraintField; @@ -1252,7 +1299,7 @@ public clusterAttributeQuality quality } /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { @@ -1438,7 +1485,7 @@ public partial class clusterAttributeAccess private string readPrivilegeField; - private bool writeField; + private string writeField; private string writePrivilegeField; @@ -1476,7 +1523,7 @@ public string readPrivilege /// [System.Xml.Serialization.XmlAttributeAttribute()] - public bool write + public string write { get { @@ -1765,7 +1812,7 @@ public partial class clusterCommand private clusterCommandAccess accessField; - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private clusterCommandField[] fieldField; @@ -1804,7 +1851,7 @@ public clusterCommandAccess access } /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { @@ -1992,7 +2039,7 @@ public partial class clusterCommandField private object optionalConformField; - private object mandatoryConformField; + private attributeMandatoryConform mandatoryConformField; private object disallowConformField; @@ -2048,7 +2095,7 @@ public object optionalConform } /// - public object mandatoryConform + public attributeMandatoryConform mandatoryConform { get { diff --git a/MatterDotNet/Clusters/Application/ActionsCluster.cs b/MatterDotNet/Clusters/Application/ActionsCluster.cs new file mode 100644 index 0000000..ddc415b --- /dev/null +++ b/MatterDotNet/Clusters/Application/ActionsCluster.cs @@ -0,0 +1,609 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Actions Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class ActionsCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0025; + + /// + /// Actions Cluster + /// + public ActionsCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected ActionsCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Action Error + /// + public enum ActionErrorEnum { + /// + /// Other reason not listed in the row(s) below + /// + Unknown = 0, + /// + /// The action was interrupted by another command or interaction + /// + Interrupted = 1, + } + + /// + /// Action State + /// + public enum ActionStateEnum { + /// + /// The action is not active + /// + Inactive = 0, + /// + /// The action is active + /// + Active = 1, + /// + /// The action has been paused + /// + Paused = 2, + /// + /// The action has been disabled + /// + Disabled = 3, + } + + /// + /// Action Type + /// + public enum ActionTypeEnum { + /// + /// Use this only when none of the other values applies + /// + Other = 0, + /// + /// Bring the endpoints into a certain state + /// + Scene = 1, + /// + /// A sequence of states with a certain time pattern + /// + Sequence = 2, + /// + /// Control an automation (e.g. motion sensor controlling lights) + /// + Automation = 3, + /// + /// Sequence that will run when something doesn't happen + /// + Exception = 4, + /// + /// Use the endpoints to send a message to user + /// + Notification = 5, + /// + /// Higher priority notification + /// + Alarm = 6, + } + + /// + /// Endpoint List Type + /// + public enum EndpointListTypeEnum { + /// + /// Another group of endpoints + /// + Other = 0, + /// + /// User-configured group of endpoints where an endpoint can be in only one room + /// + Room = 1, + /// + /// User-configured group of endpoints where an endpoint can be in any number of zones + /// + Zone = 2, + } + + /// + /// Command Bits + /// + [Flags] + public enum CommandBits { + /// + /// Indicate support for InstantAction command + /// + InstantAction = 1, + /// + /// Indicate support for InstantActionWithTransition command + /// + InstantActionWithTransition = 2, + /// + /// Indicate support for StartAction command + /// + StartAction = 4, + /// + /// Indicate support for StartActionWithDuration command + /// + StartActionWithDuration = 8, + /// + /// Indicate support for StopAction command + /// + StopAction = 16, + /// + /// Indicate support for PauseAction command + /// + PauseAction = 32, + /// + /// Indicate support for PauseActionWithDuration command + /// + PauseActionWithDuration = 64, + /// + /// Indicate support for ResumeAction command + /// + ResumeAction = 128, + /// + /// Indicate support for EnableAction command + /// + EnableAction = 256, + /// + /// Indicate support for EnableActionWithDuration command + /// + EnableActionWithDuration = 512, + /// + /// Indicate support for DisableAction command + /// + DisableAction = 1024, + /// + /// Indicate support for DisableActionWithDuration command + /// + DisableActionWithDuration = 2048, + } + #endregion Enums + + #region Records + /// + /// Action + /// + public record Action : TLVPayload { + /// + /// Action + /// + public Action() { } + + [SetsRequiredMembers] + internal Action(object[] fields) { + FieldReader reader = new FieldReader(fields); + ActionID = reader.GetUShort(0)!.Value; + Name = reader.GetString(1, false)!; + Type = (ActionTypeEnum)reader.GetUShort(2)!.Value; + EndpointListID = reader.GetUShort(3)!.Value; + SupportedCommands = (CommandBits)reader.GetUShort(4)!.Value; + State = (ActionStateEnum)reader.GetUShort(5)!.Value; + } + public required ushort ActionID { get; set; } + public required string Name { get; set; } + public required ActionTypeEnum Type { get; set; } + public required ushort EndpointListID { get; set; } + public required CommandBits SupportedCommands { get; set; } + public required ActionStateEnum State { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + writer.WriteString(1, Name); + writer.WriteUShort(2, (ushort)Type); + writer.WriteUShort(3, EndpointListID); + writer.WriteUShort(4, (ushort)SupportedCommands); + writer.WriteUShort(5, (ushort)State); + writer.EndContainer(); + } + } + + /// + /// Endpoint List + /// + public record EndpointList : TLVPayload { + /// + /// Endpoint List + /// + public EndpointList() { } + + [SetsRequiredMembers] + internal EndpointList(object[] fields) { + FieldReader reader = new FieldReader(fields); + EndpointListID = reader.GetUShort(0)!.Value; + Name = reader.GetString(1, false)!; + Type = (EndpointListTypeEnum)reader.GetUShort(2)!.Value; + { + Endpoints = new List(); + foreach (var item in (List)fields[3]) { + Endpoints.Add(reader.GetUShort(-1)!.Value); + } + } + } + public required ushort EndpointListID { get; set; } + public required string Name { get; set; } + public required EndpointListTypeEnum Type { get; set; } + public required List Endpoints { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, EndpointListID); + writer.WriteString(1, Name); + writer.WriteUShort(2, (ushort)Type); + { + Constrain(Endpoints, 0, 256); + writer.StartList(3); + foreach (var item in Endpoints) { + writer.WriteUShort(-1, item); + } + writer.EndContainer(); + } + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + private record InstantActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record InstantActionWithTransitionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + public required ushort TransitionTime { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.WriteUShort(2, TransitionTime); + writer.EndContainer(); + } + } + + private record StartActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record StartActionWithDurationPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + public required uint Duration { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.WriteUInt(2, Duration); + writer.EndContainer(); + } + } + + private record StopActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record PauseActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record PauseActionWithDurationPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + public required uint Duration { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.WriteUInt(2, Duration); + writer.EndContainer(); + } + } + + private record ResumeActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record EnableActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record EnableActionWithDurationPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + public required uint Duration { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.WriteUInt(2, Duration); + writer.EndContainer(); + } + } + + private record DisableActionPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.EndContainer(); + } + } + + private record DisableActionWithDurationPayload : TLVPayload { + public required ushort ActionID { get; set; } + public uint? InvokeID { get; set; } + public required uint Duration { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, ActionID); + if (InvokeID != null) + writer.WriteUInt(1, InvokeID); + writer.WriteUInt(2, Duration); + writer.EndContainer(); + } + } + #endregion Payloads + + #region Commands + /// + /// Instant Action + /// + public async Task InstantAction(SecureSession session, ushort ActionID, uint? InvokeID) { + InstantActionPayload requestFields = new InstantActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + return ValidateResponse(resp); + } + + /// + /// Instant Action With Transition + /// + public async Task InstantActionWithTransition(SecureSession session, ushort ActionID, uint? InvokeID, ushort TransitionTime) { + InstantActionWithTransitionPayload requestFields = new InstantActionWithTransitionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + TransitionTime = TransitionTime, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x01, requestFields); + return ValidateResponse(resp); + } + + /// + /// Start Action + /// + public async Task StartAction(SecureSession session, ushort ActionID, uint? InvokeID) { + StartActionPayload requestFields = new StartActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x02, requestFields); + return ValidateResponse(resp); + } + + /// + /// Start Action With Duration + /// + public async Task StartActionWithDuration(SecureSession session, ushort ActionID, uint? InvokeID, uint Duration) { + StartActionWithDurationPayload requestFields = new StartActionWithDurationPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + Duration = Duration, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x03, requestFields); + return ValidateResponse(resp); + } + + /// + /// Stop Action + /// + public async Task StopAction(SecureSession session, ushort ActionID, uint? InvokeID) { + StopActionPayload requestFields = new StopActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x04, requestFields); + return ValidateResponse(resp); + } + + /// + /// Pause Action + /// + public async Task PauseAction(SecureSession session, ushort ActionID, uint? InvokeID) { + PauseActionPayload requestFields = new PauseActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x05, requestFields); + return ValidateResponse(resp); + } + + /// + /// Pause Action With Duration + /// + public async Task PauseActionWithDuration(SecureSession session, ushort ActionID, uint? InvokeID, uint Duration) { + PauseActionWithDurationPayload requestFields = new PauseActionWithDurationPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + Duration = Duration, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x06, requestFields); + return ValidateResponse(resp); + } + + /// + /// Resume Action + /// + public async Task ResumeAction(SecureSession session, ushort ActionID, uint? InvokeID) { + ResumeActionPayload requestFields = new ResumeActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x07, requestFields); + return ValidateResponse(resp); + } + + /// + /// Enable Action + /// + public async Task EnableAction(SecureSession session, ushort ActionID, uint? InvokeID) { + EnableActionPayload requestFields = new EnableActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x08, requestFields); + return ValidateResponse(resp); + } + + /// + /// Enable Action With Duration + /// + public async Task EnableActionWithDuration(SecureSession session, ushort ActionID, uint? InvokeID, uint Duration) { + EnableActionWithDurationPayload requestFields = new EnableActionWithDurationPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + Duration = Duration, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x09, requestFields); + return ValidateResponse(resp); + } + + /// + /// Disable Action + /// + public async Task DisableAction(SecureSession session, ushort ActionID, uint? InvokeID) { + DisableActionPayload requestFields = new DisableActionPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x0A, requestFields); + return ValidateResponse(resp); + } + + /// + /// Disable Action With Duration + /// + public async Task DisableActionWithDuration(SecureSession session, ushort ActionID, uint? InvokeID, uint Duration) { + DisableActionWithDurationPayload requestFields = new DisableActionWithDurationPayload() { + ActionID = ActionID, + InvokeID = InvokeID, + Duration = Duration, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x0B, requestFields); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Get the Action List attribute + /// + public async Task> GetActionList(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 0))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new Action(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Endpoint Lists attribute + /// + public async Task> GetEndpointLists(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 1))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new EndpointList(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Setup URL attribute + /// + public async Task GetSetupURL(SecureSession session) { + return (string?)(dynamic?)await GetAttribute(session, 2) ?? ""; + } + #endregion Attributes + + /// + public override string ToString() { + return "Actions Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/AirQualityCluster.cs b/MatterDotNet/Clusters/Application/AirQualityCluster.cs new file mode 100644 index 0000000..5fc32b9 --- /dev/null +++ b/MatterDotNet/Clusters/Application/AirQualityCluster.cs @@ -0,0 +1,129 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Air Quality Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class AirQualityCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x005B; + + /// + /// Air Quality Cluster + /// + public AirQualityCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected AirQualityCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Cluster supports the Fair air quality level + /// + Fair = 1, + /// + /// Cluster supports the Moderate air quality level + /// + Moderate = 2, + /// + /// Cluster supports the Very poor air quality level + /// + VeryPoor = 4, + /// + /// Cluster supports the Extremely poor air quality level + /// + ExtremelyPoor = 8, + } + + /// + /// Air Quality + /// + public enum AirQualityEnum { + /// + /// The air quality is unknown. + /// + Unknown = 0, + /// + /// The air quality is good. + /// + Good = 1, + /// + /// The air quality is fair. + /// + Fair = 2, + /// + /// The air quality is moderate. + /// + Moderate = 3, + /// + /// The air quality is poor. + /// + Poor = 4, + /// + /// The air quality is very poor. + /// + VeryPoor = 5, + /// + /// The air quality is extremely poor. + /// + ExtremelyPoor = 6, + } + #endregion Enums + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Air Quality attribute + /// + public async Task GetAirQuality(SecureSession session) { + return (AirQualityEnum)await GetEnumAttribute(session, 0); + } + #endregion Attributes + + /// + public override string ToString() { + return "Air Quality Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/ApplicationBasicCluster.cs b/MatterDotNet/Clusters/Application/ApplicationBasicCluster.cs new file mode 100644 index 0000000..be608f7 --- /dev/null +++ b/MatterDotNet/Clusters/Application/ApplicationBasicCluster.cs @@ -0,0 +1,155 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Application Basic Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class ApplicationBasicCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x050D; + + /// + /// Application Basic Cluster + /// + public ApplicationBasicCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected ApplicationBasicCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Application Status + /// + public enum ApplicationStatusEnum { + /// + /// Application is not running. + /// + Stopped = 0, + /// + /// Application is running, is visible to the user, and is the active target for input. + /// + ActiveVisibleFocus = 1, + /// + /// Application is running but not visible to the user. + /// + ActiveHidden = 2, + /// + /// Application is running and visible, but is not the active target for input. + /// + ActiveVisibleNotFocus = 3, + } + #endregion Enums + + #region Records + /// + /// Application + /// + public record Application : TLVPayload { + /// + /// Application + /// + public Application() { } + + [SetsRequiredMembers] + internal Application(object[] fields) { + FieldReader reader = new FieldReader(fields); + CatalogVendorID = reader.GetUShort(0)!.Value; + ApplicationID = reader.GetString(1, false)!; + } + public required ushort CatalogVendorID { get; set; } + public required string ApplicationID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, CatalogVendorID); + writer.WriteString(1, ApplicationID); + writer.EndContainer(); + } + } + #endregion Records + + #region Attributes + /// + /// Get the Vendor Name attribute + /// + public async Task GetVendorName(SecureSession session) { + return (string?)(dynamic?)await GetAttribute(session, 0) ?? ""; + } + + /// + /// Get the Vendor ID attribute + /// + public async Task GetVendorID(SecureSession session) { + return (ushort)(dynamic?)(await GetAttribute(session, 1))!; + } + + /// + /// Get the Application Name attribute + /// + public async Task GetApplicationName(SecureSession session) { + return (string)(dynamic?)(await GetAttribute(session, 2))!; + } + + /// + /// Get the Product ID attribute + /// + public async Task GetProductID(SecureSession session) { + return (ushort)(dynamic?)(await GetAttribute(session, 3))!; + } + + /// + /// Get the Application attribute + /// + public async Task GetApplication(SecureSession session) { + return new Application((object[])(await GetAttribute(session, 4))!); + } + + /// + /// Get the Status attribute + /// + public async Task GetStatus(SecureSession session) { + return (ApplicationStatusEnum)await GetEnumAttribute(session, 5); + } + + /// + /// Get the Application Version attribute + /// + public async Task GetApplicationVersion(SecureSession session) { + return (string)(dynamic?)(await GetAttribute(session, 6))!; + } + + /// + /// Get the Allowed Vendor List attribute + /// + public async Task> GetAllowedVendorList(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 7))!); + for (int i = 0; i < reader.Count; i++) + list.Add(reader.GetUShort(i)!.Value); + return list; + } + #endregion Attributes + + /// + public override string ToString() { + return "Application Basic Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/ApplicationLauncherCluster.cs b/MatterDotNet/Clusters/Application/ApplicationLauncherCluster.cs new file mode 100644 index 0000000..710c0fb --- /dev/null +++ b/MatterDotNet/Clusters/Application/ApplicationLauncherCluster.cs @@ -0,0 +1,260 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Application Launcher Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class ApplicationLauncherCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x050C; + + /// + /// Application Launcher Cluster + /// + public ApplicationLauncherCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected ApplicationLauncherCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Support for attributes and commands required for endpoint to support launching any application within the supported application catalogs + /// + ApplicationPlatform = 1, + } + + /// + /// Status + /// + public enum StatusEnum { + /// + /// Command succeeded + /// + Success = 0, + /// + /// Requested app is not available. + /// + AppNotAvailable = 1, + /// + /// Video platform unable to honor command. + /// + SystemBusy = 2, + } + #endregion Enums + + #region Records + /// + /// Application EP + /// + public record ApplicationEP : TLVPayload { + /// + /// Application EP + /// + public ApplicationEP() { } + + [SetsRequiredMembers] + internal ApplicationEP(object[] fields) { + FieldReader reader = new FieldReader(fields); + Application = new Application((object[])fields[0]); + Endpoint = reader.GetUShort(1, true); + } + public required Application Application { get; set; } + public ushort? Endpoint { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + Application.Serialize(writer, 0); + if (Endpoint != null) + writer.WriteUShort(1, Endpoint); + writer.EndContainer(); + } + } + + /// + /// Application + /// + public record Application : TLVPayload { + /// + /// Application + /// + public Application() { } + + [SetsRequiredMembers] + internal Application(object[] fields) { + FieldReader reader = new FieldReader(fields); + CatalogVendorID = reader.GetUShort(0)!.Value; + ApplicationID = reader.GetString(1, false)!; + } + public required ushort CatalogVendorID { get; set; } + public required string ApplicationID { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, CatalogVendorID); + writer.WriteString(1, ApplicationID); + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + private record LaunchAppPayload : TLVPayload { + public required Application Application { get; set; } + public byte[]? Data { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + Application.Serialize(writer, 0); + if (Data != null) + writer.WriteBytes(1, Data); + writer.EndContainer(); + } + } + + private record StopAppPayload : TLVPayload { + public required Application Application { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + Application.Serialize(writer, 0); + writer.EndContainer(); + } + } + + private record HideAppPayload : TLVPayload { + public required Application Application { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + Application.Serialize(writer, 0); + writer.EndContainer(); + } + } + + /// + /// Launcher Response - Reply from server + /// + public struct LauncherResponse() { + public required StatusEnum Status { get; set; } + public byte[]? Data { get; set; } + } + #endregion Payloads + + #region Commands + /// + /// Launch App + /// + public async Task LaunchApp(SecureSession session, Application Application, byte[]? Data) { + LaunchAppPayload requestFields = new LaunchAppPayload() { + Application = Application, + Data = Data, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + if (!ValidateResponse(resp)) + return null; + return new LauncherResponse() { + Status = (StatusEnum)(byte)GetField(resp, 0), + Data = (byte[]?)GetOptionalField(resp, 1), + }; + } + + /// + /// Stop App + /// + public async Task StopApp(SecureSession session, Application Application) { + StopAppPayload requestFields = new StopAppPayload() { + Application = Application, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x01, requestFields); + if (!ValidateResponse(resp)) + return null; + return new LauncherResponse() { + Status = (StatusEnum)(byte)GetField(resp, 0), + Data = (byte[]?)GetOptionalField(resp, 1), + }; + } + + /// + /// Hide App + /// + public async Task HideApp(SecureSession session, Application Application) { + HideAppPayload requestFields = new HideAppPayload() { + Application = Application, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x02, requestFields); + if (!ValidateResponse(resp)) + return null; + return new LauncherResponse() { + Status = (StatusEnum)(byte)GetField(resp, 0), + Data = (byte[]?)GetOptionalField(resp, 1), + }; + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Catalog List attribute + /// + public async Task> GetCatalogList(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 0))!); + for (int i = 0; i < reader.Count; i++) + list.Add(reader.GetUShort(i)!.Value); + return list; + } + + /// + /// Get the Current App attribute + /// + public async Task GetCurrentApp(SecureSession session) { + return new ApplicationEP((object[])(await GetAttribute(session, 1))!) ?? null; + } + #endregion Attributes + + /// + public override string ToString() { + return "Application Launcher Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/AudioOutputCluster.cs b/MatterDotNet/Clusters/Application/AudioOutputCluster.cs new file mode 100644 index 0000000..76efeeb --- /dev/null +++ b/MatterDotNet/Clusters/Application/AudioOutputCluster.cs @@ -0,0 +1,190 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Audio Output Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class AudioOutputCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x050B; + + /// + /// Audio Output Cluster + /// + public AudioOutputCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected AudioOutputCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Supports updates to output names + /// + NameUpdates = 1, + } + + /// + /// Output Type + /// + public enum OutputTypeEnum { + /// + /// HDMI + /// + HDMI = 0, + BT = 1, + Optical = 2, + Headphone = 3, + Internal = 4, + Other = 5, + } + #endregion Enums + + #region Records + /// + /// Output Info + /// + public record OutputInfo : TLVPayload { + /// + /// Output Info + /// + public OutputInfo() { } + + [SetsRequiredMembers] + internal OutputInfo(object[] fields) { + FieldReader reader = new FieldReader(fields); + Index = reader.GetByte(0)!.Value; + OutputType = (OutputTypeEnum)reader.GetUShort(1)!.Value; + Name = reader.GetString(2, false)!; + } + public required byte Index { get; set; } + public required OutputTypeEnum OutputType { get; set; } + public required string Name { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteByte(0, Index); + writer.WriteUShort(1, (ushort)OutputType); + writer.WriteString(2, Name); + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + private record SelectOutputPayload : TLVPayload { + public required byte Index { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteByte(0, Index); + writer.EndContainer(); + } + } + + private record RenameOutputPayload : TLVPayload { + public required byte Index { get; set; } + public required string Name { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteByte(0, Index); + writer.WriteString(1, Name); + writer.EndContainer(); + } + } + #endregion Payloads + + #region Commands + /// + /// Select Output + /// + public async Task SelectOutput(SecureSession session, byte Index) { + SelectOutputPayload requestFields = new SelectOutputPayload() { + Index = Index, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + return ValidateResponse(resp); + } + + /// + /// Rename Output + /// + public async Task RenameOutput(SecureSession session, byte Index, string Name) { + RenameOutputPayload requestFields = new RenameOutputPayload() { + Index = Index, + Name = Name, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x01, requestFields); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Output List attribute + /// + public async Task> GetOutputList(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 0))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new OutputInfo(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Current Output attribute + /// + public async Task GetCurrentOutput(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 1))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Audio Output Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/BallastConfigurationCluster.cs b/MatterDotNet/Clusters/Application/BallastConfigurationCluster.cs new file mode 100644 index 0000000..7a883eb --- /dev/null +++ b/MatterDotNet/Clusters/Application/BallastConfigurationCluster.cs @@ -0,0 +1,238 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Ballast Configuration Cluster + /// + [ClusterRevision(CLUSTER_ID, 4)] + public class BallastConfigurationCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0301; + + /// + /// Ballast Configuration Cluster + /// + public BallastConfigurationCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected BallastConfigurationCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Ballast Status Bitmap + /// + [Flags] + public enum BallastStatusBitmap { + /// + /// Operational state of the ballast. + /// + BallastNonOperational = 1, + /// + /// Operational state of the lamps. + /// + LampFailure = 2, + } + + /// + /// Lamp Alarm Mode Bitmap + /// + [Flags] + public enum LampAlarmModeBitmap { + /// + /// State of LampBurnHours alarm generation + /// + LampBurnHours = 1, + } + #endregion Enums + + #region Attributes + /// + /// Get the Physical Min Level attribute + /// + public async Task GetPhysicalMinLevel(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 0) ?? 1; + } + + /// + /// Get the Physical Max Level attribute + /// + public async Task GetPhysicalMaxLevel(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 1) ?? 254; + } + + /// + /// Get the Ballast Status attribute + /// + public async Task GetBallastStatus(SecureSession session) { + return (BallastStatusBitmap)await GetEnumAttribute(session, 2); + } + + /// + /// Get the Min Level attribute + /// + public async Task GetMinLevel(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 16))!; + } + + /// + /// Set the Min Level attribute + /// + public async Task SetMinLevel (SecureSession session, byte value) { + await SetAttribute(session, 16, value); + } + + /// + /// Get the Max Level attribute + /// + public async Task GetMaxLevel(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 17))!; + } + + /// + /// Set the Max Level attribute + /// + public async Task SetMaxLevel (SecureSession session, byte value) { + await SetAttribute(session, 17, value); + } + + /// + /// Get the Intrinsic Ballast Factor attribute + /// + public async Task GetIntrinsicBallastFactor(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 20, true); + } + + /// + /// Set the Intrinsic Ballast Factor attribute + /// + public async Task SetIntrinsicBallastFactor (SecureSession session, byte? value) { + await SetAttribute(session, 20, value, true); + } + + /// + /// Get the Ballast Factor Adjustment attribute + /// + public async Task GetBallastFactorAdjustment(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 21, true) ?? null; + } + + /// + /// Set the Ballast Factor Adjustment attribute + /// + public async Task SetBallastFactorAdjustment (SecureSession session, byte? value = null) { + await SetAttribute(session, 21, value, true); + } + + /// + /// Get the Lamp Quantity attribute + /// + public async Task GetLampQuantity(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 32))!; + } + + /// + /// Get the Lamp Type attribute + /// + public async Task GetLampType(SecureSession session) { + return (string?)(dynamic?)await GetAttribute(session, 48) ?? ""; + } + + /// + /// Set the Lamp Type attribute + /// + public async Task SetLampType (SecureSession session, string? value = "") { + await SetAttribute(session, 48, value); + } + + /// + /// Get the Lamp Manufacturer attribute + /// + public async Task GetLampManufacturer(SecureSession session) { + return (string?)(dynamic?)await GetAttribute(session, 49) ?? ""; + } + + /// + /// Set the Lamp Manufacturer attribute + /// + public async Task SetLampManufacturer (SecureSession session, string? value = "") { + await SetAttribute(session, 49, value); + } + + /// + /// Get the Lamp Rated Hours attribute + /// + public async Task GetLampRatedHours(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 50, true) ?? null; + } + + /// + /// Set the Lamp Rated Hours attribute + /// + public async Task SetLampRatedHours (SecureSession session, uint? value = null) { + await SetAttribute(session, 50, value, true); + } + + /// + /// Get the Lamp Burn Hours attribute + /// + public async Task GetLampBurnHours(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 51, true) ?? 0; + } + + /// + /// Set the Lamp Burn Hours attribute + /// + public async Task SetLampBurnHours (SecureSession session, uint? value = 0) { + await SetAttribute(session, 51, value, true); + } + + /// + /// Get the Lamp Alarm Mode attribute + /// + public async Task GetLampAlarmMode(SecureSession session) { + return (LampAlarmModeBitmap)await GetEnumAttribute(session, 52); + } + + /// + /// Set the Lamp Alarm Mode attribute + /// + public async Task SetLampAlarmMode (SecureSession session, LampAlarmModeBitmap value) { + await SetAttribute(session, 52, value); + } + + /// + /// Get the Lamp Burn Hours Trip Point attribute + /// + public async Task GetLampBurnHoursTripPoint(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 53, true) ?? null; + } + + /// + /// Set the Lamp Burn Hours Trip Point attribute + /// + public async Task SetLampBurnHoursTripPoint (SecureSession session, uint? value = null) { + await SetAttribute(session, 53, value, true); + } + #endregion Attributes + + /// + public override string ToString() { + return "Ballast Configuration Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/BooleanStateCluster.cs b/MatterDotNet/Clusters/Application/BooleanStateCluster.cs new file mode 100644 index 0000000..074ea38 --- /dev/null +++ b/MatterDotNet/Clusters/Application/BooleanStateCluster.cs @@ -0,0 +1,49 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Boolean State Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class BooleanStateCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0045; + + /// + /// Boolean State Cluster + /// + public BooleanStateCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected BooleanStateCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Attributes + /// + /// Get the State Value attribute + /// + public async Task GetStateValue(SecureSession session) { + return (bool)(dynamic?)(await GetAttribute(session, 0))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Boolean State Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/BooleanStateConfigurationCluster.cs b/MatterDotNet/Clusters/Application/BooleanStateConfigurationCluster.cs new file mode 100644 index 0000000..23bd5e6 --- /dev/null +++ b/MatterDotNet/Clusters/Application/BooleanStateConfigurationCluster.cs @@ -0,0 +1,224 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Boolean State Configuration Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class BooleanStateConfigurationCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0080; + + /// + /// Boolean State Configuration Cluster + /// + public BooleanStateConfigurationCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected BooleanStateConfigurationCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Supports visual alarms + /// + Visual = 1, + /// + /// Supports audible alarms + /// + Audible = 2, + /// + /// Supports ability to suppress or acknowledge alarms + /// + AlarmSuppress = 4, + /// + /// Supports ability to set sensor sensitivity + /// + SensitivityLevel = 8, + } + + /// + /// Alarm Mode Bitmap + /// + [Flags] + public enum AlarmModeBitmap { + /// + /// Visual alarming + /// + Visual = 1, + /// + /// Audible alarming + /// + Audible = 2, + } + + /// + /// Sensor Fault Bitmap + /// + [Flags] + public enum SensorFaultBitmap { + /// + /// Unspecified fault detected + /// + GeneralFault = 1, + } + #endregion Enums + + #region Payloads + private record SuppressAlarmPayload : TLVPayload { + public required AlarmModeBitmap AlarmsToSuppress { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, (ushort)AlarmsToSuppress); + writer.EndContainer(); + } + } + + private record EnableDisableAlarmPayload : TLVPayload { + public required AlarmModeBitmap AlarmsToEnableDisable { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, (ushort)AlarmsToEnableDisable); + writer.EndContainer(); + } + } + #endregion Payloads + + #region Commands + /// + /// Suppress Alarm + /// + public async Task SuppressAlarm(SecureSession session, AlarmModeBitmap AlarmsToSuppress) { + SuppressAlarmPayload requestFields = new SuppressAlarmPayload() { + AlarmsToSuppress = AlarmsToSuppress, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + return ValidateResponse(resp); + } + + /// + /// Enable Disable Alarm + /// + public async Task EnableDisableAlarm(SecureSession session, AlarmModeBitmap AlarmsToEnableDisable) { + EnableDisableAlarmPayload requestFields = new EnableDisableAlarmPayload() { + AlarmsToEnableDisable = AlarmsToEnableDisable, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x01, requestFields); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Current Sensitivity Level attribute + /// + public async Task GetCurrentSensitivityLevel(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 0))!; + } + + /// + /// Set the Current Sensitivity Level attribute + /// + public async Task SetCurrentSensitivityLevel (SecureSession session, byte value) { + await SetAttribute(session, 0, value); + } + + /// + /// Get the Supported Sensitivity Levels attribute + /// + public async Task GetSupportedSensitivityLevels(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 1))!; + } + + /// + /// Get the Default Sensitivity Level attribute + /// + public async Task GetDefaultSensitivityLevel(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 2))!; + } + + /// + /// Get the Alarms Active attribute + /// + public async Task GetAlarmsActive(SecureSession session) { + return (AlarmModeBitmap)await GetEnumAttribute(session, 3); + } + + /// + /// Get the Alarms Suppressed attribute + /// + public async Task GetAlarmsSuppressed(SecureSession session) { + return (AlarmModeBitmap)await GetEnumAttribute(session, 4); + } + + /// + /// Get the Alarms Enabled attribute + /// + public async Task GetAlarmsEnabled(SecureSession session) { + return (AlarmModeBitmap)await GetEnumAttribute(session, 5); + } + + /// + /// Get the Alarms Supported attribute + /// + public async Task GetAlarmsSupported(SecureSession session) { + return (AlarmModeBitmap)await GetEnumAttribute(session, 6); + } + + /// + /// Get the Sensor Fault attribute + /// + public async Task GetSensorFault(SecureSession session) { + return (SensorFaultBitmap)await GetEnumAttribute(session, 7); + } + #endregion Attributes + + /// + public override string ToString() { + return "Boolean State Configuration Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/ConcentrationMeasurementClusters.cs b/MatterDotNet/Clusters/Application/ConcentrationMeasurementClusters.cs new file mode 100644 index 0000000..b4a8d6d --- /dev/null +++ b/MatterDotNet/Clusters/Application/ConcentrationMeasurementClusters.cs @@ -0,0 +1,255 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Concentration Measurement Clusters + /// + [ClusterRevision(CLUSTER_ID, 3)] + public class ConcentrationMeasurementClusters : ClusterBase + { + internal const uint CLUSTER_ID = 0x040C; + + /// + /// Concentration Measurement Clusters + /// + public ConcentrationMeasurementClusters(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected ConcentrationMeasurementClusters(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Cluster supports numeric measurement of substance + /// + NumericMeasurement = 1, + /// + /// Cluster supports basic level indication for substance using the ConcentrationLevel enum + /// + LevelIndication = 2, + /// + /// Cluster supports the Medium Concentration Level + /// + MediumLevel = 4, + /// + /// Cluster supports the Critical Concentration Level + /// + CriticalLevel = 8, + /// + /// Cluster supports peak numeric measurement of substance + /// + PeakMeasurement = 16, + /// + /// Cluster supports average numeric measurement of substance + /// + AverageMeasurement = 32, + } + + /// + /// Level Value + /// + public enum LevelValueEnum { + /// + /// The level is Unknown + /// + Unknown = 0, + /// + /// The level is considered Low + /// + Low = 1, + /// + /// The level is considered Medium + /// + Medium = 2, + /// + /// The level is considered High + /// + High = 3, + /// + /// The level is considered Critical + /// + Critical = 4, + } + + /// + /// Measurement Medium + /// + public enum MeasurementMediumEnum { + /// + /// The measurement is being made in Air + /// + Air = 0, + /// + /// The measurement is being made in Water + /// + Water = 1, + /// + /// The measurement is being made in Soil + /// + Soil = 2, + } + + /// + /// Measurement Unit + /// + public enum MeasurementUnitEnum { + /// + /// Parts per Million (10) + /// + PPM = 0, + /// + /// Parts per Billion (10) + /// + PPB = 1, + /// + /// Parts per Trillion (10) + /// + PPT = 2, + /// + /// Milligram per m + /// + MGM3 = 3, + /// + /// Microgram per m + /// + UGM3 = 4, + /// + /// Nanogram per m + /// + NGM3 = 5, + /// + /// Particles per m + /// + PM3 = 6, + /// + /// Becquerel per m + /// + BQM3 = 7, + } + #endregion Enums + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Measured Value attribute + /// + public async Task GetMeasuredValue(SecureSession session) { + return (float?)(dynamic?)await GetAttribute(session, 0, true) ?? null; + } + + /// + /// Get the Min Measured Value attribute + /// + public async Task GetMinMeasuredValue(SecureSession session) { + return (float?)(dynamic?)await GetAttribute(session, 1, true) ?? null; + } + + /// + /// Get the Max Measured Value attribute + /// + public async Task GetMaxMeasuredValue(SecureSession session) { + return (float?)(dynamic?)await GetAttribute(session, 2, true) ?? null; + } + + /// + /// Get the Peak Measured Value attribute + /// + public async Task GetPeakMeasuredValue(SecureSession session) { + return (float?)(dynamic?)await GetAttribute(session, 3, true) ?? null; + } + + /// + /// Get the Peak Measured Value Window attribute + /// + public async Task GetPeakMeasuredValueWindow(SecureSession session) { + return (TimeSpan?)(dynamic?)await GetAttribute(session, 4) ?? TimeSpan.FromSeconds(1); + } + + /// + /// Get the Average Measured Value attribute + /// + public async Task GetAverageMeasuredValue(SecureSession session) { + return (float?)(dynamic?)await GetAttribute(session, 5, true) ?? null; + } + + /// + /// Get the Average Measured Value Window attribute + /// + public async Task GetAverageMeasuredValueWindow(SecureSession session) { + return (TimeSpan?)(dynamic?)await GetAttribute(session, 6) ?? TimeSpan.FromSeconds(1); + } + + /// + /// Get the Uncertainty attribute + /// + public async Task GetUncertainty(SecureSession session) { + return (float)(dynamic?)(await GetAttribute(session, 7))!; + } + + /// + /// Get the Measurement Unit attribute + /// + public async Task GetMeasurementUnit(SecureSession session) { + return (MeasurementUnitEnum)await GetEnumAttribute(session, 8); + } + + /// + /// Get the Measurement Medium attribute + /// + public async Task GetMeasurementMedium(SecureSession session) { + return (MeasurementMediumEnum)await GetEnumAttribute(session, 9); + } + + /// + /// Get the Level Value attribute + /// + public async Task GetLevelValue(SecureSession session) { + return (LevelValueEnum)await GetEnumAttribute(session, 10); + } + #endregion Attributes + + /// + public override string ToString() { + return "Concentration Measurement Clusters"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/FanControlCluster.cs b/MatterDotNet/Clusters/Application/FanControlCluster.cs new file mode 100644 index 0000000..dfa999b --- /dev/null +++ b/MatterDotNet/Clusters/Application/FanControlCluster.cs @@ -0,0 +1,380 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Fan Control Cluster + /// + [ClusterRevision(CLUSTER_ID, 4)] + public class FanControlCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0202; + + /// + /// Fan Control Cluster + /// + public FanControlCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected FanControlCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// 0-SpeedMax Fan Speeds + /// + MultiSpeed = 1, + /// + /// Automatic mode supported for fan speed + /// + Auto = 2, + /// + /// Rocking movement supported + /// + Rocking = 4, + /// + /// Wind emulation supported + /// + Wind = 8, + /// + /// Step command supported + /// + Step = 16, + /// + /// Airflow Direction attribute is supported + /// + AirflowDirection = 32, + } + + /// + /// Airflow Direction + /// + public enum AirflowDirectionEnum { + /// + /// Airflow is in the forward direction + /// + Forward = 0, + /// + /// Airflow is in the reverse direction + /// + Reverse = 1, + } + + /// + /// Fan Mode + /// + public enum FanModeEnum { + /// + /// Fan is off + /// + Off = 0, + /// + /// Fan using low speed + /// + Low = 1, + /// + /// Fan using medium speed + /// + Medium = 2, + /// + /// Fan using high speed + /// + High = 3, + On = 4, + /// + /// Fan is using auto mode + /// + Auto = 5, + /// + /// Fan is using smart mode + /// + Smart = 6, + } + + /// + /// Fan Mode Sequence + /// + public enum FanModeSequenceEnum { + /// + /// Fan is capable of off, low, medium and high modes + /// + Off_Low_Med_High = 0, + /// + /// Fan is capable of off, low and high modes + /// + Off_Low_High = 1, + /// + /// Fan is capable of off, low, medium, high and auto modes + /// + Off_Low_Med_High_Auto = 2, + /// + /// Fan is capable of off, low, high and auto modes + /// + Off_Low_High_Auto = 3, + /// + /// Fan is capable of off, high and auto modes + /// + Off_High_Auto = 4, + /// + /// Fan is capable of off and high modes + /// + Off_High = 5, + } + + /// + /// Step Direction + /// + public enum StepDirectionEnum { + /// + /// Step moves in increasing direction + /// + Increase = 0, + /// + /// Step moves in decreasing direction + /// + Decrease = 1, + } + + /// + /// Rock Bitmap + /// + [Flags] + public enum RockBitmap { + /// + /// Indicate rock left to right + /// + RockLeftRight = 1, + /// + /// Indicate rock up and down + /// + RockUpDown = 2, + /// + /// Indicate rock around + /// + RockRound = 4, + } + + /// + /// Wind Bitmap + /// + [Flags] + public enum WindBitmap { + /// + /// Indicate sleep wind + /// + SleepWind = 1, + /// + /// Indicate natural wind + /// + NaturalWind = 2, + } + #endregion Enums + + #region Payloads + private record StepPayload : TLVPayload { + public required StepDirectionEnum Direction { get; set; } = StepDirectionEnum.Increase; + public bool? Wrap { get; set; } = false; + public bool? LowestOff { get; set; } = true; + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, (ushort)Direction); + if (Wrap != null) + writer.WriteBool(1, Wrap); + if (LowestOff != null) + writer.WriteBool(2, LowestOff); + writer.EndContainer(); + } + } + #endregion Payloads + + #region Commands + /// + /// Step + /// + public async Task Step(SecureSession session, StepDirectionEnum Direction, bool? Wrap, bool? LowestOff) { + StepPayload requestFields = new StepPayload() { + Direction = Direction, + Wrap = Wrap, + LowestOff = LowestOff, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Fan Mode attribute + /// + public async Task GetFanMode(SecureSession session) { + return (FanModeEnum)await GetEnumAttribute(session, 0); + } + + /// + /// Set the Fan Mode attribute + /// + public async Task SetFanMode (SecureSession session, FanModeEnum value) { + await SetAttribute(session, 0, value); + } + + /// + /// Get the Fan Mode Sequence attribute + /// + public async Task GetFanModeSequence(SecureSession session) { + return (FanModeSequenceEnum)await GetEnumAttribute(session, 1); + } + + /// + /// Get the Percent Setting attribute + /// + public async Task GetPercentSetting(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 2, true) ?? 0; + } + + /// + /// Set the Percent Setting attribute + /// + public async Task SetPercentSetting (SecureSession session, byte? value = 0) { + await SetAttribute(session, 2, value, true); + } + + /// + /// Get the Percent Current attribute + /// + public async Task GetPercentCurrent(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 3))!; + } + + /// + /// Get the Speed Max attribute + /// + public async Task GetSpeedMax(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 4))!; + } + + /// + /// Get the Speed Setting attribute + /// + public async Task GetSpeedSetting(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 5, true) ?? 0; + } + + /// + /// Set the Speed Setting attribute + /// + public async Task SetSpeedSetting (SecureSession session, byte? value = 0) { + await SetAttribute(session, 5, value, true); + } + + /// + /// Get the Speed Current attribute + /// + public async Task GetSpeedCurrent(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 6))!; + } + + /// + /// Get the Rock Support attribute + /// + public async Task GetRockSupport(SecureSession session) { + return (RockBitmap)await GetEnumAttribute(session, 7); + } + + /// + /// Get the Rock Setting attribute + /// + public async Task GetRockSetting(SecureSession session) { + return (RockBitmap)await GetEnumAttribute(session, 8); + } + + /// + /// Set the Rock Setting attribute + /// + public async Task SetRockSetting (SecureSession session, RockBitmap value) { + await SetAttribute(session, 8, value); + } + + /// + /// Get the Wind Support attribute + /// + public async Task GetWindSupport(SecureSession session) { + return (WindBitmap)await GetEnumAttribute(session, 9); + } + + /// + /// Get the Wind Setting attribute + /// + public async Task GetWindSetting(SecureSession session) { + return (WindBitmap)await GetEnumAttribute(session, 10); + } + + /// + /// Set the Wind Setting attribute + /// + public async Task SetWindSetting (SecureSession session, WindBitmap value) { + await SetAttribute(session, 10, value); + } + + /// + /// Get the Airflow Direction attribute + /// + public async Task GetAirflowDirection(SecureSession session) { + return (AirflowDirectionEnum)await GetEnumAttribute(session, 11); + } + + /// + /// Set the Airflow Direction attribute + /// + public async Task SetAirflowDirection (SecureSession session, AirflowDirectionEnum value) { + await SetAttribute(session, 11, value); + } + #endregion Attributes + + /// + public override string ToString() { + return "Fan Control Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/FlowMeasurementCluster.cs b/MatterDotNet/Clusters/Application/FlowMeasurementCluster.cs new file mode 100644 index 0000000..a9e2d2f --- /dev/null +++ b/MatterDotNet/Clusters/Application/FlowMeasurementCluster.cs @@ -0,0 +1,70 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Flow Measurement Cluster + /// + [ClusterRevision(CLUSTER_ID, 3)] + public class FlowMeasurementCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0404; + + /// + /// Flow Measurement Cluster + /// + public FlowMeasurementCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected FlowMeasurementCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Attributes + /// + /// Get the Measured Value attribute + /// + public async Task GetMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 0, true) ?? null; + } + + /// + /// Get the Min Measured Value attribute + /// + public async Task GetMinMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 1, true); + } + + /// + /// Get the Max Measured Value attribute + /// + public async Task GetMaxMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 2, true); + } + + /// + /// Get the Tolerance attribute + /// + public async Task GetTolerance(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 3) ?? 0; + } + #endregion Attributes + + /// + public override string ToString() { + return "Flow Measurement Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/IlluminanceMeasurementCluster.cs b/MatterDotNet/Clusters/Application/IlluminanceMeasurementCluster.cs new file mode 100644 index 0000000..684cf88 --- /dev/null +++ b/MatterDotNet/Clusters/Application/IlluminanceMeasurementCluster.cs @@ -0,0 +1,93 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Illuminance Measurement Cluster + /// + [ClusterRevision(CLUSTER_ID, 3)] + public class IlluminanceMeasurementCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0400; + + /// + /// Illuminance Measurement Cluster + /// + public IlluminanceMeasurementCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected IlluminanceMeasurementCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Light Sensor Type + /// + public enum LightSensorTypeEnum { + /// + /// Indicates photodiode sensor type + /// + Photodiode = 0, + /// + /// Indicates CMOS sensor type + /// + CMOS = 1, + } + #endregion Enums + + #region Attributes + /// + /// Get the Measured Value attribute + /// + public async Task GetMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 0, true) ?? 0; + } + + /// + /// Get the Min Measured Value attribute + /// + public async Task GetMinMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 1, true); + } + + /// + /// Get the Max Measured Value attribute + /// + public async Task GetMaxMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 2, true); + } + + /// + /// Get the Tolerance attribute + /// + public async Task GetTolerance(SecureSession session) { + return (ushort)(dynamic?)(await GetAttribute(session, 3))!; + } + + /// + /// Get the Light Sensor Type attribute + /// + public async Task GetLightSensorType(SecureSession session) { + return (LightSensorTypeEnum?)await GetEnumAttribute(session, 4, true); + } + #endregion Attributes + + /// + public override string ToString() { + return "Illuminance Measurement Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/LowPowerCluster.cs b/MatterDotNet/Clusters/Application/LowPowerCluster.cs new file mode 100644 index 0000000..4bb844c --- /dev/null +++ b/MatterDotNet/Clusters/Application/LowPowerCluster.cs @@ -0,0 +1,56 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Low Power Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class LowPowerCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0508; + + /// + /// Low Power Cluster + /// + public LowPowerCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected LowPowerCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Payloads + #endregion Payloads + + #region Commands + /// + /// Sleep + /// + public async Task Sleep(SecureSession session) { + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00); + return ValidateResponse(resp); + } + #endregion Commands + + + /// + public override string ToString() { + return "Low Power Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/OccupancySensingCluster.cs b/MatterDotNet/Clusters/Application/OccupancySensingCluster.cs new file mode 100644 index 0000000..8f46cfd --- /dev/null +++ b/MatterDotNet/Clusters/Application/OccupancySensingCluster.cs @@ -0,0 +1,243 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Occupancy Sensing Cluster + /// + [ClusterRevision(CLUSTER_ID, 4)] + public class OccupancySensingCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0406; + + /// + /// Occupancy Sensing Cluster + /// + public OccupancySensingCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected OccupancySensingCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Occupancy Sensor Type + /// + public enum OccupancySensorTypeEnum { + /// + /// Indicates a passive infrared sensor. + /// + PIR = 0, + /// + /// Indicates a ultrasonic sensor. + /// + Ultrasonic = 1, + /// + /// Indicates a passive infrared and ultrasonic sensor. + /// + PIRAndUltrasonic = 2, + /// + /// Indicates a physical contact sensor. + /// + PhysicalContact = 3, + } + + /// + /// Occupancy Bitmap + /// + [Flags] + public enum OccupancyBitmap { + /// + /// Indicates the sensed occupancy state + /// + Occupied = 1, + } + + /// + /// Occupancy Sensor Type Bitmap + /// + [Flags] + public enum OccupancySensorTypeBitmap { + /// + /// Indicates a passive infrared sensor. + /// + PIR = 1, + /// + /// Indicates a ultrasonic sensor. + /// + Ultrasonic = 2, + /// + /// Indicates a physical contact sensor. + /// + PhysicalContact = 4, + } + #endregion Enums + + #region Attributes + /// + /// Get the Occupancy attribute + /// + public async Task GetOccupancy(SecureSession session) { + return (OccupancyBitmap)await GetEnumAttribute(session, 0); + } + + /// + /// Get the Occupancy Sensor Type attribute + /// + public async Task GetOccupancySensorType(SecureSession session) { + return (OccupancySensorTypeEnum)await GetEnumAttribute(session, 1); + } + + /// + /// Get the Occupancy Sensor Type Bitmap attribute + /// + public async Task GetOccupancySensorTypeBitmap(SecureSession session) { + return (OccupancySensorTypeBitmap)await GetEnumAttribute(session, 2); + } + + /// + /// Get the PIR Occupied To Unoccupied Delay attribute + /// + public async Task GetPIROccupiedToUnoccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 16) ?? 0; + } + + /// + /// Set the PIR Occupied To Unoccupied Delay attribute + /// + public async Task SetPIROccupiedToUnoccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 16, value); + } + + /// + /// Get the PIR Unoccupied To Occupied Delay attribute + /// + public async Task GetPIRUnoccupiedToOccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 17) ?? 0; + } + + /// + /// Set the PIR Unoccupied To Occupied Delay attribute + /// + public async Task SetPIRUnoccupiedToOccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 17, value); + } + + /// + /// Get the PIR Unoccupied To Occupied Threshold attribute + /// + public async Task GetPIRUnoccupiedToOccupiedThreshold(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 18) ?? 1; + } + + /// + /// Set the PIR Unoccupied To Occupied Threshold attribute + /// + public async Task SetPIRUnoccupiedToOccupiedThreshold (SecureSession session, byte? value = 1) { + await SetAttribute(session, 18, value); + } + + /// + /// Get the Ultrasonic Occupied To Unoccupied Delay attribute + /// + public async Task GetUltrasonicOccupiedToUnoccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 32) ?? 0; + } + + /// + /// Set the Ultrasonic Occupied To Unoccupied Delay attribute + /// + public async Task SetUltrasonicOccupiedToUnoccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 32, value); + } + + /// + /// Get the Ultrasonic Unoccupied To Occupied Delay attribute + /// + public async Task GetUltrasonicUnoccupiedToOccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 33) ?? 0; + } + + /// + /// Set the Ultrasonic Unoccupied To Occupied Delay attribute + /// + public async Task SetUltrasonicUnoccupiedToOccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 33, value); + } + + /// + /// Get the Ultrasonic Unoccupied To Occupied Threshold attribute + /// + public async Task GetUltrasonicUnoccupiedToOccupiedThreshold(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 34) ?? 1; + } + + /// + /// Set the Ultrasonic Unoccupied To Occupied Threshold attribute + /// + public async Task SetUltrasonicUnoccupiedToOccupiedThreshold (SecureSession session, byte? value = 1) { + await SetAttribute(session, 34, value); + } + + /// + /// Get the Physical Contact Occupied To Unoccupied Delay attribute + /// + public async Task GetPhysicalContactOccupiedToUnoccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 48) ?? 0; + } + + /// + /// Set the Physical Contact Occupied To Unoccupied Delay attribute + /// + public async Task SetPhysicalContactOccupiedToUnoccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 48, value); + } + + /// + /// Get the Physical Contact Unoccupied To Occupied Delay attribute + /// + public async Task GetPhysicalContactUnoccupiedToOccupiedDelay(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 49) ?? 0; + } + + /// + /// Set the Physical Contact Unoccupied To Occupied Delay attribute + /// + public async Task SetPhysicalContactUnoccupiedToOccupiedDelay (SecureSession session, ushort? value = 0) { + await SetAttribute(session, 49, value); + } + + /// + /// Get the Physical Contact Unoccupied To Occupied Threshold attribute + /// + public async Task GetPhysicalContactUnoccupiedToOccupiedThreshold(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 50) ?? 1; + } + + /// + /// Set the Physical Contact Unoccupied To Occupied Threshold attribute + /// + public async Task SetPhysicalContactUnoccupiedToOccupiedThreshold (SecureSession session, byte? value = 1) { + await SetAttribute(session, 50, value); + } + #endregion Attributes + + /// + public override string ToString() { + return "Occupancy Sensing Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/SwitchCluster.cs b/MatterDotNet/Clusters/Application/SwitchCluster.cs new file mode 100644 index 0000000..fd33ca9 --- /dev/null +++ b/MatterDotNet/Clusters/Application/SwitchCluster.cs @@ -0,0 +1,113 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Switch Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class SwitchCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x003B; + + /// + /// Switch Cluster + /// + public SwitchCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected SwitchCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Switch is latching + /// + LatchingSwitch = 1, + /// + /// Switch is momentary + /// + MomentarySwitch = 2, + /// + /// Switch supports release + /// + MomentarySwitchRelease = 4, + /// + /// Switch supports long press + /// + MomentarySwitchLongPress = 8, + /// + /// Switch supports multi-press + /// + MomentarySwitchMultiPress = 16, + } + #endregion Enums + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Number Of Positions attribute + /// + public async Task GetNumberOfPositions(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 0) ?? 2; + } + + /// + /// Get the Current Position attribute + /// + public async Task GetCurrentPosition(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 1) ?? 0; + } + + /// + /// Get the Multi Press Max attribute + /// + public async Task GetMultiPressMax(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 2) ?? 2; + } + #endregion Attributes + + /// + public override string ToString() { + return "Switch Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/WakeOnLANCluster.cs b/MatterDotNet/Clusters/Application/WakeOnLANCluster.cs new file mode 100644 index 0000000..a88fcb3 --- /dev/null +++ b/MatterDotNet/Clusters/Application/WakeOnLANCluster.cs @@ -0,0 +1,57 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; +using System.Net; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Wake On LAN Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class WakeOnLANCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0503; + + /// + /// Wake On LAN Cluster + /// + public WakeOnLANCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected WakeOnLANCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Attributes + /// + /// Get the MAC Address attribute + /// + public async Task GetMACAddress(SecureSession session) { + return (string)(dynamic?)(await GetAttribute(session, 0))!; + } + + /// + /// Get the Link Local Address attribute + /// + public async Task GetLinkLocalAddress(SecureSession session) { + return (IPAddress)(dynamic?)(await GetAttribute(session, 1))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Wake On LAN Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Application/WaterContentMeasurementClusters.cs b/MatterDotNet/Clusters/Application/WaterContentMeasurementClusters.cs new file mode 100644 index 0000000..e36422d --- /dev/null +++ b/MatterDotNet/Clusters/Application/WaterContentMeasurementClusters.cs @@ -0,0 +1,70 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; + +namespace MatterDotNet.Clusters.Application +{ + /// + /// Water Content Measurement Clusters + /// + [ClusterRevision(CLUSTER_ID, 3)] + public class WaterContentMeasurementClusters : ClusterBase + { + internal const uint CLUSTER_ID = 0x0405; + + /// + /// Water Content Measurement Clusters + /// + public WaterContentMeasurementClusters(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected WaterContentMeasurementClusters(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Attributes + /// + /// Get the Measured Value attribute + /// + public async Task GetMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 0, true); + } + + /// + /// Get the Min Measured Value attribute + /// + public async Task GetMinMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 1, true); + } + + /// + /// Get the Max Measured Value attribute + /// + public async Task GetMaxMeasuredValue(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 2, true); + } + + /// + /// Get the Tolerance attribute + /// + public async Task GetTolerance(SecureSession session) { + return (ushort)(dynamic?)(await GetAttribute(session, 3))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Water Content Measurement Clusters"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/ClusterBase.cs b/MatterDotNet/Clusters/ClusterBase.cs index 1f546ba..e228388 100644 --- a/MatterDotNet/Clusters/ClusterBase.cs +++ b/MatterDotNet/Clusters/ClusterBase.cs @@ -243,16 +243,48 @@ public static ClusterBase Create(uint clusterId, ushort endPoint) return new AccessControlCluster(endPoint); case AdministratorCommissioningCluster.CLUSTER_ID: return new AdministratorCommissioningCluster(endPoint); + case AirQualityCluster.CLUSTER_ID: + return new AirQualityCluster(endPoint); + case ApplicationBasicCluster.CLUSTER_ID: + return new ApplicationBasicCluster(endPoint); + case ApplicationLauncherCluster.CLUSTER_ID: + return new ApplicationLauncherCluster(endPoint); + case AudioOutputCluster.CLUSTER_ID: + return new AudioOutputCluster(endPoint); + case BallastConfigurationCluster.CLUSTER_ID: + return new BallastConfigurationCluster(endPoint); case BasicInformationCluster.CLUSTER_ID: return new BasicInformationCluster(endPoint); + case BindingCluster.CLUSTER_ID: + return new BindingCluster(endPoint); + case BooleanStateCluster.CLUSTER_ID: + return new BooleanStateCluster(endPoint); + case BooleanStateConfigurationCluster.CLUSTER_ID: + return new BooleanStateConfigurationCluster(endPoint); + case ActionsCluster.CLUSTER_ID: + return new ActionsCluster(endPoint); case BridgedDeviceBasicInformationCluster.CLUSTER_ID: return new BridgedDeviceBasicInformationCluster(endPoint); case ColorControlCluster.CLUSTER_ID: return new ColorControlCluster(endPoint); + case ConcentrationMeasurementClusters.CLUSTER_ID: + return new ConcentrationMeasurementClusters(endPoint); case DescriptorCluster.CLUSTER_ID: return new DescriptorCluster(endPoint); + case EthernetNetworkDiagnosticsCluster.CLUSTER_ID: + return new EthernetNetworkDiagnosticsCluster(endPoint); case GeneralDiagnosticsCluster.CLUSTER_ID: return new GeneralDiagnosticsCluster(endPoint); + case SoftwareDiagnosticsCluster.CLUSTER_ID: + return new SoftwareDiagnosticsCluster(endPoint); + case ThreadNetworkDiagnosticsCluster.CLUSTER_ID: + return new ThreadNetworkDiagnosticsCluster(endPoint); + case WiFiNetworkDiagnosticsCluster.CLUSTER_ID: + return new WiFiNetworkDiagnosticsCluster(endPoint); + case FanControlCluster.CLUSTER_ID: + return new FanControlCluster(endPoint); + case FlowMeasurementCluster.CLUSTER_ID: + return new FlowMeasurementCluster(endPoint); case GeneralCommissioningCluster.CLUSTER_ID: return new GeneralCommissioningCluster(endPoint); case GroupKeyManagementCluster.CLUSTER_ID: @@ -261,19 +293,32 @@ public static ClusterBase Create(uint clusterId, ushort endPoint) return new GroupsCluster(endPoint); case IdentifyCluster.CLUSTER_ID: return new IdentifyCluster(endPoint); + case IlluminanceMeasurementCluster.CLUSTER_ID: + return new IlluminanceMeasurementCluster(endPoint); case FixedLabelCluster.CLUSTER_ID: return new FixedLabelCluster(endPoint); case UserLabelCluster.CLUSTER_ID: return new UserLabelCluster(endPoint); case LevelControlCluster.CLUSTER_ID: return new LevelControlCluster(endPoint); + case LowPowerCluster.CLUSTER_ID: + return new LowPowerCluster(endPoint); + case NetworkCommissioningCluster.CLUSTER_ID: + return new NetworkCommissioningCluster(endPoint); + case OccupancySensingCluster.CLUSTER_ID: + return new OccupancySensingCluster(endPoint); case On_OffCluster.CLUSTER_ID: return new On_OffCluster(endPoint); case NodeOperationalCredentialsCluster.CLUSTER_ID: return new NodeOperationalCredentialsCluster(endPoint); + case SwitchCluster.CLUSTER_ID: + return new SwitchCluster(endPoint); case TimeSynchronizationCluster.CLUSTER_ID: return new TimeSynchronizationCluster(endPoint); - + case WakeOnLANCluster.CLUSTER_ID: + return new WakeOnLANCluster(endPoint); + case WaterContentMeasurementClusters.CLUSTER_ID: + return new WaterContentMeasurementClusters(endPoint); default: return new UnknownCluster(clusterId, endPoint); } diff --git a/MatterDotNet/Clusters/Utility/BindingCluster.cs b/MatterDotNet/Clusters/Utility/BindingCluster.cs new file mode 100644 index 0000000..f710150 --- /dev/null +++ b/MatterDotNet/Clusters/Utility/BindingCluster.cs @@ -0,0 +1,96 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Binding Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class BindingCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x001E; + + /// + /// Binding Cluster + /// + public BindingCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected BindingCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Records + /// + /// Target + /// + public record Target : TLVPayload { + /// + /// Target + /// + public Target() { } + + [SetsRequiredMembers] + internal Target(object[] fields) { + FieldReader reader = new FieldReader(fields); + Node = reader.GetULong(1)!.Value; + Group = reader.GetUShort(2)!.Value; + Endpoint = reader.GetUShort(3)!.Value; + Cluster = reader.GetUInt(4, true); + } + public required ulong Node { get; set; } + public required ushort Group { get; set; } + public required ushort Endpoint { get; set; } + public uint? Cluster { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteULong(1, Node); + writer.WriteUShort(2, Group, ushort.MaxValue, 1); + writer.WriteUShort(3, Endpoint); + if (Cluster != null) + writer.WriteUInt(4, Cluster); + writer.EndContainer(); + } + } + #endregion Records + + #region Attributes + /// + /// Get the Binding attribute + /// + public async Task> GetBinding(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 0))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new Target(reader.GetStruct(i)!)); + return list; + } + + /// + /// Set the Binding attribute + /// + public async Task SetBinding (SecureSession session, List value) { + await SetAttribute(session, 0, value); + } + #endregion Attributes + + /// + public override string ToString() { + return "Binding Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Utility/EthernetNetworkDiagnosticsCluster.cs b/MatterDotNet/Clusters/Utility/EthernetNetworkDiagnosticsCluster.cs new file mode 100644 index 0000000..c39157d --- /dev/null +++ b/MatterDotNet/Clusters/Utility/EthernetNetworkDiagnosticsCluster.cs @@ -0,0 +1,204 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Ethernet Network Diagnostics Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class EthernetNetworkDiagnosticsCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0037; + + /// + /// Ethernet Network Diagnostics Cluster + /// + public EthernetNetworkDiagnosticsCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected EthernetNetworkDiagnosticsCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Node makes available the counts for the number of received and transmitted packets on the ethernet interface. + /// + PacketCounts = 1, + /// + /// Node makes available the counts for the number of errors that have occurred during the reception and transmission of packets on the ethernet interface. + /// + ErrorCounts = 2, + } + + /// + /// PHY Rate + /// + public enum PHYRateEnum { + /// + /// PHY rate is 10Mbps + /// + Rate10M = 0, + /// + /// PHY rate is 100Mbps + /// + Rate100M = 1, + /// + /// PHY rate is 1Gbps + /// + Rate1G = 2, + /// + /// PHY rate is 2.5Gbps + /// + Rate2_5G = 3, + /// + /// PHY rate is 5Gbps + /// + Rate5G = 4, + /// + /// PHY rate is 10Gbps + /// + Rate10G = 5, + /// + /// PHY rate is 40Gbps + /// + Rate40G = 6, + /// + /// PHY rate is 100Gbps + /// + Rate100G = 7, + /// + /// PHY rate is 200Gbps + /// + Rate200G = 8, + /// + /// PHY rate is 400Gbps + /// + Rate400G = 9, + } + #endregion Enums + + #region Payloads + #endregion Payloads + + #region Commands + /// + /// Reset Counts + /// + public async Task ResetCounts(SecureSession session) { + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the PHY Rate attribute + /// + public async Task GetPHYRate(SecureSession session) { + return (PHYRateEnum?)await GetEnumAttribute(session, 0, true); + } + + /// + /// Get the Full Duplex attribute + /// + public async Task GetFullDuplex(SecureSession session) { + return (bool?)(dynamic?)await GetAttribute(session, 1, true) ?? null; + } + + /// + /// Get the Packet Rx Count attribute + /// + public async Task GetPacketRxCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 2) ?? 0; + } + + /// + /// Get the Packet Tx Count attribute + /// + public async Task GetPacketTxCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 3) ?? 0; + } + + /// + /// Get the Tx Err Count attribute + /// + public async Task GetTxErrCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 4) ?? 0; + } + + /// + /// Get the Collision Count attribute + /// + public async Task GetCollisionCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 5) ?? 0; + } + + /// + /// Get the Overrun Count attribute + /// + public async Task GetOverrunCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 6) ?? 0; + } + + /// + /// Get the Carrier Detect attribute + /// + public async Task GetCarrierDetect(SecureSession session) { + return (bool?)(dynamic?)await GetAttribute(session, 7, true) ?? null; + } + + /// + /// Get the Time Since Reset attribute + /// + public async Task GetTimeSinceReset(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 8) ?? 0; + } + #endregion Attributes + + /// + public override string ToString() { + return "Ethernet Network Diagnostics Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Utility/NetworkCommissioningCluster.cs b/MatterDotNet/Clusters/Utility/NetworkCommissioningCluster.cs new file mode 100644 index 0000000..f45494e --- /dev/null +++ b/MatterDotNet/Clusters/Utility/NetworkCommissioningCluster.cs @@ -0,0 +1,653 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; +using System.Net.NetworkInformation; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Network Commissioning Cluster + /// + [ClusterRevision(CLUSTER_ID, 2)] + public class NetworkCommissioningCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0031; + + /// + /// Network Commissioning Cluster + /// + public NetworkCommissioningCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected NetworkCommissioningCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Wi-Fi related features + /// + WiFiNetworkInterface = 1, + /// + /// Thread related features + /// + ThreadNetworkInterface = 2, + /// + /// Ethernet related features + /// + EthernetNetworkInterface = 4, + } + + /// + /// Network Commissioning Status + /// + public enum NetworkCommissioningStatusEnum { + /// + /// OK, no error + /// + Success = 0, + /// + /// Value Outside Range + /// + OutOfRange = 1, + /// + /// A collection would exceed its size limit + /// + BoundsExceeded = 2, + /// + /// The NetworkID is not among the collection of added networks + /// + NetworkIDNotFound = 3, + /// + /// The NetworkID is already among the collection of added networks + /// + DuplicateNetworkID = 4, + /// + /// Cannot find AP: SSID Not found + /// + NetworkNotFound = 5, + /// + /// Cannot find AP: Mismatch on band/channels/regulatory domain / 2.4GHz vs 5GHz + /// + RegulatoryError = 6, + /// + /// Cannot associate due to authentication failure + /// + AuthFailure = 7, + /// + /// Cannot associate due to unsupported security mode + /// + UnsupportedSecurity = 8, + /// + /// Other association failure + /// + OtherConnectionFailure = 9, + /// + /// Failure to generate an IPv6 address + /// + IPV6Failed = 10, + /// + /// Failure to bind Wi-Fi +<->+ IP interfaces + /// + IPBindFailed = 11, + /// + /// Unknown error + /// + UnknownError = 12, + } + + /// + /// Wi Fi Band + /// + public enum WiFiBandEnum { + /// + /// 2.4GHz - 2.401GHz to 2.495GHz (802.11b/g/n/ax) + /// + _2G4 = 0, + /// + /// 3.65GHz - 3.655GHz to 3.695GHz (802.11y) + /// + _3G65 = 1, + /// + /// 5GHz - 5.150GHz to 5.895GHz (802.11a/n/ac/ax) + /// + _5G = 2, + /// + /// 6GHz - 5.925GHz to 7.125GHz (802.11ax / Wi-Fi 6E) + /// + _6G = 3, + /// + /// 60GHz - 57.24GHz to 70.20GHz (802.11ad/ay) + /// + _60G = 4, + /// + /// Sub-1GHz - 755MHz to 931MHz (802.11ah) + /// + _1G = 5, + } + + /// + /// Thread Capabilities Bitmap + /// + [Flags] + public enum ThreadCapabilitiesBitmap { + /// + /// Thread Border Router functionality is present + /// + IsBorderRouterCapable = 1, + /// + /// Router mode is supported (interface could be in router or REED mode) + /// + IsRouterCapable = 2, + /// + /// Sleepy end-device mode is supported + /// + IsSleepyEndDeviceCapable = 4, + /// + /// Device is a full Thread device (opposite of Minimal Thread Device) + /// + IsFullThreadDevice = 8, + /// + /// Synchronized sleepy end-device mode is supported + /// + IsSynchronizedSleepyEndDeviceCapable = 16, + } + + /// + /// Wi Fi Security Bitmap + /// + [Flags] + public enum WiFiSecurityBitmap { + /// + /// Supports unencrypted Wi-Fi + /// + Unencrypted = 1, + /// + /// Supports Wi-Fi using WEP security + /// + WEP = 2, + /// + /// Supports Wi-Fi using WPA-Personal security + /// + WPAPERSONAL = 4, + /// + /// Supports Wi-Fi using WPA2-Personal security + /// + WPA2PERSONAL = 8, + /// + /// Supports Wi-Fi using WPA3-Personal security + /// + WPA3PERSONAL = 16, + } + #endregion Enums + + #region Records + /// + /// Network Info + /// + public record NetworkInfo : TLVPayload { + /// + /// Network Info + /// + public NetworkInfo() { } + + [SetsRequiredMembers] + internal NetworkInfo(object[] fields) { + FieldReader reader = new FieldReader(fields); + NetworkID = reader.GetBytes(0, false, 32, 1 +)!; + Connected = reader.GetBool(1)!.Value; + } + public required byte[] NetworkID { get; set; } + public required bool Connected { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, NetworkID, 32, 1); + writer.WriteBool(1, Connected); + writer.EndContainer(); + } + } + + /// + /// Thread Interface Scan Result + /// + public record ThreadInterfaceScanResult : TLVPayload { + /// + /// Thread Interface Scan Result + /// + public ThreadInterfaceScanResult() { } + + [SetsRequiredMembers] + internal ThreadInterfaceScanResult(object[] fields) { + FieldReader reader = new FieldReader(fields); + PanId = reader.GetUShort(0)!.Value; + ExtendedPanId = reader.GetULong(1)!.Value; + NetworkName = reader.GetString(2, false, 16, 1)!; + Channel = reader.GetUShort(3)!.Value; + Version = reader.GetByte(4)!.Value; + ExtendedAddress = new PhysicalAddress(reader.GetBytes(5, false, 8, 6)!); + RSSI = reader.GetSByte(6)!.Value; + LQI = reader.GetByte(7)!.Value; + } + public required ushort PanId { get; set; } + public required ulong ExtendedPanId { get; set; } + public required string NetworkName { get; set; } + public required ushort Channel { get; set; } + public required byte Version { get; set; } + public required PhysicalAddress ExtendedAddress { get; set; } + public required sbyte RSSI { get; set; } + public required byte LQI { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, PanId, 65534); + writer.WriteULong(1, ExtendedPanId); + writer.WriteString(2, NetworkName, 16, 1); + writer.WriteUShort(3, Channel); + writer.WriteByte(4, Version); + writer.WriteBytes(5, ExtendedAddress.GetAddressBytes()); + writer.WriteSByte(6, RSSI); + writer.WriteByte(7, LQI); + writer.EndContainer(); + } + } + + /// + /// Wi Fi Interface Scan Result + /// + public record WiFiInterfaceScanResult : TLVPayload { + /// + /// Wi Fi Interface Scan Result + /// + public WiFiInterfaceScanResult() { } + + [SetsRequiredMembers] + internal WiFiInterfaceScanResult(object[] fields) { + FieldReader reader = new FieldReader(fields); + Security = (WiFiSecurityBitmap)reader.GetUShort(0)!.Value; + SSID = reader.GetBytes(1, false)!; + BSSID = reader.GetBytes(2, false)!; + Channel = reader.GetUShort(3)!.Value; + WiFiBand = (WiFiBandEnum)reader.GetUShort(4, true)!.Value; + RSSI = reader.GetSByte(5, true); + } + public required WiFiSecurityBitmap Security { get; set; } + public required byte[] SSID { get; set; } + public required byte[] BSSID { get; set; } + public required ushort Channel { get; set; } + public WiFiBandEnum? WiFiBand { get; set; } + public sbyte? RSSI { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, (ushort)Security); + writer.WriteBytes(1, SSID, 32); + writer.WriteBytes(2, BSSID, 6); + writer.WriteUShort(3, Channel); + if (WiFiBand != null) + writer.WriteUShort(4, (ushort?)WiFiBand); + if (RSSI != null) + writer.WriteSByte(5, RSSI); + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + private record ScanNetworksPayload : TLVPayload { + public byte[]? SSID { get; set; } = null; + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + if (SSID != null) + writer.WriteBytes(0, SSID, 32, 1); + if (Breadcrumb != null) + writer.WriteULong(1, Breadcrumb); + writer.EndContainer(); + } + } + + /// + /// Scan Networks Response - Reply from server + /// + public struct ScanNetworksResponse() { + public required NetworkCommissioningStatusEnum NetworkingStatus { get; set; } + public string? DebugText { get; set; } + public required List WiFiScanResults { get; set; } + public required List ThreadScanResults { get; set; } + } + + private record AddOrUpdateWiFiNetworkPayload : TLVPayload { + public required byte[] SSID { get; set; } + public required byte[] Credentials { get; set; } + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, SSID, 32); + writer.WriteBytes(1, Credentials, 64); + if (Breadcrumb != null) + writer.WriteULong(2, Breadcrumb); + writer.EndContainer(); + } + } + + private record AddOrUpdateThreadNetworkPayload : TLVPayload { + public required byte[] OperationalDataset { get; set; } + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, OperationalDataset, 254); + if (Breadcrumb != null) + writer.WriteULong(1, Breadcrumb); + writer.EndContainer(); + } + } + + private record RemoveNetworkPayload : TLVPayload { + public required byte[] NetworkID { get; set; } + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, NetworkID, 32, 1); + if (Breadcrumb != null) + writer.WriteULong(1, Breadcrumb); + writer.EndContainer(); + } + } + + /// + /// Network Config Response - Reply from server + /// + public struct NetworkConfigResponse() { + public required NetworkCommissioningStatusEnum NetworkingStatus { get; set; } + public string? DebugText { get; set; } + public byte? NetworkIndex { get; set; } + } + + private record ConnectNetworkPayload : TLVPayload { + public required byte[] NetworkID { get; set; } + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, NetworkID, 32, 1); + if (Breadcrumb != null) + writer.WriteULong(1, Breadcrumb); + writer.EndContainer(); + } + } + + /// + /// Connect Network Response - Reply from server + /// + public struct ConnectNetworkResponse() { + public required NetworkCommissioningStatusEnum NetworkingStatus { get; set; } + public string? DebugText { get; set; } + public required int ? ErrorValue { get; set; } + } + + private record ReorderNetworkPayload : TLVPayload { + public required byte[] NetworkID { get; set; } + public required byte NetworkIndex { get; set; } + public ulong? Breadcrumb { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBytes(0, NetworkID, 32, 1); + writer.WriteByte(1, NetworkIndex); + if (Breadcrumb != null) + writer.WriteULong(2, Breadcrumb); + writer.EndContainer(); + } + } + #endregion Payloads + + #region Commands + /// + /// Scan Networks + /// + public async Task ScanNetworks(SecureSession session, byte[]? SSID, ulong? Breadcrumb) { + ScanNetworksPayload requestFields = new ScanNetworksPayload() { + SSID = SSID, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00, requestFields); + if (!ValidateResponse(resp)) + return null; + return new ScanNetworksResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + WiFiScanResults = (List)GetField(resp, 2), + ThreadScanResults = (List)GetField(resp, 3), + }; + } + + /// + /// Add Or Update Wi Fi Network + /// + public async Task AddOrUpdateWiFiNetwork(SecureSession session, byte[] SSID, byte[] Credentials, ulong? Breadcrumb) { + AddOrUpdateWiFiNetworkPayload requestFields = new AddOrUpdateWiFiNetworkPayload() { + SSID = SSID, + Credentials = Credentials, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x02, requestFields); + if (!ValidateResponse(resp)) + return null; + return new NetworkConfigResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + NetworkIndex = (byte?)GetOptionalField(resp, 2), + }; + } + + /// + /// Add Or Update Thread Network + /// + public async Task AddOrUpdateThreadNetwork(SecureSession session, byte[] OperationalDataset, ulong? Breadcrumb) { + AddOrUpdateThreadNetworkPayload requestFields = new AddOrUpdateThreadNetworkPayload() { + OperationalDataset = OperationalDataset, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x03, requestFields); + if (!ValidateResponse(resp)) + return null; + return new NetworkConfigResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + NetworkIndex = (byte?)GetOptionalField(resp, 2), + }; + } + + /// + /// Remove Network + /// + public async Task RemoveNetwork(SecureSession session, byte[] NetworkID, ulong? Breadcrumb) { + RemoveNetworkPayload requestFields = new RemoveNetworkPayload() { + NetworkID = NetworkID, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x04, requestFields); + if (!ValidateResponse(resp)) + return null; + return new NetworkConfigResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + NetworkIndex = (byte?)GetOptionalField(resp, 2), + }; + } + + /// + /// Connect Network + /// + public async Task ConnectNetwork(SecureSession session, byte[] NetworkID, ulong? Breadcrumb) { + ConnectNetworkPayload requestFields = new ConnectNetworkPayload() { + NetworkID = NetworkID, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x06, requestFields); + if (!ValidateResponse(resp)) + return null; + return new ConnectNetworkResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + ErrorValue = (int )GetField(resp, 2), + }; + } + + /// + /// Reorder Network + /// + public async Task ReorderNetwork(SecureSession session, byte[] NetworkID, byte NetworkIndex, ulong? Breadcrumb) { + ReorderNetworkPayload requestFields = new ReorderNetworkPayload() { + NetworkID = NetworkID, + NetworkIndex = NetworkIndex, + Breadcrumb = Breadcrumb, + }; + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x08, requestFields); + if (!ValidateResponse(resp)) + return null; + return new NetworkConfigResponse() { + NetworkingStatus = (NetworkCommissioningStatusEnum)(byte)GetField(resp, 0), + DebugText = (string?)GetOptionalField(resp, 1), + NetworkIndex = (byte?)GetOptionalField(resp, 2), + }; + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Max Networks attribute + /// + public async Task GetMaxNetworks(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 0))!; + } + + /// + /// Get the Networks attribute + /// + public async Task> GetNetworks(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 1))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new NetworkInfo(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Scan Max Time Seconds attribute + /// + public async Task GetScanMaxTimeSeconds(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 2))!; + } + + /// + /// Get the Connect Max Time Seconds attribute + /// + public async Task GetConnectMaxTimeSeconds(SecureSession session) { + return (byte)(dynamic?)(await GetAttribute(session, 3))!; + } + + /// + /// Get the Interface Enabled attribute + /// + public async Task GetInterfaceEnabled(SecureSession session) { + return (bool?)(dynamic?)await GetAttribute(session, 4) ?? true; + } + + /// + /// Set the Interface Enabled attribute + /// + public async Task SetInterfaceEnabled (SecureSession session, bool? value = true) { + await SetAttribute(session, 4, value); + } + + /// + /// Get the Last Networking Status attribute + /// + public async Task GetLastNetworkingStatus(SecureSession session) { + return (NetworkCommissioningStatusEnum?)await GetEnumAttribute(session, 5, true); + } + + /// + /// Get the Last Network ID attribute + /// + public async Task GetLastNetworkID(SecureSession session) { + return (byte[]?)(dynamic?)await GetAttribute(session, 6, true) ?? null; + } + + /// + /// Get the Last Connect Error Value attribute + /// + public async Task GetLastConnectErrorValue(SecureSession session) { + return (int ?)(dynamic?)await GetAttribute(session, 7, true) ?? null; + } + + /// + /// Get the Supported Wi Fi Bands attribute + /// + public async Task> GetSupportedWiFiBands(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 8))!); + for (int i = 0; i < reader.Count; i++) + list.Add((WiFiBandEnum)reader.GetUShort(i)!.Value); + return list; + } + + /// + /// Get the Supported Thread Features attribute + /// + public async Task GetSupportedThreadFeatures(SecureSession session) { + return (ThreadCapabilitiesBitmap)await GetEnumAttribute(session, 9); + } + + /// + /// Get the Thread Version attribute + /// + public async Task GetThreadVersion(SecureSession session) { + return (ushort)(dynamic?)(await GetAttribute(session, 10))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Network Commissioning Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Utility/SoftwareDiagnosticsCluster.cs b/MatterDotNet/Clusters/Utility/SoftwareDiagnosticsCluster.cs new file mode 100644 index 0000000..97cda93 --- /dev/null +++ b/MatterDotNet/Clusters/Utility/SoftwareDiagnosticsCluster.cs @@ -0,0 +1,165 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Software Diagnostics Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class SoftwareDiagnosticsCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0034; + + /// + /// Software Diagnostics Cluster + /// + public SoftwareDiagnosticsCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected SoftwareDiagnosticsCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Node makes available the metrics for high watermark related to memory consumption. + /// + Watermarks = 1, + } + #endregion Enums + + #region Records + /// + /// Thread Metrics + /// + public record ThreadMetrics : TLVPayload { + /// + /// Thread Metrics + /// + public ThreadMetrics() { } + + [SetsRequiredMembers] + internal ThreadMetrics(object[] fields) { + FieldReader reader = new FieldReader(fields); + ID = reader.GetULong(0)!.Value; + Name = reader.GetString(1, true); + StackFreeCurrent = reader.GetUInt(2, true); + StackFreeMinimum = reader.GetUInt(3, true); + StackSize = reader.GetUInt(4, true); + } + public required ulong ID { get; set; } + public string? Name { get; set; } = ""; + public uint? StackFreeCurrent { get; set; } + public uint? StackFreeMinimum { get; set; } + public uint? StackSize { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteULong(0, ID); + if (Name != null) + writer.WriteString(1, Name, 8); + if (StackFreeCurrent != null) + writer.WriteUInt(2, StackFreeCurrent); + if (StackFreeMinimum != null) + writer.WriteUInt(3, StackFreeMinimum); + if (StackSize != null) + writer.WriteUInt(4, StackSize); + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + #endregion Payloads + + #region Commands + /// + /// Reset Watermarks + /// + public async Task ResetWatermarks(SecureSession session) { + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Thread Metrics attribute + /// + public async Task> GetThreadMetrics(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 0))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new ThreadMetrics(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Current Heap Free attribute + /// + public async Task GetCurrentHeapFree(SecureSession session) { + return (ulong)(dynamic?)(await GetAttribute(session, 1))!; + } + + /// + /// Get the Current Heap Used attribute + /// + public async Task GetCurrentHeapUsed(SecureSession session) { + return (ulong)(dynamic?)(await GetAttribute(session, 2))!; + } + + /// + /// Get the Current Heap High Watermark attribute + /// + public async Task GetCurrentHeapHighWatermark(SecureSession session) { + return (ulong)(dynamic?)(await GetAttribute(session, 3))!; + } + #endregion Attributes + + /// + public override string ToString() { + return "Software Diagnostics Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Utility/ThreadNetworkDiagnosticsCluster.cs b/MatterDotNet/Clusters/Utility/ThreadNetworkDiagnosticsCluster.cs new file mode 100644 index 0000000..9875742 --- /dev/null +++ b/MatterDotNet/Clusters/Utility/ThreadNetworkDiagnosticsCluster.cs @@ -0,0 +1,820 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Payloads; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; +using System.Diagnostics.CodeAnalysis; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Thread Network Diagnostics Cluster + /// + [ClusterRevision(CLUSTER_ID, 2)] + public class ThreadNetworkDiagnosticsCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0035; + + /// + /// Thread Network Diagnostics Cluster + /// + public ThreadNetworkDiagnosticsCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected ThreadNetworkDiagnosticsCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Server supports the counts for the number of received and transmitted packets on the Thread interface. + /// + PacketCounts = 1, + /// + /// Server supports the counts for the number of errors that have occurred during the reception and transmission of packets on the Thread interface. + /// + ErrorCounts = 2, + /// + /// Server supports the counts for various MLE layer happenings. + /// + MLECounts = 4, + /// + /// Server supports the counts for various MAC layer happenings. + /// + MACCounts = 8, + } + + /// + /// Connection Status + /// + public enum ConnectionStatusEnum { + /// + /// Node is connected + /// + Connected = 0, + /// + /// Node is not connected + /// + NotConnected = 1, + } + + /// + /// Network Fault + /// + public enum NetworkFaultEnum { + /// + /// Indicates an unspecified fault. + /// + Unspecified = 0, + /// + /// Indicates the Thread link is down. + /// + LinkDown = 1, + /// + /// Indicates there has been Thread hardware failure. + /// + HardwareFailure = 2, + /// + /// Indicates the Thread network is jammed. + /// + NetworkJammed = 3, + } + + /// + /// Routing Role + /// + public enum RoutingRoleEnum { + /// + /// Unspecified routing role. + /// + Unspecified = 0, + /// + /// The Node does not currently have a role as a result of the Thread interface not currently being configured or operational. + /// + Unassigned = 1, + /// + /// The Node acts as a Sleepy End Device with RX-off-when-idle sleepy radio behavior. + /// + SleepyEndDevice = 2, + /// + /// The Node acts as an End Device without RX-off-when-idle sleepy radio behavior. + /// + EndDevice = 3, + /// + /// The Node acts as an Router Eligible End Device. + /// + REED = 4, + /// + /// The Node acts as a Router Device. + /// + Router = 5, + /// + /// The Node acts as a Leader Device. + /// + Leader = 6, + } + #endregion Enums + + #region Records + /// + /// Neighbor Table + /// + public record NeighborTable : TLVPayload { + /// + /// Neighbor Table + /// + public NeighborTable() { } + + [SetsRequiredMembers] + internal NeighborTable(object[] fields) { + FieldReader reader = new FieldReader(fields); + ExtAddress = reader.GetULong(0)!.Value; + Age = reader.GetUInt(1)!.Value; + Rloc16 = reader.GetUShort(2)!.Value; + LinkFrameCounter = reader.GetUInt(3)!.Value; + MleFrameCounter = reader.GetUInt(4)!.Value; + LQI = reader.GetByte(5)!.Value; + AverageRssi = reader.GetSByte(6, true); + LastRssi = reader.GetSByte(7, true); + FrameErrorRate = reader.GetByte(8)!.Value; + MessageErrorRate = reader.GetByte(9)!.Value; + RxOnWhenIdle = reader.GetBool(10)!.Value; + FullThreadDevice = reader.GetBool(11)!.Value; + FullNetworkData = reader.GetBool(12)!.Value; + IsChild = reader.GetBool(13)!.Value; + } + public required ulong ExtAddress { get; set; } + public required uint Age { get; set; } + public required ushort Rloc16 { get; set; } + public required uint LinkFrameCounter { get; set; } + public required uint MleFrameCounter { get; set; } + public required byte LQI { get; set; } + public required sbyte? AverageRssi { get; set; } = null; + public required sbyte? LastRssi { get; set; } = null; + public required byte FrameErrorRate { get; set; } = 0; + public required byte MessageErrorRate { get; set; } = 0; + public required bool RxOnWhenIdle { get; set; } + public required bool FullThreadDevice { get; set; } + public required bool FullNetworkData { get; set; } + public required bool IsChild { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteULong(0, ExtAddress); + writer.WriteUInt(1, Age); + writer.WriteUShort(2, Rloc16); + writer.WriteUInt(3, LinkFrameCounter); + writer.WriteUInt(4, MleFrameCounter); + writer.WriteByte(5, LQI, 255); + writer.WriteSByte(6, AverageRssi, 0, -128); + writer.WriteSByte(7, LastRssi, 0, -128); + writer.WriteByte(8, FrameErrorRate, 100); + writer.WriteByte(9, MessageErrorRate, 100); + writer.WriteBool(10, RxOnWhenIdle); + writer.WriteBool(11, FullThreadDevice); + writer.WriteBool(12, FullNetworkData); + writer.WriteBool(13, IsChild); + writer.EndContainer(); + } + } + + /// + /// Operational Dataset Components + /// + public record OperationalDatasetComponents : TLVPayload { + /// + /// Operational Dataset Components + /// + public OperationalDatasetComponents() { } + + [SetsRequiredMembers] + internal OperationalDatasetComponents(object[] fields) { + FieldReader reader = new FieldReader(fields); + ActiveTimestampPresent = reader.GetBool(0)!.Value; + PendingTimestampPresent = reader.GetBool(1)!.Value; + MasterKeyPresent = reader.GetBool(2)!.Value; + NetworkNamePresent = reader.GetBool(3)!.Value; + ExtendedPanIdPresent = reader.GetBool(4)!.Value; + MeshLocalPrefixPresent = reader.GetBool(5)!.Value; + DelayPresent = reader.GetBool(6)!.Value; + PanIdPresent = reader.GetBool(7)!.Value; + ChannelPresent = reader.GetBool(8)!.Value; + PskcPresent = reader.GetBool(9)!.Value; + SecurityPolicyPresent = reader.GetBool(10)!.Value; + ChannelMaskPresent = reader.GetBool(11)!.Value; + } + public required bool ActiveTimestampPresent { get; set; } + public required bool PendingTimestampPresent { get; set; } + public required bool MasterKeyPresent { get; set; } + public required bool NetworkNamePresent { get; set; } + public required bool ExtendedPanIdPresent { get; set; } + public required bool MeshLocalPrefixPresent { get; set; } + public required bool DelayPresent { get; set; } + public required bool PanIdPresent { get; set; } + public required bool ChannelPresent { get; set; } + public required bool PskcPresent { get; set; } + public required bool SecurityPolicyPresent { get; set; } + public required bool ChannelMaskPresent { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteBool(0, ActiveTimestampPresent); + writer.WriteBool(1, PendingTimestampPresent); + writer.WriteBool(2, MasterKeyPresent); + writer.WriteBool(3, NetworkNamePresent); + writer.WriteBool(4, ExtendedPanIdPresent); + writer.WriteBool(5, MeshLocalPrefixPresent); + writer.WriteBool(6, DelayPresent); + writer.WriteBool(7, PanIdPresent); + writer.WriteBool(8, ChannelPresent); + writer.WriteBool(9, PskcPresent); + writer.WriteBool(10, SecurityPolicyPresent); + writer.WriteBool(11, ChannelMaskPresent); + writer.EndContainer(); + } + } + + /// + /// Route Table + /// + public record RouteTable : TLVPayload { + /// + /// Route Table + /// + public RouteTable() { } + + [SetsRequiredMembers] + internal RouteTable(object[] fields) { + FieldReader reader = new FieldReader(fields); + ExtAddress = reader.GetULong(0)!.Value; + Rloc16 = reader.GetUShort(1)!.Value; + RouterId = reader.GetByte(2)!.Value; + NextHop = reader.GetByte(3)!.Value; + PathCost = reader.GetByte(4)!.Value; + LQIIn = reader.GetByte(5)!.Value; + LQIOut = reader.GetByte(6)!.Value; + Age = reader.GetByte(7)!.Value; + Allocated = reader.GetBool(8)!.Value; + LinkEstablished = reader.GetBool(9)!.Value; + } + public required ulong ExtAddress { get; set; } + public required ushort Rloc16 { get; set; } + public required byte RouterId { get; set; } + public required byte NextHop { get; set; } + public required byte PathCost { get; set; } + public required byte LQIIn { get; set; } + public required byte LQIOut { get; set; } + public required byte Age { get; set; } + public required bool Allocated { get; set; } + public required bool LinkEstablished { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteULong(0, ExtAddress); + writer.WriteUShort(1, Rloc16); + writer.WriteByte(2, RouterId); + writer.WriteByte(3, NextHop); + writer.WriteByte(4, PathCost); + writer.WriteByte(5, LQIIn); + writer.WriteByte(6, LQIOut); + writer.WriteByte(7, Age); + writer.WriteBool(8, Allocated); + writer.WriteBool(9, LinkEstablished); + writer.EndContainer(); + } + } + + /// + /// Security Policy + /// + public record SecurityPolicy : TLVPayload { + /// + /// Security Policy + /// + public SecurityPolicy() { } + + [SetsRequiredMembers] + internal SecurityPolicy(object[] fields) { + FieldReader reader = new FieldReader(fields); + RotationTime = reader.GetUShort(0)!.Value; + Flags = reader.GetUShort(1)!.Value; + } + public required ushort RotationTime { get; set; } + public required ushort Flags { get; set; } + internal override void Serialize(TLVWriter writer, long structNumber = -1) { + writer.StartStructure(structNumber); + writer.WriteUShort(0, RotationTime); + writer.WriteUShort(1, Flags); + writer.EndContainer(); + } + } + #endregion Records + + #region Payloads + #endregion Payloads + + #region Commands + /// + /// Reset Counts + /// + public async Task ResetCounts(SecureSession session) { + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the Channel attribute + /// + public async Task GetChannel(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 0, true); + } + + /// + /// Get the Routing Role attribute + /// + public async Task GetRoutingRole(SecureSession session) { + return (RoutingRoleEnum?)await GetEnumAttribute(session, 1, true); + } + + /// + /// Get the Network Name attribute + /// + public async Task GetNetworkName(SecureSession session) { + return (string?)(dynamic?)await GetAttribute(session, 2, true); + } + + /// + /// Get the Pan Id attribute + /// + public async Task GetPanId(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 3, true); + } + + /// + /// Get the Extended Pan Id attribute + /// + public async Task GetExtendedPanId(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 4, true); + } + + /// + /// Get the Mesh Local Prefix attribute + /// + public async Task GetMeshLocalPrefix(SecureSession session) { + return (byte[]?)(dynamic?)await GetAttribute(session, 5, true); + } + + /// + /// Get the Overrun Count attribute + /// + public async Task GetOverrunCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 6) ?? 0; + } + + /// + /// Get the Neighbor Table attribute + /// + public async Task> GetNeighborTable(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 7))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new NeighborTable(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Route Table attribute + /// + public async Task> GetRouteTable(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 8))!); + for (int i = 0; i < reader.Count; i++) + list.Add(new RouteTable(reader.GetStruct(i)!)); + return list; + } + + /// + /// Get the Partition Id attribute + /// + public async Task GetPartitionId(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 9, true); + } + + /// + /// Get the Weighting attribute + /// + public async Task GetWeighting(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 10, true); + } + + /// + /// Get the Data Version attribute + /// + public async Task GetDataVersion(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 11, true); + } + + /// + /// Get the Stable Data Version attribute + /// + public async Task GetStableDataVersion(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 12, true); + } + + /// + /// Get the Leader Router Id attribute + /// + public async Task GetLeaderRouterId(SecureSession session) { + return (byte?)(dynamic?)await GetAttribute(session, 13, true); + } + + /// + /// Get the Detached Role Count attribute + /// + public async Task GetDetachedRoleCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 14) ?? 0; + } + + /// + /// Get the Child Role Count attribute + /// + public async Task GetChildRoleCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 15) ?? 0; + } + + /// + /// Get the Router Role Count attribute + /// + public async Task GetRouterRoleCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 16) ?? 0; + } + + /// + /// Get the Leader Role Count attribute + /// + public async Task GetLeaderRoleCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 17) ?? 0; + } + + /// + /// Get the Attach Attempt Count attribute + /// + public async Task GetAttachAttemptCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 18) ?? 0; + } + + /// + /// Get the Partition Id Change Count attribute + /// + public async Task GetPartitionIdChangeCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 19) ?? 0; + } + + /// + /// Get the Better Partition Attach Attempt Count attribute + /// + public async Task GetBetterPartitionAttachAttemptCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 20) ?? 0; + } + + /// + /// Get the Parent Change Count attribute + /// + public async Task GetParentChangeCount(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 21) ?? 0; + } + + /// + /// Get the Tx Total Count attribute + /// + public async Task GetTxTotalCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 22) ?? 0; + } + + /// + /// Get the Tx Unicast Count attribute + /// + public async Task GetTxUnicastCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 23) ?? 0; + } + + /// + /// Get the Tx Broadcast Count attribute + /// + public async Task GetTxBroadcastCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 24) ?? 0; + } + + /// + /// Get the Tx Ack Requested Count attribute + /// + public async Task GetTxAckRequestedCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 25) ?? 0; + } + + /// + /// Get the Tx Acked Count attribute + /// + public async Task GetTxAckedCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 26) ?? 0; + } + + /// + /// Get the Tx No Ack Requested Count attribute + /// + public async Task GetTxNoAckRequestedCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 27) ?? 0; + } + + /// + /// Get the Tx Data Count attribute + /// + public async Task GetTxDataCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 28) ?? 0; + } + + /// + /// Get the Tx Data Poll Count attribute + /// + public async Task GetTxDataPollCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 29) ?? 0; + } + + /// + /// Get the Tx Beacon Count attribute + /// + public async Task GetTxBeaconCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 30) ?? 0; + } + + /// + /// Get the Tx Beacon Request Count attribute + /// + public async Task GetTxBeaconRequestCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 31) ?? 0; + } + + /// + /// Get the Tx Other Count attribute + /// + public async Task GetTxOtherCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 32) ?? 0; + } + + /// + /// Get the Tx Retry Count attribute + /// + public async Task GetTxRetryCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 33) ?? 0; + } + + /// + /// Get the Tx Direct Max Retry Expiry Count attribute + /// + public async Task GetTxDirectMaxRetryExpiryCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 34) ?? 0; + } + + /// + /// Get the Tx Indirect Max Retry Expiry Count attribute + /// + public async Task GetTxIndirectMaxRetryExpiryCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 35) ?? 0; + } + + /// + /// Get the Tx Err Cca Count attribute + /// + public async Task GetTxErrCcaCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 36) ?? 0; + } + + /// + /// Get the Tx Err Abort Count attribute + /// + public async Task GetTxErrAbortCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 37) ?? 0; + } + + /// + /// Get the Tx Err Busy Channel Count attribute + /// + public async Task GetTxErrBusyChannelCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 38) ?? 0; + } + + /// + /// Get the Rx Total Count attribute + /// + public async Task GetRxTotalCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 39) ?? 0; + } + + /// + /// Get the Rx Unicast Count attribute + /// + public async Task GetRxUnicastCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 40) ?? 0; + } + + /// + /// Get the Rx Broadcast Count attribute + /// + public async Task GetRxBroadcastCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 41) ?? 0; + } + + /// + /// Get the Rx Data Count attribute + /// + public async Task GetRxDataCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 42) ?? 0; + } + + /// + /// Get the Rx Data Poll Count attribute + /// + public async Task GetRxDataPollCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 43) ?? 0; + } + + /// + /// Get the Rx Beacon Count attribute + /// + public async Task GetRxBeaconCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 44) ?? 0; + } + + /// + /// Get the Rx Beacon Request Count attribute + /// + public async Task GetRxBeaconRequestCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 45) ?? 0; + } + + /// + /// Get the Rx Other Count attribute + /// + public async Task GetRxOtherCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 46) ?? 0; + } + + /// + /// Get the Rx Address Filtered Count attribute + /// + public async Task GetRxAddressFilteredCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 47) ?? 0; + } + + /// + /// Get the Rx Dest Addr Filtered Count attribute + /// + public async Task GetRxDestAddrFilteredCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 48) ?? 0; + } + + /// + /// Get the Rx Duplicated Count attribute + /// + public async Task GetRxDuplicatedCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 49) ?? 0; + } + + /// + /// Get the Rx Err No Frame Count attribute + /// + public async Task GetRxErrNoFrameCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 50) ?? 0; + } + + /// + /// Get the Rx Err Unknown Neighbor Count attribute + /// + public async Task GetRxErrUnknownNeighborCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 51) ?? 0; + } + + /// + /// Get the Rx Err Invalid Src Addr Count attribute + /// + public async Task GetRxErrInvalidSrcAddrCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 52) ?? 0; + } + + /// + /// Get the Rx Err Sec Count attribute + /// + public async Task GetRxErrSecCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 53) ?? 0; + } + + /// + /// Get the Rx Err Fcs Count attribute + /// + public async Task GetRxErrFcsCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 54) ?? 0; + } + + /// + /// Get the Rx Err Other Count attribute + /// + public async Task GetRxErrOtherCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 55) ?? 0; + } + + /// + /// Get the Active Timestamp attribute + /// + public async Task GetActiveTimestamp(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 56, true) ?? 0; + } + + /// + /// Get the Pending Timestamp attribute + /// + public async Task GetPendingTimestamp(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 57, true) ?? 0; + } + + /// + /// Get the Delay attribute + /// + public async Task GetDelay(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 58, true) ?? 0; + } + + /// + /// Get the Security Policy attribute + /// + public async Task GetSecurityPolicy(SecureSession session) { + return new SecurityPolicy((object[])(await GetAttribute(session, 59))!); + } + + /// + /// Get the Channel Page0 Mask attribute + /// + public async Task GetChannelPage0Mask(SecureSession session) { + return (byte[]?)(dynamic?)await GetAttribute(session, 60, true); + } + + /// + /// Get the Operational Dataset Components attribute + /// + public async Task GetOperationalDatasetComponents(SecureSession session) { + return new OperationalDatasetComponents((object[])(await GetAttribute(session, 61))!); + } + + /// + /// Get the Active Network Faults List attribute + /// + public async Task> GetActiveNetworkFaultsList(SecureSession session) { + List list = new List(); + FieldReader reader = new FieldReader((IList)(await GetAttribute(session, 62))!); + for (int i = 0; i < reader.Count; i++) + list.Add((NetworkFaultEnum)reader.GetUShort(i)!.Value); + return list; + } + #endregion Attributes + + /// + public override string ToString() { + return "Thread Network Diagnostics Cluster"; + } + } +} \ No newline at end of file diff --git a/MatterDotNet/Clusters/Utility/Wi-FiNetworkDiagnosticsCluster.cs b/MatterDotNet/Clusters/Utility/Wi-FiNetworkDiagnosticsCluster.cs new file mode 100644 index 0000000..15f5631 --- /dev/null +++ b/MatterDotNet/Clusters/Utility/Wi-FiNetworkDiagnosticsCluster.cs @@ -0,0 +1,286 @@ +// MatterDotNet Copyright (C) 2025 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Affero General Public License for more details. +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// WARNING: This file was auto-generated. Do not edit. + +using MatterDotNet.Messages.InteractionModel; +using MatterDotNet.Protocol.Parsers; +using MatterDotNet.Protocol.Sessions; +using MatterDotNet.Protocol.Subprotocols; + +namespace MatterDotNet.Clusters.Utility +{ + /// + /// Wi-Fi Network Diagnostics Cluster + /// + [ClusterRevision(CLUSTER_ID, 1)] + public class WiFiNetworkDiagnosticsCluster : ClusterBase + { + internal const uint CLUSTER_ID = 0x0036; + + /// + /// Wi-Fi Network Diagnostics Cluster + /// + public WiFiNetworkDiagnosticsCluster(ushort endPoint) : base(CLUSTER_ID, endPoint) { } + /// + protected WiFiNetworkDiagnosticsCluster(uint cluster, ushort endPoint) : base(cluster, endPoint) { } + + #region Enums + /// + /// Supported Features + /// + [Flags] + public enum Feature { + /// + /// Node makes available the counts for the number of received and transmitted packets on the Wi-Fi interface. + /// + PacketCounts = 1, + /// + /// Node makes available the counts for the number of errors that have occurred during the reception and transmission of packets on the Wi-Fi interface. + /// + ErrorCounts = 2, + } + + /// + /// Association Failure Cause + /// + public enum AssociationFailureCauseEnum { + /// + /// The reason for the failure is unknown. + /// + Unknown = 0, + /// + /// An error occurred during association. + /// + AssociationFailed = 1, + /// + /// An error occurred during authentication. + /// + AuthenticationFailed = 2, + /// + /// The specified SSID could not be found. + /// + SsidNotFound = 3, + } + + /// + /// Connection Status + /// + public enum ConnectionStatusEnum { + /// + /// Indicate the node is connected + /// + Connected = 0, + /// + /// Indicate the node is not connected + /// + NotConnected = 1, + } + + /// + /// Security Type + /// + public enum SecurityTypeEnum { + /// + /// Indicate the usage of an unspecified Wi-Fi security type + /// + Unspecified = 0, + /// + /// Indicate the usage of no Wi-Fi security + /// + None = 1, + /// + /// Indicate the usage of WEP Wi-Fi security + /// + WEP = 2, + /// + /// Indicate the usage of WPA Wi-Fi security + /// + WPA = 3, + /// + /// Indicate the usage of WPA2 Wi-Fi security + /// + WPA2 = 4, + /// + /// Indicate the usage of WPA3 Wi-Fi security + /// + WPA3 = 5, + } + + /// + /// Wi Fi Version + /// + public enum WiFiVersionEnum { + /// + /// Indicate the network interface is currently using 802.11a against the wireless access point. + /// + a = 0, + /// + /// Indicate the network interface is currently using 802.11b against the wireless access point. + /// + b = 1, + /// + /// Indicate the network interface is currently using 802.11g against the wireless access point. + /// + g = 2, + /// + /// Indicate the network interface is currently using 802.11n against the wireless access point. + /// + n = 3, + /// + /// Indicate the network interface is currently using 802.11ac against the wireless access point. + /// + ac = 4, + /// + /// Indicate the network interface is currently using 802.11ax against the wireless access point. + /// + ax = 5, + /// + /// Indicate the network interface is currently using 802.11ah against the wireless access point. + /// + ah = 6, + } + #endregion Enums + + #region Payloads + #endregion Payloads + + #region Commands + /// + /// Reset Counts + /// + public async Task ResetCounts(SecureSession session) { + InvokeResponseIB resp = await InteractionManager.ExecCommand(session, endPoint, CLUSTER_ID, 0x00); + return ValidateResponse(resp); + } + #endregion Commands + + #region Attributes + /// + /// Features supported by this cluster + /// + /// + /// + public async Task GetSupportedFeatures(SecureSession session) + { + return (Feature)(byte)(await GetAttribute(session, 0xFFFC))!; + } + + /// + /// Returns true when the feature is supported by the cluster + /// + /// + /// + /// + public async Task Supports(SecureSession session, Feature feature) + { + return ((feature & await GetSupportedFeatures(session)) != 0); + } + + /// + /// Get the BSSID attribute + /// + public async Task GetBSSID(SecureSession session) { + return (byte[]?)(dynamic?)await GetAttribute(session, 0, true) ?? null; + } + + /// + /// Get the Security Type attribute + /// + public async Task GetSecurityType(SecureSession session) { + return (SecurityTypeEnum?)await GetEnumAttribute(session, 1, true); + } + + /// + /// Get the Wi Fi Version attribute + /// + public async Task GetWiFiVersion(SecureSession session) { + return (WiFiVersionEnum?)await GetEnumAttribute(session, 2, true); + } + + /// + /// Get the Channel Number attribute + /// + public async Task GetChannelNumber(SecureSession session) { + return (ushort?)(dynamic?)await GetAttribute(session, 3, true) ?? null; + } + + /// + /// Get the RSSI attribute + /// + public async Task GetRSSI(SecureSession session) { + return (sbyte?)(dynamic?)await GetAttribute(session, 4, true) ?? null; + } + + /// + /// Get the Beacon Lost Count attribute + /// + public async Task GetBeaconLostCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 5, true) ?? 0; + } + + /// + /// Get the Beacon Rx Count attribute + /// + public async Task GetBeaconRxCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 6, true) ?? 0; + } + + /// + /// Get the Packet Multicast Rx Count attribute + /// + public async Task GetPacketMulticastRxCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 7, true) ?? 0; + } + + /// + /// Get the Packet Multicast Tx Count attribute + /// + public async Task GetPacketMulticastTxCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 8, true) ?? 0; + } + + /// + /// Get the Packet Unicast Rx Count attribute + /// + public async Task GetPacketUnicastRxCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 9, true) ?? 0; + } + + /// + /// Get the Packet Unicast Tx Count attribute + /// + public async Task GetPacketUnicastTxCount(SecureSession session) { + return (uint?)(dynamic?)await GetAttribute(session, 10, true) ?? 0; + } + + /// + /// Get the Current Max Rate attribute + /// + public async Task GetCurrentMaxRate(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 11, true) ?? 0; + } + + /// + /// Get the Overrun Count attribute + /// + public async Task GetOverrunCount(SecureSession session) { + return (ulong?)(dynamic?)await GetAttribute(session, 12, true) ?? 0; + } + #endregion Attributes + + /// + public override string ToString() { + return "Wi-Fi Network Diagnostics Cluster"; + } + } +} \ No newline at end of file