diff --git a/RDMSharp/Metadata/DataTree.cs b/RDMSharp/Metadata/DataTree.cs new file mode 100644 index 0000000..4e6a3fa --- /dev/null +++ b/RDMSharp/Metadata/DataTree.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace RDMSharp.Metadata +{ + public readonly struct DataTree : IEquatable + { + public readonly string Name; + public readonly uint Index; + public readonly object? Value; + public readonly string? Unit; + public readonly DataTreeValueLabel[]? Labels; + public readonly DataTree[]? Children; + public readonly DataTreeIssue[]? Issues; + + private DataTree(string name, uint index, DataTreeIssue[]? issues = null) + { + Name = name; + Index = index; + Issues = issues; + } + public DataTree(DataTree dataTree, uint index) : this(dataTree.Name, index, dataTree.Issues) + { + Value = dataTree.Value; + Unit = dataTree.Unit; + Labels = dataTree.Labels; + Children = dataTree.Children; + } + public DataTree(string name, uint index, object value, DataTreeIssue[]? issues = null, string unit = null, DataTreeValueLabel[] labels = null) : this(name, index, issues) + { + if (value is IEnumerable || value is DataTree[] children) + throw new ArgumentException($"Use other Constructor if you use {nameof(Children)}"); + + Value = value; + Unit = unit; + Labels = labels; + } + + public DataTree(string name, uint index, DataTree[] children, DataTreeIssue[]? issues = null) : this(name, index, issues) + { + Children = children; + } + + public override string ToString() + { + return $"[{Index}] {Name}: {Value}"; + } + + public override bool Equals(object obj) + { + return obj is DataTree tree && Equals(tree); + } + + public bool Equals(DataTree other) + { + return Name == other.Name && + Index == other.Index && + EqualityComparer.Default.Equals(Value, other.Value) && + compairArrays(this, other); + + bool compairArrays(DataTree _this, DataTree other) + { + if (_this.Children != null) + { + if (!_this.Children.SequenceEqual(other.Children)) + return false; + } + else if (other.Children != null) + return false; + if (_this.Issues != null) + { + if (!_this.Issues.SequenceEqual(other.Issues)) + return false; + } + else if (other.Issues != null) + return false; + + return true; + } + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, Index, Value, Children, Issues); + } + + public static bool operator ==(DataTree left, DataTree right) + { + return left.Equals(right); + } + + public static bool operator !=(DataTree left, DataTree right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeBranch.cs b/RDMSharp/Metadata/DataTreeBranch.cs new file mode 100644 index 0000000..20341fa --- /dev/null +++ b/RDMSharp/Metadata/DataTreeBranch.cs @@ -0,0 +1,282 @@ +using RDMSharp.Metadata.JSON; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Xml.Linq; + +namespace RDMSharp.Metadata +{ + public readonly struct DataTreeBranch : IEquatable + { + public static readonly DataTreeBranch Empty = new DataTreeBranch(); + public static readonly DataTreeBranch Unset = new DataTreeBranch(true); + + public readonly DataTree[] Children; + public readonly bool IsEmpty; + public readonly bool IsUnset; + + public readonly object ParsedObject; + public DataTreeBranch() + { + IsEmpty = true; + } + private DataTreeBranch(bool isUnset) + { + IsUnset = true; + } + public DataTreeBranch(params DataTree[] children) + { + if (children.Length == 0) + IsEmpty = true; + + Children = children; + if (Children.Count(c => c.Index == 0) > 1) + for (uint i = 0; i < Children.Length; i++) + Children[i] = new DataTree(Children[i], i); + } + private DataTreeBranch(object parsedObject, params DataTree[] children): this(children) + { + ParsedObject = parsedObject; + } + public DataTreeBranch(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType, params DataTree[] children): this(children) + { + if (define == null) + throw new ArgumentNullException(); + + ParsedObject = this.getParsedObject(define, commandType); + } + + private object getParsedObject(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType) + { + ushort pid = define.PID; + var definedDataTreeObjectType = MetadataFactory.GetDefinedDataTreeObjectType(define, commandType); + return getParsedObject(pid, definedDataTreeObjectType, commandType); + } + private object getParsedObject(ushort pid, Type definedDataTreeObjectType, Command.ECommandDublicte commandType) + { + if (IsEmpty || IsUnset) + return null; + try + { + if (definedDataTreeObjectType != null) + { + if (definedDataTreeObjectType.IsEnum) + { + var enumAttribute = definedDataTreeObjectType.GetCustomAttributes().FirstOrDefault(a => (ushort)a.Parameter == pid && a.Command == commandType); + + var eChildren = getChildrenUsingPath(enumAttribute, Children); + if (enumAttribute.IsArray) + { + var array = Array.CreateInstance(definedDataTreeObjectType, eChildren.Length); + var aa = eChildren.Select(eC => Enum.ToObject(definedDataTreeObjectType, eC.Value)).ToArray(); + Array.Copy(aa, array, eChildren.Length); + return array; + } + else + return Enum.ToObject(definedDataTreeObjectType, eChildren.Single().Value); + } + + ConstructorInfo[] constructors = definedDataTreeObjectType.GetConstructors(); + var objectAttribute = definedDataTreeObjectType.GetCustomAttributes().FirstOrDefault(a => (ushort)a.Parameter == pid && a.Command == commandType); + + + var children = getChildrenUsingPath(objectAttribute, Children); + DataTree[] getChildrenUsingPath(DataTreeObjectAttribute objectAttribute, DataTree[] children) + { + if (!string.IsNullOrWhiteSpace(objectAttribute.Path)) + { + string[] path = objectAttribute.Path.Split('/'); + while (path.Length >= 1) + { + children = children.FirstOrDefault(c => string.Equals(c.Name, path[0])).Children; + path = path.Skip(1).ToArray(); + } + } + return children; + } + + + foreach (var constructor in constructors) + { + if (constructor.GetCustomAttribute() is DataTreeObjectConstructorAttribute cAttribute) + { + var parameters = new List(); + foreach (var param in constructor.GetParameters()) + if (param.GetCustomAttribute() is DataTreeObjectParameterAttribute pAttribute) + { + var children2 = children; + string name = pAttribute.Name; + string[] path = name.Split('/'); + while (path.Length > 1) + { + children2 = children2.FirstOrDefault(c => string.Equals(c.Name, path[0])).Children; + path = path.Skip(1).ToArray(); + if (path.Length == 1) + name = path[0]; + } + if (!pAttribute.IsArray && children2.FirstOrDefault(c => string.Equals(c.Name, name)) is DataTree child) + parameters.Add(child.Value); + else if (pAttribute.IsArray && children2.Where(c => string.Equals(c.Name, pAttribute.Name)).OfType() is IEnumerable childenum) + { + Type targetType = children2.First().Value.GetType(); + var array = Array.CreateInstance(targetType, children2.Length); + Array.Copy(children2.Select(c => c.Value).ToArray(), array, children2.Length); + parameters.Add(array); + } + else + throw new ArgumentException($"No matching Value found for '{pAttribute.Name}'"); + } + + var instance = constructor.Invoke(parameters.ToArray()); + return instance; + } + } + } + + if (Children.Length == 1) + { + DataTree dataTree = Children[0]; + + if (dataTree.Value != null) + return dataTree.Value; + + if (dataTree.Children.GroupBy(c => c.Name).Count() == 1) + { + var list = dataTree.Children.Select(c => c.Value).ToList(); + Type targetType = list.First().GetType(); + var array = Array.CreateInstance(targetType, list.Count); + Array.Copy(list.ToArray(), array, list.Count); + //for (int i = 0; i < list.Count; i++) + // array.SetValue(Convert.ChangeType(list[i], targetType), i); + + return array; + } + } + } + catch (Exception e) + { + throw e; + } + + throw new NotImplementedException(); + } + + public static DataTreeBranch FromObject(object obj, ERDM_Command command, ERDM_Parameter parameter) + { + + Type type = obj.GetType(); + bool isArray = type.IsArray; + + if (isArray) + type = type.GetElementType(); + + if (type.GetCustomAttributes().FirstOrDefault(a => a.Parameter == parameter && a.Command == Tools.ConvertCommandDublicteToCommand(command) && a.IsArray == isArray) is not DataTreeObjectAttribute dataTreeObjectAttribute) + return DataTreeBranch.Unset; + + List children = new List(); + if (!type.IsEnum) + { + var properties = type.GetProperties().Where(p => p.GetCustomAttributes().Count() != 0).ToArray(); + + if (isArray) + { + Array array = (Array)obj; + for (uint i = 0; i < array.Length; i++) + children.Add(new DataTree(string.Empty, i, convertToDataTree(array.GetValue(i), properties, parameter))); + } + else + children.AddRange(convertToDataTree(obj, properties, parameter)); + } + else + { + DataTreeEnumAttribute enumAttribute = dataTreeObjectAttribute as DataTreeEnumAttribute; + if (isArray) + { + Array array = (Array)obj; + for (uint i = 0; i < array.Length; i++) + children.Add(new DataTree(enumAttribute.Name, i, getUnderlyingValue(array.GetValue(i)))); + } + else + children.Add(new DataTree(enumAttribute.Name, 0, getUnderlyingValue(obj))); + } + + if (!string.IsNullOrWhiteSpace(dataTreeObjectAttribute.Path)) + { + string[] path = dataTreeObjectAttribute.Path.Split('/'); + DataTree? route = null; + for (int i = path.Length; i != 0; i--) + { + if (route.HasValue) + route = new DataTree(path[i - 1], 0, route); + else + route = new DataTree(path[i - 1], 0, children.ToArray()); + } + + return new DataTreeBranch(obj, route.Value); + } + + return new DataTreeBranch(obj, children.ToArray()); + + static DataTree[] convertToDataTree(object value, PropertyInfo[] properties, ERDM_Parameter parameter) + { + List innetChildren = new List(); + foreach (var property in properties) + { + var attributes = property.GetCustomAttributes(); + DataTreeObjectPropertyAttribute attribute = attributes.FirstOrDefault(); + if (attributes.Count() != 1) + attribute = attributes.FirstOrDefault(a => a.Parameter == parameter); + + if (attribute != null) + innetChildren.Add(new DataTree(attribute.Name, attribute.Index, property.GetValue(value))); + } + return innetChildren.ToArray(); + } + static object getUnderlyingValue(object enumValue) + { + // Ermitteln des zugrunde liegenden Typs + Type underlyingType = Enum.GetUnderlyingType(enumValue.GetType()); + + // Konvertierung des Enum-Werts in den zugrunde liegenden Typ + return Convert.ChangeType(enumValue, underlyingType); + } + } + + public override bool Equals(object obj) + { + return obj is DataTreeBranch branch && Equals(branch); + } + + public bool Equals(DataTreeBranch other) + { + for (int i = 0; i < Children.Length; i++) + { + DataTree me = Children[i]; + if ((other.Children?.Length ?? 0) <= i) + return false; + DataTree ot = other.Children[i]; + if (!me.Equals(ot)) + return false; + } + return true; + // return EqualityComparer.Default.Equals(Children, other.Children); // is not dooing its job + } + + public override int GetHashCode() + { + return HashCode.Combine(Children); + } + + public static bool operator ==(DataTreeBranch left, DataTreeBranch right) + { + return left.Equals(right); + } + + public static bool operator !=(DataTreeBranch left, DataTreeBranch right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeIssue.cs b/RDMSharp/Metadata/DataTreeIssue.cs new file mode 100644 index 0000000..b9f3fef --- /dev/null +++ b/RDMSharp/Metadata/DataTreeIssue.cs @@ -0,0 +1,20 @@ +using System; + +namespace RDMSharp.Metadata +{ + public readonly struct DataTreeIssue + { + public readonly string Description; + + public DataTreeIssue(string description) + { + if (string.IsNullOrWhiteSpace(description)) + throw new ArgumentNullException($"{nameof(description)} has to be a vaild String"); + Description = description; + } + public override string ToString() + { + return Description; + } + } +} diff --git a/RDMSharp/Metadata/DataTreeObjectAttribute.cs b/RDMSharp/Metadata/DataTreeObjectAttribute.cs new file mode 100644 index 0000000..405f79d --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectAttribute.cs @@ -0,0 +1,44 @@ +using RDMSharp.Metadata.JSON; +using RDMSharp.ParameterWrapper; +using System; + +namespace RDMSharp.Metadata; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] +public class DataTreeObjectAttribute : Attribute +{ + public readonly ERDM_Parameter Parameter; + public readonly Command.ECommandDublicte Command; + public readonly EManufacturer Manufacturer = EManufacturer.ESTA; + + public readonly bool IsArray; + public readonly string Path; + + public DataTreeObjectAttribute(ERDM_Parameter parameter, Command.ECommandDublicte command, bool isArray = false, string path=null) + { + Parameter = parameter; + Command = command; + IsArray = isArray; + Path = path; + } + public DataTreeObjectAttribute(EManufacturer manufacturer, ERDM_Parameter parameter, Command.ECommandDublicte command, bool isArray = false, string path = null) + : this(parameter, command, isArray, path) + { + Manufacturer = manufacturer; + } +} +[AttributeUsage(AttributeTargets.Enum, AllowMultiple = true)] +public class DataTreeEnumAttribute : DataTreeObjectAttribute +{ + public readonly string Name; + public DataTreeEnumAttribute(ERDM_Parameter parameter, Command.ECommandDublicte command, string name, bool isArray = false, string path = null) + : base(parameter, command, isArray, path) + { + Name = name; + } + public DataTreeEnumAttribute(EManufacturer manufacturer, ERDM_Parameter parameter, Command.ECommandDublicte command, string name, bool isArray = false, string path = null) + : base(manufacturer, parameter, command, isArray, path) + { + Name = name; + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeObjectConstructorAttribute.cs b/RDMSharp/Metadata/DataTreeObjectConstructorAttribute.cs new file mode 100644 index 0000000..55bc0ad --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectConstructorAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace RDMSharp.Metadata; + +[AttributeUsage(AttributeTargets.Constructor)] +public class DataTreeObjectConstructorAttribute : Attribute +{ + public DataTreeObjectConstructorAttribute() + { + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeObjectDependeciePropertyAttribute.cs b/RDMSharp/Metadata/DataTreeObjectDependeciePropertyAttribute.cs new file mode 100644 index 0000000..3aa2c85 --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectDependeciePropertyAttribute.cs @@ -0,0 +1,21 @@ +using RDMSharp.Metadata.JSON; +using System; + +namespace RDMSharp.Metadata; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] +public class DataTreeObjectDependeciePropertyAttribute : Attribute +{ + public readonly string Name; + public readonly ERDM_Parameter Parameter; + public readonly Command.ECommandDublicte Command; + public readonly DataTreeObjectDependeciePropertyBag Bag; + + public DataTreeObjectDependeciePropertyAttribute(string name, ERDM_Parameter parameter, Command.ECommandDublicte command) + { + Name = name; + Parameter = parameter; + Command = command; + Bag = new DataTreeObjectDependeciePropertyBag(name, parameter, command); + } +} diff --git a/RDMSharp/Metadata/DataTreeObjectDependeciePropertyBag.cs b/RDMSharp/Metadata/DataTreeObjectDependeciePropertyBag.cs new file mode 100644 index 0000000..5acd64e --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectDependeciePropertyBag.cs @@ -0,0 +1,18 @@ +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.Metadata; + +public readonly struct DataTreeObjectDependeciePropertyBag +{ + public readonly string Name; + public readonly ERDM_Parameter Parameter; + public readonly Command.ECommandDublicte Command; + public readonly object Value; + + internal DataTreeObjectDependeciePropertyBag(string name, ERDM_Parameter parameter, Command.ECommandDublicte command) + { + Name = name; + Parameter = parameter; + Command = command; + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeObjectParameterAttribute.cs b/RDMSharp/Metadata/DataTreeObjectParameterAttribute.cs new file mode 100644 index 0000000..ea801e2 --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectParameterAttribute.cs @@ -0,0 +1,22 @@ +using System; + +namespace RDMSharp.Metadata; + +[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true)] +public class DataTreeObjectParameterAttribute : Attribute +{ + public readonly string Name; + + public readonly ERDM_Parameter? Parameter; + + public readonly bool IsArray; + + public DataTreeObjectParameterAttribute(string name) + { + Name = name; + } + public DataTreeObjectParameterAttribute(ERDM_Parameter parameter, string name) : this(name) + { + Parameter = parameter; + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeObjectPropertyAttribute.cs b/RDMSharp/Metadata/DataTreeObjectPropertyAttribute.cs new file mode 100644 index 0000000..485212a --- /dev/null +++ b/RDMSharp/Metadata/DataTreeObjectPropertyAttribute.cs @@ -0,0 +1,24 @@ +using RDMSharp.Metadata.JSON; +using System; +using System.Threading; + +namespace RDMSharp.Metadata; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] +public class DataTreeObjectPropertyAttribute : Attribute +{ + public readonly string Name; + public readonly uint Index; + + public readonly ERDM_Parameter? Parameter; + + public DataTreeObjectPropertyAttribute(string name, uint index) + { + Name = name; + Index = index; + } + public DataTreeObjectPropertyAttribute(ERDM_Parameter parameter, string name, uint index) : this(name, index) + { + Parameter = parameter; + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/DataTreeValueLabel.cs b/RDMSharp/Metadata/DataTreeValueLabel.cs new file mode 100644 index 0000000..8c0281f --- /dev/null +++ b/RDMSharp/Metadata/DataTreeValueLabel.cs @@ -0,0 +1,14 @@ +namespace RDMSharp.Metadata +{ + public readonly struct DataTreeValueLabel + { + public readonly object Value; + public readonly string Label; + + public DataTreeValueLabel(object value, string label) + { + Value = value; + Label = label; + } + } +} diff --git a/RDMSharp/Metadata/DefineNotFoundException.cs b/RDMSharp/Metadata/DefineNotFoundException.cs new file mode 100644 index 0000000..602a6e7 --- /dev/null +++ b/RDMSharp/Metadata/DefineNotFoundException.cs @@ -0,0 +1,15 @@ +using System; + +namespace RDMSharp.Metadata +{ + public class DefineNotFoundException : Exception + { + public DefineNotFoundException() + { + } + + public DefineNotFoundException(string message) : base(message) + { + } + } +} diff --git a/RDMSharp/Metadata/JSON/Command.cs b/RDMSharp/Metadata/JSON/Command.cs new file mode 100644 index 0000000..ebe4464 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Command.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Text.Json.Serialization; +using RDMSharp.Metadata.JSON.Converter; +using RDMSharp.RDM; +using OneOf = RDMSharp.Metadata.JSON.OneOfTypes.OneOfTypes; + +namespace RDMSharp.Metadata.JSON +{ + [JsonConverter(typeof(CommandConverter))] + public readonly struct Command + { + [JsonConverter(typeof(CustomEnumConverter))] + public enum ECommandDublicte + { + [JsonPropertyName("get_request")] + GetRequest, + [JsonPropertyName("get_response")] + GetResponse, + [JsonPropertyName("set_request")] + SetRequest, + [JsonPropertyName("set_response")] + SetResponse, + [JsonPropertyName("different_pid")] + DifferentDid + } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly ECommandDublicte? EnumValue { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly OneOf? SingleField { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly OneOf[]? ListOfFields { get; } + + public bool GetIsEmpty() + { + if (EnumValue != null) + return false; + if (SingleField != null) + return false; + if (ListOfFields != null) + return ListOfFields.Length == 0; + + return true; + } + public Command(ECommandDublicte enumValue) + { + EnumValue = enumValue; + } + public Command(OneOf singleField) + { + SingleField = singleField; + } + public Command(OneOf[] listOfFields) + { + ListOfFields = listOfFields; + } + public PDL GetDataLength() + { + if(GetIsEmpty()) + return new PDL(); + if (SingleField.HasValue) + return SingleField.Value.GetDataLength(); + if (ListOfFields != null) + return new PDL(ListOfFields.Select(f => f.GetDataLength()).ToArray()); + + throw new NotSupportedException(); + } + + public CommonPropertiesForNamed[] GetRequiredProperties() + { + if (SingleField.HasValue) + return new CommonPropertiesForNamed[] { SingleField.Value.ObjectType }; + if (ListOfFields != null) + { + List names = new(); + foreach (var field in ListOfFields) + names.Add(field.ObjectType); + return names.ToArray(); + } + throw new NotImplementedException(); + } + public override string ToString() + { + if (EnumValue.HasValue) + return EnumValue.Value.ToString(); + if (SingleField.HasValue) + return SingleField.Value.ToString(); + if (ListOfFields != null) + return $"[ {string.Join("; ", ListOfFields.Select(f => f.ToString()))} ]"; + return base.ToString(); + } + } +} diff --git a/RDMSharp/Metadata/JSON/CommonPropertiesForNamed.cs b/RDMSharp/Metadata/JSON/CommonPropertiesForNamed.cs new file mode 100644 index 0000000..b305a65 --- /dev/null +++ b/RDMSharp/Metadata/JSON/CommonPropertiesForNamed.cs @@ -0,0 +1,34 @@ +using RDMSharp.RDM; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON +{ + public abstract class CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public abstract string Name { get; } + [JsonPropertyName("displayName")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public abstract string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public abstract string? Notes { get; } + [JsonPropertyName("resources")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public abstract string[]? Resources { get; } + + public abstract PDL GetDataLength(); + + public abstract byte[] ParsePayloadToData(DataTree dataTree); + public abstract DataTree ParseDataToPayload(ref byte[] data); + + public override string ToString() + { + if(!string.IsNullOrWhiteSpace(DisplayName)) + return DisplayName; + + return Name; + } + } +} diff --git a/RDMSharp/Metadata/JSON/Converter/CommandConverter.cs b/RDMSharp/Metadata/JSON/Converter/CommandConverter.cs new file mode 100644 index 0000000..89eaeb8 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/CommandConverter.cs @@ -0,0 +1,45 @@ +using System.Text.Json; +using System; +using System.Text.Json.Serialization; +using OneOf = RDMSharp.Metadata.JSON.OneOfTypes.OneOfTypes; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class CommandConverter : JsonConverter + { + public override Command Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var enumValue = JsonSerializer.Deserialize(ref reader, options); + return new Command(enumValue); + } + else if (reader.TokenType == JsonTokenType.StartObject) + { + var singleField = JsonSerializer.Deserialize(ref reader, options); + return new Command(singleField); + } + else if (reader.TokenType == JsonTokenType.StartArray) + { + var listOfFields = JsonSerializer.Deserialize(ref reader, options); + if (listOfFields.Length == 0) + return new Command(); + return new Command(listOfFields); + } + + throw new JsonException("Unexpected JSON format for FieldContainer."); + } + + public override void Write(Utf8JsonWriter writer, Command value, JsonSerializerOptions options) + { + if (value.GetIsEmpty()) + JsonSerializer.Serialize(writer, new object[0], options); + else if (value.EnumValue.HasValue) + JsonSerializer.Serialize(writer, value.EnumValue.Value, options); + else if (value.SingleField != null) + JsonSerializer.Serialize(writer, value.SingleField.Value, options); + else if (value.ListOfFields != null) + JsonSerializer.Serialize(writer, value.ListOfFields, options); + } + } +} diff --git a/RDMSharp/Metadata/JSON/Converter/CustomEnumConverter.cs b/RDMSharp/Metadata/JSON/Converter/CustomEnumConverter.cs new file mode 100644 index 0000000..e18aa8c --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/CustomEnumConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class CustomEnumConverter : JsonConverter where T : struct, Enum + { + public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string enumValue = reader.GetString(); + + foreach (var field in typeof(T).GetFields()) + { + if (field.GetCustomAttribute()?.Name == enumValue) + { + return (T)field.GetValue(null); + } + } + + throw new JsonException($"Unknown enum value: {enumValue}"); + } + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + var field = typeof(T).GetField(value.ToString()); + + var attribute = field.GetCustomAttribute(); + string enumString = attribute.Name; + + writer.WriteStringValue(enumString); + } + } + +} diff --git a/RDMSharp/Metadata/JSON/Converter/OneOfTypesConverter.cs b/RDMSharp/Metadata/JSON/Converter/OneOfTypesConverter.cs new file mode 100644 index 0000000..982c005 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/OneOfTypesConverter.cs @@ -0,0 +1,148 @@ +using RDMSharp.Metadata.JSON.OneOfTypes; +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using OneOf = RDMSharp.Metadata.JSON.OneOfTypes.OneOfTypes; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class OneOfTypesConverter : JsonConverter + { + public override OneOf Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + JsonElement element = JsonSerializer.Deserialize(ref reader, options); + if (!element.TryGetProperty("type", out JsonElement typeProperty)) + { + if (element.TryGetProperty("$ref", out JsonElement refProperty)) + { + var referenceType = element.Deserialize(options); + return new OneOf(referenceType); + } + throw new JsonException("Unexpected JSON format for FieldContainer."); + } + + string type= typeProperty.GetString(); + switch (type) + { + case "bitField": + var bitFieldType = element.Deserialize(options); + return new OneOf(bitFieldType); + + case "bytes": + var bytesType = element.Deserialize(options); + return new OneOf(bytesType); + + case "boolean": + var booleanType = element.Deserialize(options); + return new OneOf(booleanType); + + case "compound": + var compoundType = element.Deserialize(options); + return new OneOf(compoundType); + + case "int8": + var integerTypeInt8 = element.Deserialize>(options); + return new OneOf(integerTypeInt8); + case "uint8": + var integerTypeUInt8 = element.Deserialize>(options); + return new OneOf(integerTypeUInt8); + + case "int16": + var integerTypeInt16 = element.Deserialize>(options); + return new OneOf(integerTypeInt16); + case "uint16": + var integerTypeUInt16 = element.Deserialize>(options); + return new OneOf(integerTypeUInt16); + + case "int32": + var integerTypeInt32 = element.Deserialize>(options); + return new OneOf(integerTypeInt32); + case "uint32": + var integerTypeUInt32 = element.Deserialize>(options); + return new OneOf(integerTypeUInt32); + + case "int64": + var integerTypeInt64 = element.Deserialize>(options); + return new OneOf(integerTypeInt64); + case "uint64": + var integerTypeUInt64 = element.Deserialize>(options); + return new OneOf(integerTypeUInt64); + +#if NET7_0_OR_GREATER + case "int128": + var integerTypeInt128 = element.Deserialize>(options); + return new OneOf(integerTypeInt128); + case "uint128": + var integerTypeUInt128 = element.Deserialize>(options); + return new OneOf(integerTypeUInt128); +#endif + + case "list": + var listType = element.Deserialize(options); + return new OneOf(listType); + + case "pdEnvelope": + var pdEnvelopeType = element.Deserialize(options); + return new OneOf(pdEnvelopeType); + + case "string": + var stringType = element.Deserialize(options); + return new OneOf(stringType); + } + + throw new JsonException($"Unexpected JSON format Type: {type} for FieldContainer."); + } + + public override void Write(Utf8JsonWriter writer, OneOf value, JsonSerializerOptions options) + { + if (value.BitFieldType != null) + JsonSerializer.Serialize(writer, value.BitFieldType, options); + + else if (value.BooleanType != null) + JsonSerializer.Serialize(writer, value.BooleanType, options); + + else if (value.BytesType != null) + JsonSerializer.Serialize(writer, value.BytesType, options); + + else if (value.ReferenceType != null) + JsonSerializer.Serialize(writer, value.ReferenceType, options); + + else if (value.IntegerType_UInt8 != null) + JsonSerializer.Serialize(writer, value.IntegerType_UInt8, options); + else if (value.IntegerType_Int8 != null) + JsonSerializer.Serialize(writer, value.IntegerType_Int8, options); + + else if (value.IntegerType_UInt16 != null) + JsonSerializer.Serialize(writer, value.IntegerType_UInt16, options); + else if (value.IntegerType_Int16 != null) + JsonSerializer.Serialize(writer, value.IntegerType_Int16, options); + + else if (value.IntegerType_UInt32 != null) + JsonSerializer.Serialize(writer, value.IntegerType_UInt32, options); + else if (value.IntegerType_Int32 != null) + JsonSerializer.Serialize(writer, value.IntegerType_Int32, options); + + else if (value.IntegerType_UInt64 != null) + JsonSerializer.Serialize(writer, value.IntegerType_UInt64, options); + else if (value.IntegerType_Int64 != null) + JsonSerializer.Serialize(writer, value.IntegerType_Int64, options); +#if NET7_0_OR_GREATER + else if (value.IntegerType_UInt128 != null) + JsonSerializer.Serialize(writer, value.IntegerType_UInt128, options); + else if (value.IntegerType_Int128 != null) + JsonSerializer.Serialize(writer, value.IntegerType_Int128, options); +#endif + else if (value.StringType != null) + JsonSerializer.Serialize(writer, value.StringType, options); + + else if (value.ListType != null) + JsonSerializer.Serialize(writer, value.ListType, options); + + else if (value.CompoundType != null) + JsonSerializer.Serialize(writer, value.CompoundType, options); + + else if (value.PD_EnvelopeType != null) + JsonSerializer.Serialize(writer, value.PD_EnvelopeType, options); + } + } +} diff --git a/RDMSharp/Metadata/JSON/Converter/SubdeviceTypeConverter.cs b/RDMSharp/Metadata/JSON/Converter/SubdeviceTypeConverter.cs new file mode 100644 index 0000000..b7b4219 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/SubdeviceTypeConverter.cs @@ -0,0 +1,33 @@ +using System.Text.Json; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class SubdeviceTypeConverter : JsonConverter + { + public override SubdeviceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + { + var number = JsonSerializer.Deserialize(ref reader, options); + return new SubdeviceType(number); + } + else if (reader.TokenType == JsonTokenType.StartObject) + { + var objectValue = JsonSerializer.Deserialize(ref reader, options); + return new SubdeviceType(objectValue); + } + + throw new JsonException("Unexpected JSON format for FieldContainer."); + } + + public override void Write(Utf8JsonWriter writer, SubdeviceType value, JsonSerializerOptions options) + { + if (value.Value.HasValue) + JsonSerializer.Serialize(writer, value.Value.Value, options); + else if (value.Range.HasValue) + JsonSerializer.Serialize(writer, value.Range.Value, options); + } + } +} diff --git a/RDMSharp/Metadata/JSON/Converter/SubdevicesForRequestsConverter.cs b/RDMSharp/Metadata/JSON/Converter/SubdevicesForRequestsConverter.cs new file mode 100644 index 0000000..306ef97 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/SubdevicesForRequestsConverter.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class SubdevicesForRequestsConverter : JsonConverter + { + public override SubdevicesForRequests Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var enumValue = JsonSerializer.Deserialize(ref reader, options); + return new SubdevicesForRequests(enumValue); + } + var objectValue = JsonSerializer.Deserialize(ref reader, options); + return new SubdevicesForRequests(objectValue); + } + + public override void Write(Utf8JsonWriter writer, SubdevicesForRequests value, JsonSerializerOptions options) + { + if (value.EnumValue.HasValue) + JsonSerializer.Serialize(writer, value.EnumValue.Value, new JsonSerializerOptions(options) + { + Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + else if (value.ObjectValue != null) + JsonSerializer.Serialize(writer, value.ObjectValue, options); + } + } +} diff --git a/RDMSharp/Metadata/JSON/Converter/SubdevicesForResponsesConverter.cs b/RDMSharp/Metadata/JSON/Converter/SubdevicesForResponsesConverter.cs new file mode 100644 index 0000000..114bf17 --- /dev/null +++ b/RDMSharp/Metadata/JSON/Converter/SubdevicesForResponsesConverter.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.Converter +{ + public class SubdevicesForResponsesConverter : JsonConverter + { + public override SubdevicesForResponses Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var enumValue = JsonSerializer.Deserialize(ref reader, options); + return new SubdevicesForResponses(enumValue); + } + var objectValue = JsonSerializer.Deserialize(ref reader, options); + return new SubdevicesForResponses(objectValue); + } + + public override void Write(Utf8JsonWriter writer, SubdevicesForResponses value, JsonSerializerOptions options) + { + if (value.EnumValue.HasValue) + JsonSerializer.Serialize(writer, value.EnumValue.Value, new JsonSerializerOptions(options) + { + Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + else if (value.ObjectValue != null) + JsonSerializer.Serialize(writer, value.ObjectValue, options); + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs new file mode 100644 index 0000000..648c1aa --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BitFieldType.cs @@ -0,0 +1,146 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class BitFieldType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + + [JsonPropertyName("size")] + [JsonPropertyOrder(31)] + public ushort Size { get; } + + [JsonPropertyName("valueForUnspecified")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(32)] + public bool? ValueForUnspecified { get; } + + [JsonPropertyName("bits")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(41)] + public BitType[] Bits { get; } + + [JsonConstructor] + public BitFieldType(string name, + string displayName, + string notes, + string[] resources, + string type, + ushort size, + bool? valueForUnspecified, + BitType[] bits) : base() + { + if (!"bitField".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"bitField\""); + if (size % 8 != 0) + throw new ArgumentOutOfRangeException($"Argument {nameof(size)} has to be a multiple of 8"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Size = size; + ValueForUnspecified = valueForUnspecified; + Bits = bits; + } + public BitFieldType(string name, ushort size, BitType[] bits, bool valueForUnspecified = false) : this(name, null, null, null, "bitField", size, valueForUnspecified, bits) + { + } + + public override PDL GetDataLength() + { + return new PDL((uint)(Size / 8)); + } + + public override string ToString() + { + return $"{Name} [ {string.Join("; ", Bits.Select(b => b.ToString()))} ]"; + } + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + if (dataTree.Children.Length != this.Bits.Length) + throw new ArithmeticException($"The given {nameof(dataTree.Children)}.{nameof(dataTree.Children.Length)}({dataTree.Children.Length}) not match {nameof(Bits)}.{nameof(Bits.Length)}({Bits.Length})"); + + bool[] data = new bool[Size]; + if (ValueForUnspecified == true) + for (int i = 0; i < Size; i++) + data[i] = true; + + foreach (DataTree bitDataTree in dataTree.Children) + { + BitType bit = Bits.FirstOrDefault(b=>b.Name== bitDataTree.Name); + if (bit == null) + throw new ArithmeticException($"Can't find matching BitType {bitDataTree.Name}"); + if (Bits.Length <= bitDataTree.Index || Bits[bitDataTree.Index] != bit) + throw new ArithmeticException($"The given DataTree {nameof(bitDataTree.Index)}({bitDataTree.Index}) not match BitType {nameof(bit.Index)}({bit.Index})"); + if (bitDataTree.Value is not bool value) + throw new ArithmeticException($"DataTree Value is not bool"); + + data[bit.Index] = value; + } + + return Tools.ValueToData(data); + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + List bitDataTrees = new List(); + List issueList = new List(); + int byteCount = (Size / 8); + if (byteCount > data.Length) + { + issueList.Add(new DataTreeIssue($"Data length not match given Size/8 ({byteCount})")); + byte[] cloneData = new byte[byteCount]; + Array.Copy(data, cloneData, data.Length); + data = cloneData; + } + bool[] bools = Tools.DataToBoolArray(ref data, Size); + for (uint i = 0; i < Bits.Length; i++) + { + BitType bitType = Bits[i]; + bitDataTrees.Add(new DataTree(bitType.Name, i, bools[bitType.Index])); + } + bool valueForUnspecified = ValueForUnspecified == true; + for(int i = 0; i < bools.Length; i++) + { + if (Bits.Any(b => b.Index == i)) + continue; + + bool bit= bools[i]; + if (bit != valueForUnspecified) + issueList.Add(new DataTreeIssue($"The Bit at Index {i} is Unspecified, but the Value is not {valueForUnspecified} as defined for Unspecified Bits")); + } + var children = bitDataTrees.OrderBy(b => b.Index).ToArray(); + var dataTree = new DataTree(this.Name, 0, children: children, issueList.Count != 0 ? issueList.ToArray() : null); + return dataTree; + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs new file mode 100644 index 0000000..82520bf --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BitType.cs @@ -0,0 +1,84 @@ +using System; +using System.Text.Json.Serialization; +using RDMSharp.RDM; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class BitType : CommonPropertiesForNamed + { + [JsonConstructor] + public BitType(string name, + string displayName, + string notes, + string[] resources, + string type, + ushort index, + bool? reserved, + bool? valueIfReserved) : base() + { + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Index = index; + Reserved = reserved; + ValueIfReserved = valueIfReserved; + } + public BitType(string name, ushort index) : this(name, null, null, null, "bit", index, null, null) + { + } + + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Type { get; } + [JsonPropertyName("index")] + [JsonPropertyOrder(21)] + public ushort Index { get; } + [JsonPropertyName("reserved")] + [JsonPropertyOrder(31)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? Reserved { get; } + [JsonPropertyName("valueIfReserved")] + [JsonPropertyOrder(32)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? ValueIfReserved { get; } + + public override PDL GetDataLength() + { + throw new NotSupportedException(); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + throw new NotSupportedException(); + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + throw new NotSupportedException(); + } + + public override string ToString() + { + return $"{Index} -> {Name}"; + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BooleanType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BooleanType.cs new file mode 100644 index 0000000..b0dc5fd --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BooleanType.cs @@ -0,0 +1,118 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class BooleanType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + [JsonPropertyName("labels")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LabeledBooleanType[] Labels { get; } + + + [JsonConstructor] + public BooleanType(string name, + string displayName, + string notes, + string[] resources, + string type, + LabeledBooleanType[] labels) : base() + { + if (!"boolean".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"boolean\""); + + if (((labels?.Length) ?? 2) != 2) + throw new ArgumentException($"Argument {nameof(labels)} has to be null oa an array of 2"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Labels = labels; + + if (labels != null) + { + if (labels[0].Value == labels[1].Value) + throw new ArgumentException($"Argument {nameof(labels)}, both Values are the same, one has to be false, the other true"); + } + } + public override string ToString() + { + if (Labels == null) + return Name; + + return $"{Name} [ {string.Join("; ", Labels.Select(l => l.ToString()))} ]"; + } + + public override PDL GetDataLength() + { + return new PDL(1); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + if(dataTree.Value is bool value) + { + switch (value) + { + case false: + return new byte[] { 0x00 }; + case true: + return new byte[] { 0x01 }; + } + } + throw new ArithmeticException($"The given Object from {nameof(dataTree.Value)} can't be parsed"); + } + + public override DataTree ParseDataToPayload(ref byte[] data) + { + List issueList = new List(); + + uint pdl = GetDataLength().Value.Value; + if (data.Length < pdl) + { + issueList.Add(new DataTreeIssue("Given Data not fits PDL")); + byte[] cloneData = new byte[pdl]; + Array.Copy(data, cloneData, data.Length); + data = cloneData; + } + + + DataTreeValueLabel[] labels = null; + if ((Labels?.Length ?? 0) != 0) + labels = Labels.Select(lb => new DataTreeValueLabel(lb.Value, (lb.DisplayName ?? lb.Name))).ToArray(); + + bool value = false; + value = Tools.DataToBool(ref data); + + return new DataTree(this.Name, 0, value, issueList.Count != 0 ? issueList.ToArray() : null, labels: labels); + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/BytesType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/BytesType.cs new file mode 100644 index 0000000..8cedeb7 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/BytesType.cs @@ -0,0 +1,351 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class BytesType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + [JsonPropertyName("format")] + [JsonPropertyOrder(11)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Format { get; } + [JsonPropertyName("minLength")] + [JsonPropertyOrder(12)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MinLength { get; } + [JsonPropertyName("maxLength")] + [JsonPropertyOrder(13)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MaxLength { get; } + + + [JsonConstructor] + public BytesType(string name, + string displayName, + string notes, + string[] resources, + string type, + string format, + uint? minLength, + uint? maxLength) : base() + { + if (!"bytes".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"bytes\""); + if (minLength.HasValue && maxLength.HasValue) + if (minLength > maxLength) + throw new ArgumentOutOfRangeException($"Argument {nameof(minLength)} has to be <= {nameof(maxLength)}"); + if (minLength.HasValue) + if (minLength > PDL.MAX_LENGTH) + throw new ArgumentOutOfRangeException($"Argument {nameof(minLength)} has to be <= {PDL.MAX_LENGTH}"); + if (maxLength.HasValue) + if (maxLength > PDL.MAX_LENGTH) + throw new ArgumentOutOfRangeException($"Argument {nameof(maxLength)} has to be <= {PDL.MAX_LENGTH}"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Format = format; + MinLength = minLength; + MaxLength = maxLength; + } + + public override string ToString() + { + return Name; + } + + public override PDL GetDataLength() + { + uint length = 0; + string format = Format; + bool noFixedSize = false; + if (!string.IsNullOrWhiteSpace(Format) && Format.EndsWith("[]")) + format = Format.Replace("[]", ""); + switch (format) + { + case "mac-address": + case "uid": + length = 6; + break; + case "ipv4": + case "float": + length = 4; + break; + case "ipv6": + case "uuid": + case "guid": + length = 16; + break; + case "double": + length = 8; + break; + case "pid": + length = 2; + break; + default: + noFixedSize = true; + break; + } + if (!string.IsNullOrWhiteSpace(Format) && Format.EndsWith("[]")) + return new PDL(0, (uint)(Math.Truncate((double)PDL.MAX_LENGTH / length) * length)); + else if (!noFixedSize) + return new PDL(length); + + return new PDL((uint)(MinLength ?? 1), (uint)(MaxLength ?? PDL.MAX_LENGTH)); + } + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + + if (!string.IsNullOrWhiteSpace(Format) && Format.EndsWith("[]") && dataTree.Value is Array typedArray) + { + List bytes = new List(); + string format = Format.Replace("[]", ""); + for (int i = 0; i < typedArray.Length; i++) + { + object value = typedArray.GetValue(i); + bytes.AddRange(parseData(format, value)); + if (value is string) + bytes.Add(0); //Null-Delimiter + } + return bytes.ToArray(); + } + else + return parseData(Format, dataTree.Value); + + byte[] parseData(string format, object value) + { + Exception e = null; + try + { + switch (format) + { + //Known from E1.37-5 (2024) + case "uid" when value is UID uid: + return uid.ToBytes().ToArray(); + case "ipv4" when value is IPv4Address ipv4: + return (byte[])ipv4; + case "ipv6" when value is IPv6Address ipv6: + return (byte[])ipv6; + case "mac-address" when value is MACAddress macAddress: + return (byte[])macAddress; + + //Known from E1.37-5 (2024) as uuid + case "uuid" when value is Guid uuid: + return uuid.ToByteArray(); + case "guid" when value is Guid guid: + return guid.ToByteArray(); + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "pid" when value is ERDM_Parameter pid: + return Tools.ValueToData(pid); + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "double" when value is double _double: + return BitConverter.GetBytes(_double); + case "float" when value is float _float: + return BitConverter.GetBytes(_float); + + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "ascii" when value is string ascii: + return Encoding.ASCII.GetBytes(ascii); + case "utf8" when value is string utf8: + return Encoding.UTF8.GetBytes(utf8); + case "utf32" when value is string utf32: + return Encoding.UTF32.GetBytes(utf32); + case "unicode" when value is string unicode: + return Encoding.Unicode.GetBytes(unicode); + case "big_edian_unicode" when value is string big_edian_unicode: + return Encoding.BigEndianUnicode.GetBytes(big_edian_unicode); + case "latin1" when value is string latin1: + return Encoding.Latin1.GetBytes(latin1); + + //Fallback + default: + if (value is string str) + return Encoding.UTF8.GetBytes(str); + if (value is byte[] byteArray) + return byteArray; + throw new NotImplementedException($"There is no implementation for {nameof(Format)}: {Format} and Value: {value}"); + } + } + catch (Exception ex) + { + e = ex; + } + throw new ArithmeticException($"The given Object of {nameof(Format)}: \"{Format}\" can't be parsed from {nameof(value)}: {value}", e); + } + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + List issueList = new List(); + object value = null; + if (!string.IsNullOrWhiteSpace(Format) && Format.EndsWith("[]")) + { + List list = new List(); + while (data.Length > 0) + { + try + { + string format = Format.Replace("[]", ""); + list.Add(parseData(format, ref data)); + } + catch(Exception e) + { + issueList.Add(new DataTreeIssue(e.Message)); + break; + } + } + if (data.Length > 0) + issueList.Add(new DataTreeIssue("Data Length is not 0")); + + if (list.Count == 0) + value = null; + else + { + Type targetType=list.First().GetType(); + var array = Array.CreateInstance(targetType,list.Count); + for (int i = 0; i < list.Count; i++) + array.SetValue(Convert.ChangeType(list[i], targetType), i); + + value = array; + } + } + else + value = parseData(Format, ref data); + + + return new DataTree(this.Name, 0, value, issueList.Count != 0 ? issueList.ToArray() : null); + + object parseData(string format, ref byte[] data) + { + void validateDataLength(int length, ref byte[] data) + { + if (data.Length < length) + throw new ArithmeticException("Data to short"); + } + object value = null; + switch (format) + { + //Known from E1.37-5 (2024) + case "uid": + validateDataLength(6, ref data); + value = new UID(Tools.DataToUShort(ref data), Tools.DataToUInt(ref data)); + break; + case "ipv4": + validateDataLength(4, ref data); + value = new IPv4Address(data.Take(4)); + data = data.Skip(4).ToArray(); + break; + case "ipv6": + validateDataLength(16, ref data); + value = new IPv6Address(data.Take(16)); + data = data.Skip(16).ToArray(); + break; + case "mac-address": + validateDataLength(6, ref data); + value = new MACAddress(data.Take(6)); + data = data.Skip(6).ToArray(); + break; + + //Known from E1.37-5 (2024) as uuid + case "uuid": + case "guid": + validateDataLength(16, ref data); + value = new Guid(data.Take(16).ToArray()); + data = data.Skip(16).ToArray(); + break; + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "pid": + validateDataLength(2, ref data); + value = Tools.DataToEnum(ref data); + break; + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "double": + validateDataLength(8, ref data); + value = BitConverter.ToDouble(data.Take(8).ToArray(), 0); + data = data.Skip(8).ToArray(); + break; + case "float": + validateDataLength(4, ref data); + value = BitConverter.ToSingle(data.Take(4).ToArray(), 0); + data = data.Skip(4).ToArray(); + break; + + + //Additional added, because there is no fancy way to di this with E1.37-5 (2024) + case "ascii": + value = getNullDelimitetData(Encoding.ASCII, ref data); + break; + case "utf8": + value = getNullDelimitetData(Encoding.UTF8, ref data); + break; + case "utf32": + value = getNullDelimitetData(Encoding.UTF32, ref data); + break; + case "unicode": + value = getNullDelimitetData(Encoding.Unicode, ref data); + break; + case "big_edian_unicode": + value = getNullDelimitetData(Encoding.BigEndianUnicode, ref data); + break; + case "latin1": + value = getNullDelimitetData(Encoding.Latin1,ref data); + break; + + //Fallback + default: + value = data; + data = data.Skip(data.Length).ToArray(); + issueList.Add(new DataTreeIssue($"No Parser found for {nameof(Format)}: \"{Format}\"")); + break; + } + return value; + + string getNullDelimitetData(Encoding encoding, ref byte[] data) + { + string res = encoding.GetString(data); + if (res.Contains('\0')) + { + res = res.Split('\0')[0]; + int count = encoding.GetByteCount(res + "\0"); + data = data.Skip(count).ToArray(); + } + else + data = new byte[0]; + return res; + } + } + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/CompoundType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/CompoundType.cs new file mode 100644 index 0000000..0f964f5 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/CompoundType.cs @@ -0,0 +1,120 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text.Json.Serialization; + +[assembly: InternalsVisibleTo("RDMSharpTests")] + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class CompoundType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + [JsonPropertyName("subtypes")] + [JsonPropertyOrder(11)] + public OneOfTypes[] Subtypes { get; } + + + [JsonConstructor] + public CompoundType(string name, + string displayName, + string notes, + string[] resources, + string type, + OneOfTypes[] subtypes) + { + if (!"compound".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"compound\""); + + if (((subtypes?.Length) ?? 0) < 1) + throw new ArgumentException($"Argument {nameof(subtypes)} has to be at least a size of 1"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Subtypes = subtypes; + } + + public override PDL GetDataLength() + { + return new PDL(Subtypes.Select(s => s.GetDataLength()).ToArray()); + } + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + + if(dataTree.Children.Length!= Subtypes.Length) + throw new ArithmeticException($"The given {nameof(dataTree)} and {nameof(Subtypes)} has different length "); + + List data = new List(); + for (int i = 0; i < dataTree.Children.Length; i++) + { + if (Subtypes[i].IsEmpty()) + throw new ArithmeticException($"The given Object from {nameof(Subtypes)}[{i}] is Empty"); + + data.AddRange(Subtypes[i].ParsePayloadToData(dataTree.Children[i])); + } + + validateDataLength(data.Count); + + return data.ToArray(); + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + List subTypeDataTree = new List(); + List issueList = new List(); + + int dataLength = data.Length; + + for (int i = 0; i < Subtypes.Length; i++) + { + OneOfTypes subType = Subtypes[i]; + subTypeDataTree.Add(new DataTree(subType.ParseDataToPayload(ref data), (uint)i)); + } + dataLength -= data.Length; + + try + { + validateDataLength(dataLength); + } + catch (Exception e) + { + issueList.Add(new DataTreeIssue(e.Message)); + } + + return new DataTree(this.Name, 0, children:subTypeDataTree.OrderBy(b => b.Index).ToArray(), issueList.Count != 0 ? issueList.ToArray() : null); + } + + internal bool validateDataLength(int dataLength) + { + if (!GetDataLength().IsValid(dataLength)) + throw new ArithmeticException($"Parsed DataLength not fits Calculated DataLength"); + + return true; + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/EIntegerType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/EIntegerType.cs new file mode 100644 index 0000000..add763d --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/EIntegerType.cs @@ -0,0 +1,30 @@ +using RDMSharp.Metadata.JSON.Converter; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + [JsonConverter(typeof(CustomEnumConverter))] + public enum EIntegerType + { + [JsonPropertyName("int8")] + Int8, + [JsonPropertyName("int16")] + Int16, + [JsonPropertyName("int32")] + Int32, + [JsonPropertyName("int64")] + Int64, + [JsonPropertyName("int128")] + Int128, + [JsonPropertyName("uint8")] + UInt8, + [JsonPropertyName("uint16")] + UInt16, + [JsonPropertyName("uint32")] + UInt32, + [JsonPropertyName("uint64")] + UInt64, + [JsonPropertyName("uint128")] + UInt128 + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/IIntegerType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/IIntegerType.cs new file mode 100644 index 0000000..36d67ae --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/IIntegerType.cs @@ -0,0 +1,21 @@ +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public interface IIntegerType + { + string Name { get; } + string DisplayName { get; } + bool? RestrictToLabeled { get; } + string Notes { get; } + EIntegerType Type { get; } + ERDM_SensorUnit? Units { get; } + int? PrefixPower { get; } + int? PrefixBase { get; } + double PrefixMultiplyer { get; } + + bool IsInRange(object number); + object GetMaximum(); + object GetMinimum(); + object Increment(object number); + object IncrementJumpRange(object number); + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/IntegerType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/IntegerType.cs new file mode 100644 index 0000000..dc12f66 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/IntegerType.cs @@ -0,0 +1,453 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class IntegerType : CommonPropertiesForNamed, IIntegerType + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public EIntegerType Type { get; } + [JsonPropertyName("labels")] + [JsonPropertyOrder(31)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LabeledIntegerType[] Labels { get; } + [JsonPropertyName("restrictToLabeled")] + [JsonPropertyOrder(32)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? RestrictToLabeled { get; } + [JsonPropertyName("ranges")] + [JsonPropertyOrder(11)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public Range[] Ranges { get; } + [JsonPropertyName("units")] + [JsonPropertyOrder(21)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ERDM_SensorUnit? Units { get; } + [JsonPropertyName("prefixPower")] + [JsonPropertyOrder(22)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? PrefixPower { get; } = 0; + [JsonPropertyName("prefixBase")] + [JsonPropertyOrder(23)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? PrefixBase { get; } = 10; + + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public double PrefixMultiplyer { get; } + + [JsonConstructor] + public IntegerType(string name, + string displayName, + string notes, + string[] resources, + EIntegerType type, + LabeledIntegerType[] labels, + bool? restrictToLabeled, + Range[] ranges, + ERDM_SensorUnit? units, + int? prefixPower, + int? prefixBase) : base() + { + validateType(type); + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Labels = labels; + RestrictToLabeled = restrictToLabeled; + Ranges = ranges; + Units = units; + PrefixPower = prefixPower; + PrefixBase = prefixBase; + + PrefixMultiplyer = Math.Pow(PrefixBase ?? 10, PrefixPower ?? 0); + } + + private static void validateType(EIntegerType type, T dummy = default) + { + switch (dummy) + { + case sbyte when type is not EIntegerType.Int8: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.Int8}\""); + + case byte when type is not EIntegerType.UInt8: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.UInt8}\""); + + case short when type is not EIntegerType.Int16: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.Int16}\""); + + case ushort when type is not EIntegerType.UInt16: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.UInt16}\""); + + case int when type is not EIntegerType.Int32: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.Int32}\""); + + case uint when type is not EIntegerType.UInt32: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.UInt32}\""); + + case long when type is not EIntegerType.Int64: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.Int64}\""); + + case ulong when type is not EIntegerType.UInt64: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.UInt64}\""); +#if NET7_0_OR_GREATER + case Int128 when type is not EIntegerType.Int128: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.Int128}\""); + + case UInt128 when type is not EIntegerType.UInt128: + throw new ArgumentException($"Argument {nameof(type)} has to be \"{EIntegerType.UInt128}\""); +#endif + } + } + + public override string ToString() + { + if (Labels != null) + return $"{Name} {Type} -> [ {string.Join("; ", Labels.Select(l => l.ToString()))} ]"; + + return $"{Name} {Type}"; + } + + public override PDL GetDataLength() + { + switch (Type) + { + case EIntegerType.Int8: + case EIntegerType.UInt8: + return new PDL(1); + + case EIntegerType.Int16: + case EIntegerType.UInt16: + return new PDL(2); + + case EIntegerType.Int32: + case EIntegerType.UInt32: + return new PDL(4); + + case EIntegerType.Int64: + case EIntegerType.UInt64: + return new PDL(8); + } + return new PDL(16); + } + + private T convertFormatedValueToRaw(object formated) + { + if (PrefixMultiplyer == 1) + return (T)formated; + + object rawValue = null; + switch (formated) + { + case double _double: + rawValue = _double / PrefixMultiplyer; + break; + case long _long: + rawValue = _long / PrefixMultiplyer; + break; + case ulong _ulong: + rawValue = _ulong / PrefixMultiplyer; + break; + + default: + return (T)formated; + } + + if (rawValue is not null) + return (T)Convert.ChangeType(rawValue, typeof(T)); + + throw new NotImplementedException(); + } + + private object convertRawValueToFormated(T raw) + { + if (PrefixMultiplyer == 1) + return raw; + + bool isNegativ = Math.Sign(PrefixMultiplyer) == -1; + bool isDezimal = PrefixPower < 0; + + switch (raw) + { + case sbyte int8: + if (isDezimal) + return (double)(PrefixMultiplyer * int8); + if (isNegativ) + return (long)(PrefixMultiplyer * int8); + return (ulong)(PrefixMultiplyer * int8); + + case byte uint8: + if (isDezimal) + return (double)(PrefixMultiplyer * uint8); + if (isNegativ) + return (long)(PrefixMultiplyer * uint8); + return (ulong)(PrefixMultiplyer * uint8); + + case short int16: + if (isDezimal) + return (double)(PrefixMultiplyer * int16); + if (isNegativ) + return (long)(PrefixMultiplyer * int16); + return (ulong)(PrefixMultiplyer * int16); + + case ushort uint16: + if (isDezimal) + return (double)(PrefixMultiplyer * uint16); + if (isNegativ) + return (long)(PrefixMultiplyer * uint16); + return (ulong)(PrefixMultiplyer * uint16); + + case int int32: + if (isDezimal) + return (double)(PrefixMultiplyer * int32); + if (isNegativ) + return (long)(PrefixMultiplyer * int32); + return (ulong)(PrefixMultiplyer * int32); + + case uint uint32: + if (isDezimal) + return (double)(PrefixMultiplyer * uint32); + if (isNegativ) + return (long)(PrefixMultiplyer * uint32); + return (ulong)(PrefixMultiplyer * uint32); + + case long int64: + if (isDezimal) + return (double)(PrefixMultiplyer * int64); + if (isNegativ) + return (long)(PrefixMultiplyer * int64); + return (ulong)(PrefixMultiplyer * int64); + + case ulong uint64: + if (isDezimal) + return (double)(PrefixMultiplyer * uint64); + if (isNegativ) + return (long)(PrefixMultiplyer * uint64); + return (ulong)(PrefixMultiplyer * uint64); + + default: + return raw; + } + throw new NotImplementedException(); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + + var rawValue = convertFormatedValueToRaw(dataTree.Value); + if (Ranges != null) + { + if (!Ranges.Any(r => r.IsInRange(rawValue))) + throw new ArithmeticException("The Value is not in range of any Range"); + } + var data = Tools.ValueToData(rawValue); + + return data; + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + List issueList = new List(); + uint pdl = GetDataLength().Value.Value; + + if (data.Length < pdl) + { + issueList.Add(new DataTreeIssue("Given Data not fits PDL")); + byte[] cloneData = new byte[pdl]; + Array.Copy(data, cloneData, data.Length); + data = cloneData; + } + + object value = null; + + switch (this.Type) + { + case EIntegerType.Int8: + value = Tools.DataToSByte(ref data); + break; + case EIntegerType.UInt8: + value = Tools.DataToByte(ref data); + break; + case EIntegerType.Int16: + value = Tools.DataToShort(ref data); + break; + case EIntegerType.UInt16: + value = Tools.DataToUShort(ref data); + break; + case EIntegerType.Int32: + value = Tools.DataToInt(ref data); + break; + case EIntegerType.UInt32: + value = Tools.DataToUInt(ref data); + break; + case EIntegerType.Int64: + value = Tools.DataToLong(ref data); + break; + case EIntegerType.UInt64: + value = Tools.DataToULong(ref data); + break; +#if NET7_0_OR_GREATER + case EIntegerType.Int128: + value = Tools.DataToInt128(ref data); + break; + case EIntegerType.UInt128: + value = Tools.DataToUInt128(ref data); + break; +#endif + } + if (Ranges != null) + { + if (!Ranges.Any(r => r.IsInRange((T)value))) + issueList.Add(new DataTreeIssue("The Value is not in range of any Range")); + } + + string unit = null; + if (Units.HasValue) + unit = Tools.GetUnitSymbol(Units.Value); + DataTreeValueLabel[] labels = null; + if ((Labels?.Length ?? 0) != 0) + labels = Labels.Select(lb => new DataTreeValueLabel(lb.Value, (lb.DisplayName ?? lb.Name))).ToArray(); + + return new DataTree(this.Name, 0, convertRawValueToFormated((T)value), issueList.Count != 0 ? issueList.ToArray() : null, unit, labels); + } + + public bool IsInRange(object number) + { + if (Ranges != null) + return Ranges.Any(r => r.IsInRange((T)number)); + + return new Range((T)GetMinimum(), (T)GetMaximum()).IsInRange((T)number); + } + + public object GetMaximum() + { + if (Ranges != null) + return Ranges.Max(r => r.Maximum); + + switch (this.Type) + { + case EIntegerType.Int8: + return sbyte.MaxValue; + case EIntegerType.UInt8: + return byte.MaxValue; + case EIntegerType.Int16: + return short.MaxValue; + case EIntegerType.UInt16: + return ushort.MaxValue; + case EIntegerType.Int32: + return int.MaxValue; + case EIntegerType.UInt32: + return uint.MaxValue; + case EIntegerType.Int64: + return long.MaxValue; + case EIntegerType.UInt64: + return ulong.MaxValue; +#if NET7_0_OR_GREATER + case EIntegerType.Int128: + return Int128.MaxValue; + case EIntegerType.UInt128: + return UInt128.MaxValue; +#endif + } + throw new NotImplementedException(); + } + + public object GetMinimum() + { + if (Ranges != null) + return Ranges.Min(r => r.Minimum); + + switch (this.Type) + { + case EIntegerType.Int8: + return sbyte.MinValue; + case EIntegerType.UInt8: + return byte.MinValue; + case EIntegerType.Int16: + return short.MinValue; + case EIntegerType.UInt16: + return ushort.MinValue; + case EIntegerType.Int32: + return int.MinValue; + case EIntegerType.UInt32: + return uint.MinValue; + case EIntegerType.Int64: + return long.MinValue; + case EIntegerType.UInt64: + return ulong.MinValue; +#if NET7_0_OR_GREATER + case EIntegerType.Int128: + return Int128.MinValue; + case EIntegerType.UInt128: + return UInt128.MinValue; +#endif + } + throw new NotImplementedException(); + } + + public object Increment(object number) + { + switch (this.Type) + { + case EIntegerType.Int8: + return (sbyte)((sbyte)number + 1); + case EIntegerType.UInt8: + return (byte)((byte)number + 1); + case EIntegerType.Int16: + return (short)((short)number + 1); + case EIntegerType.UInt16: + return (ushort)((ushort)number + 1); + case EIntegerType.Int32: + return (int)((int)number + 1); + case EIntegerType.UInt32: + return (uint)((uint)number + 1); + case EIntegerType.Int64: + return (long)((long)number + 1); + case EIntegerType.UInt64: + return (ulong)((ulong)number + 1); +#if NET7_0_OR_GREATER + case EIntegerType.Int128: + return (Int128)((Int128)number + 1); + case EIntegerType.UInt128: + return (UInt128)((UInt128)number + 1); +#endif + } + return number; + } + + public object IncrementJumpRange(object number) + { + object incremented = Increment(number); + if (IsInRange(incremented)) + return incremented; + + if (Ranges != null) + return Ranges.Where(r => r.IsBelow((T)incremented)).Min(r => r.Minimum); + + return false; + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/LabeledBooleanType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/LabeledBooleanType.cs new file mode 100644 index 0000000..8ded8c2 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/LabeledBooleanType.cs @@ -0,0 +1,66 @@ +using System; +using System.Text.Json.Serialization; +using RDMSharp.RDM; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class LabeledBooleanType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("value")] + [JsonPropertyOrder(3)] + public bool Value { get; } + + [JsonConstructor] + public LabeledBooleanType(string name, + string displayName, + string notes, + string[] resources, + bool value) : base() + { + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Value = value; + } + public LabeledBooleanType(string name, bool value) : this(name, null, null, null, value) + { + } + + public override string ToString() + { + return $"{Value} -> {Name}"; + } + + public override PDL GetDataLength() + { + throw new NotSupportedException(); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + throw new NotSupportedException(); + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + throw new NotSupportedException(); + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/LabeledIntegerType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/LabeledIntegerType.cs new file mode 100644 index 0000000..5f88836 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/LabeledIntegerType.cs @@ -0,0 +1,67 @@ +using RDMSharp.RDM; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class LabeledIntegerType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("value")] + [JsonPropertyOrder(3)] + public long Value { get; } + + [JsonConstructor] + public LabeledIntegerType(string name, + string displayName, + string notes, + string[] resources, + long value) : base() + { + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Value = value; + } + + public LabeledIntegerType(string name, long value): this(name, null, null, null, value) + { + + } + + public override string ToString() + { + return $"{Value} -> {Name}"; + } + public override PDL GetDataLength() + { + throw new NotSupportedException(); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + throw new NotSupportedException(); + } + public override DataTree ParseDataToPayload(ref byte[] data) + { + throw new NotSupportedException(); + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/ListType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/ListType.cs new file mode 100644 index 0000000..7c30ba2 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/ListType.cs @@ -0,0 +1,177 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text.Json.Serialization; + +[assembly: InternalsVisibleTo("RDMSharpTests")] + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class ListType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + [JsonPropertyName("itemType")] + [JsonPropertyOrder(21)] + public OneOfTypes ItemType { get; } + [JsonPropertyName("minItems")] + [JsonPropertyOrder(31)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MinItems { get; } + [JsonPropertyName("maxItems")] + [JsonPropertyOrder(32)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MaxItems { get; } + + + [JsonConstructor] + public ListType(string name, + string displayName, + string notes, + string[] resources, + string type, + OneOfTypes itemType, + uint? minItems, + uint? maxItems) : base() + { + if (!"list".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"list\""); + + if (itemType.IsEmpty()) + throw new ArgumentException($"Argument {nameof(itemType)} is Empty, this is not allowed"); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + ItemType = itemType; + MinItems = minItems; + MaxItems = maxItems; + } + + public override string ToString() + { + return DisplayName ?? Name; + } + + public override PDL GetDataLength() + { + uint min = 0; + uint max = 0; + + if (MinItems.HasValue) + min = MinItems.Value; + if (MaxItems.HasValue) + max = MaxItems.Value; + + PDL itemPDL = ItemType.GetDataLength(); + if (itemPDL.Value.HasValue) + { + min *= itemPDL.Value.Value; + max *= itemPDL.Value.Value; + } + else + { + if (itemPDL.MinLength.HasValue) + min *= itemPDL.MinLength.Value; + if (itemPDL.MaxLength.HasValue) + max *= itemPDL.MaxLength.Value; + } + + if (max == 0) + if (!MaxItems.HasValue) + max = PDL.MAX_LENGTH; + + if (min == max) + return new PDL(min); + + return new PDL(min, max); + } + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + + List data = new List(); + for (int i = 0; i < dataTree.Children.Length; i++) + data.AddRange(ItemType.ParsePayloadToData(dataTree.Children[i])); + + validateDataLength(data.Count); + + return data.ToArray(); + } + + public override DataTree ParseDataToPayload(ref byte[] data) + { + List dataTrees = new List(); + List issueList = new List(); + + uint index = 0; + int dataLength = data.Length; + while (_continue(ref data)) + { + dataTrees.Add(new DataTree(ItemType.ParseDataToPayload(ref data), index)); + index++; + } + dataLength -= data.Length; + + try + { + validateDataLength(dataLength); + } + catch (Exception e) + { + issueList.Add(new DataTreeIssue(e.Message)); + } + + return new DataTree(Name, 0, children: dataTrees.ToArray(), issueList.Count != 0 ? issueList.ToArray() : null); + + bool _continue(ref byte[] data) + { + if (MaxItems.HasValue) + if (dataTrees.Count > MaxItems.Value) + { + if (dataTrees.Count > 0) + issueList.Add(new DataTreeIssue($"Given data exceeds {nameof(MaxItems)}")); + return false; + } + if (data.Length == 0) + { + if (MinItems.HasValue) + if (dataTrees.Count < MinItems.Value) + issueList.Add(new DataTreeIssue($"Given data falls shorts of {nameof(MinItems)}")); + return false; + } + + return true; + } + } + internal bool validateDataLength(int dataLength) + { + if (!GetDataLength().IsValid(dataLength)) + throw new ArithmeticException($"Parsed DataLength not fits Calculated DataLength"); + + return true; + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/OneOfTypes.cs b/RDMSharp/Metadata/JSON/OneOfTypes/OneOfTypes.cs new file mode 100644 index 0000000..270c068 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/OneOfTypes.cs @@ -0,0 +1,151 @@ +using RDMSharp.Metadata.JSON.Converter; +using RDMSharp.RDM; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + [JsonConverter(typeof(OneOfTypesConverter))] + public readonly struct OneOfTypes + { + public readonly CommonPropertiesForNamed ObjectType; + public readonly BitFieldType BitFieldType { get; } + public readonly BytesType BytesType { get; } + public readonly BooleanType BooleanType { get; } + public readonly IntegerType IntegerType_UInt8 { get; } + public readonly IntegerType IntegerType_Int8 { get; } + public readonly IntegerType IntegerType_UInt16 { get; } + public readonly IntegerType IntegerType_Int16 { get; } + public readonly IntegerType IntegerType_UInt32 { get; } + public readonly IntegerType IntegerType_Int32 { get; } + public readonly IntegerType IntegerType_UInt64 { get; } + public readonly IntegerType IntegerType_Int64 { get; } +#if NET7_0_OR_GREATER + public readonly IntegerType IntegerType_UInt128 { get; } + public readonly IntegerType IntegerType_Int128 { get; } +#endif + public readonly ReferenceType? ReferenceType { get; } + public readonly ListType ListType { get; } + public readonly CompoundType CompoundType { get; } + public readonly StringType StringType { get; } + public readonly PD_EnvelopeType PD_EnvelopeType { get; } + + public OneOfTypes(BitFieldType bitFieldType) + { + BitFieldType = bitFieldType; + ObjectType = bitFieldType; + } + public OneOfTypes(BytesType bytesType) + { + BytesType = bytesType; + ObjectType = bytesType; + } + public OneOfTypes(BooleanType booleanType) + { + BooleanType = booleanType; + ObjectType = booleanType; + } + public OneOfTypes(IntegerType integerType_UInt8) + { + IntegerType_UInt8 = integerType_UInt8; + ObjectType = integerType_UInt8; + } + public OneOfTypes(IntegerType integerType_Int8) + { + IntegerType_Int8 = integerType_Int8; + ObjectType = integerType_Int8; + } + public OneOfTypes(IntegerType integerType_UInt16) + { + IntegerType_UInt16 = integerType_UInt16; + ObjectType = integerType_UInt16; + } + public OneOfTypes(IntegerType integerType_Int16) + { + IntegerType_Int16 = integerType_Int16; + ObjectType = integerType_Int16; + } + public OneOfTypes(IntegerType integerType_UInt32) + { + IntegerType_UInt32 = integerType_UInt32; + ObjectType = integerType_UInt32; + } + public OneOfTypes(IntegerType integerType_Int32) + { + IntegerType_Int32 = integerType_Int32; + ObjectType = integerType_Int32; + } + public OneOfTypes(IntegerType integerType_UInt64) + { + IntegerType_UInt64 = integerType_UInt64; + ObjectType = integerType_UInt64; + } + public OneOfTypes(IntegerType integerType_Int64) + { + IntegerType_Int64 = integerType_Int64; + ObjectType = integerType_Int64; + } +#if NET7_0_OR_GREATER + public OneOfTypes(IntegerType integerType_UInt128) + { + IntegerType_UInt128 = integerType_UInt128; + ObjectType = integerType_UInt128; + } + public OneOfTypes(IntegerType integerType_Int128) + { + IntegerType_Int128 = integerType_Int128; + ObjectType = integerType_Int128; + } +#endif + public OneOfTypes(ReferenceType referenceType) + { + ReferenceType = referenceType; + } + public OneOfTypes(StringType stringType) + { + StringType = stringType; + ObjectType = stringType; + } + public OneOfTypes(ListType listType) + { + ListType = listType; + ObjectType = listType; + } + public OneOfTypes(CompoundType compoundType) + { + CompoundType = compoundType; + ObjectType = compoundType; + } + public OneOfTypes(PD_EnvelopeType pdEnvelopeType) + { + PD_EnvelopeType = pdEnvelopeType; + ObjectType = pdEnvelopeType; + } + + public bool IsEmpty() + { + return getObjectType() == null; + } + public PDL GetDataLength() + { + return getObjectType()?.GetDataLength() ?? new PDL(); + } + public byte[] ParsePayloadToData(DataTree dataTree) + { + return getObjectType().ParsePayloadToData(dataTree); + } + public DataTree ParseDataToPayload(ref byte[] data) + { + return getObjectType().ParseDataToPayload(ref data); + } + private CommonPropertiesForNamed getObjectType() + { + return ObjectType ?? ReferenceType?.ReferencedObject; + } + + public override string ToString() + { + return getObjectType()?.ToString(); + } + } +} \ No newline at end of file diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/PD_EnvelopeType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/PD_EnvelopeType.cs new file mode 100644 index 0000000..70dd548 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/PD_EnvelopeType.cs @@ -0,0 +1,81 @@ +using RDMSharp.RDM; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class PD_EnvelopeType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(4)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + + [JsonPropertyName("length")] + [JsonPropertyOrder(6)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public byte? Length { get; } + + + [JsonConstructor] + public PD_EnvelopeType(string name, + string displayName, + string notes, + string[] resources, + string type, + byte? length) : base() + { + if (!"pdEnvelope".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"pdEnvelope\""); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Length = length; + } + + public override string ToString() + { + if (Length.HasValue) + return $"PDL: {Length} ({Length:X2}) {base.ToString()}".Trim(); + + return base.ToString(); + } + + public override PDL GetDataLength() + { + if(Length.HasValue) + return new PDL(Length.Value); + + return new PDL(); + } + + public override byte[] ParsePayloadToData(DataTree dataTree) + { + return new byte[0]; + } + + public override DataTree ParseDataToPayload(ref byte[] data) + { + return new DataTree(Name, 0, null); + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/Range.cs b/RDMSharp/Metadata/JSON/OneOfTypes/Range.cs new file mode 100644 index 0000000..cf16b0c --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/Range.cs @@ -0,0 +1,106 @@ +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public readonly struct Range + { + [JsonPropertyName("minimum")] + public readonly T Minimum { get; } + + [JsonPropertyName("maximum")] + public readonly T Maximum { get; } + + [JsonConstructor] + public Range(T minimum, T maximum) + { + Minimum = minimum; + Maximum = maximum; + } + + public bool IsInRange(T value) + { + switch (value) + { + case byte v when Minimum is byte min && Maximum is byte max: + return min <= v && v <= max; + case sbyte v when Minimum is sbyte min && Maximum is sbyte max: + return min <= v && v <= max; + case short v when Minimum is short min && Maximum is short max: + return min <= v && v <= max; + case ushort v when Minimum is ushort min && Maximum is ushort max: + return min <= v && v <= max; + case int v when Minimum is int min && Maximum is int max: + return min <= v && v <= max; + case uint v when Minimum is uint min && Maximum is uint max: + return min <= v && v <= max; + case long v when Minimum is long min && Maximum is long max: + return min <= v && v <= max; + case ulong v when Minimum is ulong min && Maximum is ulong max: + return min <= v && v <= max; +# if NET7_0_OR_GREATER + case Int128 v when Minimum is Int128 min && Maximum is Int128 max: + return min <= v && v <= max; + case UInt128 v when Minimum is UInt128 min && Maximum is UInt128 max: + return min <= v && v <= max; +#endif + } + return false; + } + + public bool IsBelow(T value) + { + switch (value) + { + case byte v when Minimum is byte min: + return min > v; + case sbyte v when Minimum is sbyte min: + return min > v; + case short v when Minimum is short min: + return min > v; + case ushort v when Minimum is ushort min: + return min > v; + case int v when Minimum is int min: + return min > v; + case uint v when Minimum is uint min: + return min > v; + case long v when Minimum is long min: + return min > v; + case ulong v when Minimum is ulong min: + return min > v; +# if NET7_0_OR_GREATER + case Int128 v when Minimum is Int128 min: + return min > v; + case UInt128 v when Minimum is UInt128 min: + return min > v; +#endif + } + return false; + } + + public override string ToString() + { + switch (Minimum) + { + case byte: + case sbyte: + return $"Range: {Minimum:X2} - {Maximum:X2}"; + case short: + case ushort: + return $"Range: {Minimum:X4} - {Maximum:X4}"; + case int: + case uint: + return $"Range: {Minimum:X8} - {Maximum:X8}"; + case long: + case ulong: + return $"Range: {Minimum:X16} - {Maximum:X16}"; +#if NET7_0_OR_GREATER + case Int128: + case UInt128: + return $"Range: {Minimum:X32} - {Maximum:X32}"; +#endif + } + return $"Range: {Minimum} - {Maximum}"; + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/ReferenceType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/ReferenceType.cs new file mode 100644 index 0000000..c3d58ac --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/ReferenceType.cs @@ -0,0 +1,70 @@ +using RDMSharp.RDM; +using System; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public readonly struct ReferenceType + { + [JsonPropertyName("$ref")] + public readonly string URI { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public readonly Command.ECommandDublicte Command { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public readonly ushort Pointer { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public readonly CommonPropertiesForNamed? ReferencedObject { get; } + + [JsonConstructor] + public ReferenceType(string uri) + { + URI = uri; + if (uri.StartsWith("#")) + { + string fragment = uri.Substring(1); + + string[] segments = fragment.Split('/', StringSplitOptions.RemoveEmptyEntries); + + switch (segments[0]) + { + case "get_request": + Command = JSON.Command.ECommandDublicte.GetRequest; + break; + case "get_response": + Command = JSON.Command.ECommandDublicte.GetResponse; + break; + case "set_request": + Command = JSON.Command.ECommandDublicte.SetRequest; + break; + case "set_response": + Command = JSON.Command.ECommandDublicte.SetResponse; + break; + } + Pointer = ushort.Parse(segments[1]); + } + else + throw new ArgumentException($"{nameof(uri)} has to start with \'#\'"); + } + public ReferenceType(string uri, CommonPropertiesForNamed referencedObject) : this(uri) + { + ReferencedObject = referencedObject; + } + public PDL GetDataLength() + { + return ReferencedObject?.GetDataLength() ?? new PDL(); + } + public byte[] ParsePayloadToData(DataTree dataTree) + { + return ReferencedObject.ParsePayloadToData(dataTree); + } + + public DataTree ParseDataToPayload(ref byte[] data) + { + return ReferencedObject.ParseDataToPayload(ref data); + } + public override string ToString() + { + return URI; + } + } +} diff --git a/RDMSharp/Metadata/JSON/OneOfTypes/StringType.cs b/RDMSharp/Metadata/JSON/OneOfTypes/StringType.cs new file mode 100644 index 0000000..978ac03 --- /dev/null +++ b/RDMSharp/Metadata/JSON/OneOfTypes/StringType.cs @@ -0,0 +1,230 @@ +using RDMSharp.RDM; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON.OneOfTypes +{ + public class StringType : CommonPropertiesForNamed + { + [JsonPropertyName("name")] + [JsonPropertyOrder(1)] + [JsonIgnore(Condition = JsonIgnoreCondition.Never)] + public override string Name { get; } + [JsonPropertyName("displayName")] + [JsonPropertyOrder(2)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string DisplayName { get; } + [JsonPropertyName("notes")] + [JsonPropertyOrder(25)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string Notes { get; } + [JsonPropertyName("resources")] + [JsonPropertyOrder(5)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public override string[] Resources { get; } + + [JsonPropertyName("type")] + [JsonPropertyOrder(3)] + public string Type { get; } + [JsonPropertyName("format")] + [JsonPropertyOrder(21)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Format { get; } + [JsonPropertyName("pattern")] + [JsonPropertyOrder(22)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Pattern { get; } + [JsonPropertyName("minLength")] + [JsonPropertyOrder(31)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MinLength { get; } + [JsonPropertyName("maxLength")] + [JsonPropertyOrder(32)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MaxLength { get; } + [JsonPropertyName("minBytes")] + [JsonPropertyOrder(41)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MinBytes { get; } + [JsonPropertyName("maxBytes")] + [JsonPropertyOrder(42)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? MaxBytes { get; } + [JsonPropertyName("restrictToASCII")] + [JsonPropertyOrder(51)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? RestrictToASCII { get; } + + + [JsonConstructor] + public StringType(string name, + string displayName, + string notes, + string[] resources, + string type, + string format, + string pattern, + uint? minLength, + uint? maxLength, + uint? minBytes, + uint? maxBytes, + bool? restrictToASCII) + { + if (!"string".Equals(type)) + throw new ArgumentException($"Argument {nameof(type)} has to be \"string\""); + + Name = name; + DisplayName = displayName; + Notes = notes; + Resources = resources; + Type = type; + Format = format; + Pattern = pattern; + MinLength = minLength; + MaxLength = maxLength; + MinBytes = minBytes; + MaxBytes = maxBytes; + RestrictToASCII = restrictToASCII; + } + public StringType( + string name, + string displayName, + string notes, + string format, + string pattern, + uint length, + bool? restrictToASCII = null) : this( + name, + displayName, + notes, + null, + "string", + format, + pattern, + minLength: length, + maxLength: length, + null, + null, + restrictToASCII) + { + } + public override string ToString() + { + return base.ToString(); + } + + public override PDL GetDataLength() + { + uint min = 0; + uint? max = null; + if (MinLength.HasValue) + min = (uint)MinLength.Value; + if (MaxLength.HasValue) + max = (uint)MaxLength.Value; + if (MinBytes.HasValue) + min = (uint)MinBytes.Value; + if (MaxBytes.HasValue) + max = (uint)MaxBytes.Value; + + if (!max.HasValue) + return new PDL(min, PDL.MAX_LENGTH); + + return new PDL(min, max.Value); + } + public override byte[] ParsePayloadToData(DataTree dataTree) + { + if (!string.Equals(dataTree.Name, this.Name)) + throw new ArithmeticException($"The given Name from {nameof(dataTree.Name)}({dataTree.Name}) not match this Name({this.Name})"); + + if (dataTree.Value is string @string) + { + if (MinLength.HasValue && MinLength.Value > @string.Length) + throw new ArithmeticException($"The given String is smaller then {nameof(MinLength)}: {MinLength}"); + if (MaxLength.HasValue && MaxLength.Value < @string.Length) + throw new ArithmeticException($"The given String is larger then {nameof(MaxLength)}: {MaxLength}"); + + Encoding encoder = null; + if (RestrictToASCII == true) + encoder = Encoding.ASCII; + else + encoder = Encoding.UTF8; + + var data = encoder.GetBytes(@string); + + if (MinBytes.HasValue && MinBytes.Value > data.Length) + throw new ArithmeticException($"The given String encoded is smaller then {nameof(MinBytes)}: {MinBytes}"); + if (MaxBytes.HasValue && MaxBytes.Value < data.Length) + throw new ArithmeticException($"The given String encoded is larger then {nameof(MaxBytes)}: {MaxBytes}"); + + return data; + } + + throw new ArithmeticException($"The given Object from {nameof(dataTree.Value)} can't be parsed"); + } + + public override DataTree ParseDataToPayload(ref byte[] data) + { + List issueList = new List(); + if (MaxBytes.HasValue && data.Length > MaxBytes.Value) + issueList.Add(new DataTreeIssue($"Data length exceeds {nameof(MaxBytes)}, the Data has {data.Length}, but {nameof(MaxBytes)} is {MaxBytes}")); + if (MinBytes.HasValue && data.Length < MinBytes.Value) + issueList.Add(new DataTreeIssue($"Data length falls shorts of {nameof(MinBytes)}, the Data has {data.Length}, but {nameof(MinBytes)} is {MinBytes}")); + + string str = null; + byte[] dataBytes = data; + int charLength = 0; + int byteLength = 0; + int takenBytesCount = 0; + if (RestrictToASCII == true) + parse(Encoding.ASCII); + else + parse(Encoding.UTF8); + + void parse(Encoding encoder) + { + str = encoder.GetString(dataBytes); + takenBytesCount = dataBytes.Length; + + string[] strings = str.Split((char)0); + if (strings.Where(s => string.IsNullOrEmpty(s)).Count() > 1) + issueList.Add(new DataTreeIssue("More then one Null-Delimiter")); + if (strings.Skip(1).Any(s => !string.IsNullOrEmpty(s))) + issueList.Add(new DataTreeIssue("Trailing Characters")); + + str = strings.First(); + byteLength = encoder.GetBytes(str).Length; + takenBytesCount = byteLength; + charLength = str.Length; + bool repeatParse = false; + if (MaxLength.HasValue && MaxLength.Value < charLength) + { + charLength = (int)MaxLength.Value; + repeatParse = true; + } + if (MaxBytes.HasValue && MaxBytes.Value < byteLength) + { + byteLength = (int)MaxBytes.Value; + repeatParse = true; + } + if (repeatParse) + { + dataBytes = dataBytes.Take(byteLength).ToArray(); + str = encoder.GetString(dataBytes); + takenBytesCount = dataBytes.Length; + } + + } + + if (MaxLength.HasValue && str.Length > MaxLength.Value) + issueList.Add(new DataTreeIssue($"String length exceeds {nameof(MaxLength)}, the Data has {str.Length}, but {nameof(MaxLength)} is {MaxLength}")); + if (MinLength.HasValue && str.Length < MinLength.Value) + issueList.Add(new DataTreeIssue($"String length falls shorts of {nameof(MinLength)}, the Data has {str.Length}, but {nameof(MinLength)} is {MinLength}")); + + data = data.Skip(takenBytesCount).ToArray(); + return new DataTree(this.Name, 0, str, issueList.Count != 0 ? issueList.ToArray() : null); + } + } +} diff --git a/RDMSharp/Metadata/JSON/SubdeviceRange.cs b/RDMSharp/Metadata/JSON/SubdeviceRange.cs new file mode 100644 index 0000000..bb1260e --- /dev/null +++ b/RDMSharp/Metadata/JSON/SubdeviceRange.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata.JSON +{ + public readonly struct SubdeviceRange + { + [JsonPropertyName("minimum")] + public readonly ushort Minimum { get; } + + [JsonPropertyName("maximum")] + public readonly ushort Maximum { get; } + + [JsonConstructor] + public SubdeviceRange(ushort minimum, ushort maximum) : this() + { + Minimum = minimum; + Maximum = maximum; + } + public override string ToString() + { + return $"Subdevice Range: {Minimum:X4} - {Maximum:X4}"; + } + } +} diff --git a/RDMSharp/Metadata/JSON/SubdeviceType.cs b/RDMSharp/Metadata/JSON/SubdeviceType.cs new file mode 100644 index 0000000..312cdf3 --- /dev/null +++ b/RDMSharp/Metadata/JSON/SubdeviceType.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; +using RDMSharp.Metadata.JSON.Converter; + +namespace RDMSharp.Metadata.JSON +{ + [JsonConverter(typeof(SubdeviceTypeConverter))] + public readonly struct SubdeviceType + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly ushort? Value { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly SubdeviceRange? Range { get; } + public SubdeviceType(ushort value) : this() + { + Value = value; + } + + public SubdeviceType(SubdeviceRange range) : this() + { + Range = range; + } + public override string ToString() + { + return Value?.ToString() ?? Range.ToString(); + } + } +} diff --git a/RDMSharp/Metadata/JSON/SubdevicesForRequests.cs b/RDMSharp/Metadata/JSON/SubdevicesForRequests.cs new file mode 100644 index 0000000..9c80418 --- /dev/null +++ b/RDMSharp/Metadata/JSON/SubdevicesForRequests.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; +using RDMSharp.Metadata.JSON.Converter; + +namespace RDMSharp.Metadata.JSON +{ + [JsonConverter(typeof(SubdevicesForRequestsConverter))] + public readonly struct SubdevicesForRequests + { + [JsonConverter(typeof(CustomEnumConverter))] + public enum ESubdevicesForRequests + { + [JsonPropertyName("root")] + Root, + [JsonPropertyName("subdevices")] + Subdevices, + [JsonPropertyName("broadcast")] + Broadcast + } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly ESubdevicesForRequests? EnumValue { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly SubdeviceType? ObjectValue { get; } + public SubdevicesForRequests(ESubdevicesForRequests enumValue) + { + EnumValue = enumValue; + } + public SubdevicesForRequests(SubdeviceType objectValue) + { + ObjectValue = objectValue; + } + public override string ToString() + { + return EnumValue?.ToString() ?? ObjectValue.ToString(); + } + } +} diff --git a/RDMSharp/Metadata/JSON/SubdevicesForResponses.cs b/RDMSharp/Metadata/JSON/SubdevicesForResponses.cs new file mode 100644 index 0000000..86e6649 --- /dev/null +++ b/RDMSharp/Metadata/JSON/SubdevicesForResponses.cs @@ -0,0 +1,38 @@ +using System.Text.Json.Serialization; +using RDMSharp.Metadata.JSON.Converter; + +namespace RDMSharp.Metadata.JSON +{ + [JsonConverter(typeof(SubdevicesForResponsesConverter))] + public readonly struct SubdevicesForResponses + { + [JsonConverter(typeof(CustomEnumConverter))] + public enum ESubdevicesForResponses + { + [JsonPropertyName("root")] + Root, + [JsonPropertyName("subdevices")] + Subdevices, + [JsonPropertyName("broadcast")] + Broadcast, + [JsonPropertyName("match")] + Match + } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly ESubdevicesForResponses? EnumValue { get; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public readonly SubdeviceType? ObjectValue { get; } + public SubdevicesForResponses(ESubdevicesForResponses enumValue) + { + EnumValue = enumValue; + } + public SubdevicesForResponses(SubdeviceType objectValue) + { + ObjectValue = objectValue; + } + public override string ToString() + { + return EnumValue?.ToString() ?? ObjectValue.ToString(); + } + } +} diff --git a/RDMSharp/Metadata/MetadataBag.cs b/RDMSharp/Metadata/MetadataBag.cs new file mode 100644 index 0000000..c14dc62 --- /dev/null +++ b/RDMSharp/Metadata/MetadataBag.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("RDMSharpTests")] + +namespace RDMSharp.Metadata +{ + public readonly struct MetadataBag + { + public readonly string Version; + public readonly string Path; + public readonly string Name; + public readonly string Content; + public readonly bool IsSchema; + public MetadataBag(MetadataVersion metadataVersion) : this(metadataVersion.Version,metadataVersion.Name,metadataVersion.IsSchema, getContent(metadataVersion.Path), metadataVersion.Path) + { + } + public MetadataBag(string version, string name, bool isSchema, string content, string path) + { + Version = version; + Name= name; + IsSchema = isSchema; + Path = path; + Content = content; + } + internal static string getContent(string path) + { + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentNullException(nameof(path)); + + var assembly = typeof(MetadataFactory).Assembly; + using Stream stream = assembly.GetManifestResourceStream(path); + using StreamReader reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + public override string ToString() + { + return $"{Name} [{Version}]"; + } + } +} diff --git a/RDMSharp/Metadata/MetadataFactory.cs b/RDMSharp/Metadata/MetadataFactory.cs new file mode 100644 index 0000000..7fe8184 --- /dev/null +++ b/RDMSharp/Metadata/MetadataFactory.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Text.Json.Nodes; +using Json.Schema; +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; + +[assembly: InternalsVisibleTo("RDMSharpTests")] + +namespace RDMSharp.Metadata +{ + public static class MetadataFactory + { + private const string SCHEMA_FILE_NAME = "schema.json"; + private const string JSON_ENDING = ".json"; + private static List metadataVersionList; + private static Dictionary> metadataVersionDefinesBagDictionary; + private static ConcurrentDictionary parameterBagDefineCache; + + public static IReadOnlyCollection MetadataVersionList + { + get + { + if (metadataVersionList == null) + { + metadataVersionList = new List(); + metadataVersionList.AddRange(GetResources().Select(r => new MetadataVersion(r))); + } + return metadataVersionList.AsReadOnly(); + } + } + public static string[] GetResources() + { + var assembly = typeof(MetadataFactory).Assembly; + return assembly.GetManifestResourceNames(); + } + private static void fillDefaultMetadataVersionList() + { + metadataVersionList.AddRange(GetResources().Select(r => new MetadataVersion(r))); + + if (metadataVersionDefinesBagDictionary == null) + metadataVersionDefinesBagDictionary = new Dictionary>(); + + var schemaList = GetMetadataSchemaVersions(); + ConcurrentDictionary versionSchemas= new ConcurrentDictionary(); + + foreach (var mv in metadataVersionList.Where(_mv => !_mv.IsSchema)) + { + var schema = schemaList.First(s => s.Version.Equals(mv.Version)); + if(!versionSchemas.TryGetValue(schema.Version, out JsonSchema jsonSchema)) + { + jsonSchema= JsonSchema.FromText(new MetadataBag(schema).Content); + versionSchemas.TryAdd(schema.Version, jsonSchema); + } + MetadataBag metadataBag = new MetadataBag(mv); + var result = jsonSchema.Evaluate(JsonNode.Parse(metadataBag.Content)); + if (result.IsValid) + { + MetadataJSONObjectDefine jsonDefine = JsonSerializer.Deserialize(metadataBag.Content); + if (!metadataVersionDefinesBagDictionary.ContainsKey(schema)) + metadataVersionDefinesBagDictionary.Add(schema, new List()); + + metadataVersionDefinesBagDictionary[schema].Add(jsonDefine); + } + } + } + + public static IReadOnlyCollection GetMetadataSchemaVersions() + { + return MetadataVersionList.Where(r => r.IsSchema).ToList().AsReadOnly(); + } + public static IReadOnlyCollection GetMetadataDefineVersions() + { + return MetadataVersionList.Where(r => !r.IsSchema).ToList().AsReadOnly(); + } + internal static MetadataJSONObjectDefine GetDefine(ParameterBag parameter) + { + try + { + if (parameterBagDefineCache == null) + parameterBagDefineCache = new ConcurrentDictionary(); + + if (parameterBagDefineCache.TryGetValue(parameter, out var define)) + return define; + + define = getDefine(parameter); + if (define != null) + { + parameterBagDefineCache.TryAdd(parameter, define); + return define; + } + } + catch (Exception ex) + { + + } + throw new DefineNotFoundException($"{parameter}"); + } + private static MetadataJSONObjectDefine getDefine(ParameterBag parameter) + { + var version = GetMetadataSchemaVersions().First(); + if (metadataVersionDefinesBagDictionary == null) + fillDefaultMetadataVersionList(); + var possibleDefines = metadataVersionDefinesBagDictionary[version].FindAll(d => d.PID == (ushort)parameter.PID && d.ManufacturerID == parameter.ManufacturerID); + if (possibleDefines.Count == 1) + return possibleDefines[0]; + + if (possibleDefines.Count > 1) + { + MetadataJSONObjectDefine define = possibleDefines.FirstOrDefault(d => d.DeviceModelID == null && d.SoftwareVersionID == null); + if (parameter.DeviceModelID != null) + { + possibleDefines = possibleDefines.Where(d => d.DeviceModelID == parameter.DeviceModelID).ToList(); + if (possibleDefines.Count == 1) + define = possibleDefines[0]; + else if (possibleDefines.Count > 1) + { + define = possibleDefines.FirstOrDefault(d => d.SoftwareVersionID == null) ?? define; + if (parameter.SoftwareVersionID != null) + { + define = possibleDefines.FirstOrDefault(d => d.SoftwareVersionID == parameter.SoftwareVersionID) ?? define; + + if (define == null) + define = possibleDefines.MinBy(d => parameter.SoftwareVersionID - d.SoftwareVersionID); + } + } + } + return possibleDefines.MaxBy(d => d.Version); + } + if (parameter.ManufacturerID == 0) + throw new InvalidOperationException($"{parameter.ManufacturerID} of 0 should lead to exact 1 Define"); + + + + throw new DefineNotFoundException($"{parameter}"); + } + + internal static byte[] ParsePayloadToData(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType, DataTreeBranch payload) + { + define.GetCommand(commandType, out Command? _command); + if (_command is not Command command) + throw new InvalidOperationException(); + + if (command.GetIsEmpty()) + return new byte[0]; + + if (payload.Children.SingleOrDefault() is DataTree dataTree && command.SingleField.HasValue) + return command.SingleField.Value.ParsePayloadToData(dataTree); + + if (payload.Children is DataTree[] dataTreeArray && command.ListOfFields.Length != 0) + { + if (dataTreeArray.Length != command.ListOfFields.Length) + throw new IndexOutOfRangeException(); + List data = new List(); + for (int i = 0; i < command.ListOfFields.Length; i++) + data.AddRange(command.ListOfFields[i].ParsePayloadToData(dataTreeArray[i])); + return data.ToArray(); + } + + throw new ArithmeticException(); + } + internal static DataTreeBranch ParseDataToPayload(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType, byte[] data) + { + define.GetCommand(commandType, out Command? _command); + if (_command is not Command command) + throw new InvalidOperationException(); + + if (command.GetIsEmpty()) + return DataTreeBranch.Empty; + + if (command.SingleField.HasValue) + return new DataTreeBranch(define, commandType, command.SingleField.Value.ParseDataToPayload(ref data)); + + if (command.ListOfFields.Length != 0) + { + List tree = new List(); + for (int i = 0; i < command.ListOfFields.Length; i++) + tree.Add(command.ListOfFields[i].ParseDataToPayload(ref data)); + return new DataTreeBranch(define, commandType, tree.ToArray()); + } + + throw new ArithmeticException(); + } + internal static byte[] GetRequestMessageData(ParameterBag parameter, DataTreeBranch payloadData) + { + return ParsePayloadToData(GetDefine(parameter), Command.ECommandDublicte.GetRequest, payloadData); + } + internal static byte[] GetResponseMessageData(ParameterBag parameter, DataTreeBranch payloadData) + { + return ParsePayloadToData(GetDefine(parameter), Command.ECommandDublicte.GetResponse, payloadData); + } + internal static byte[] SetRequestMessageData(ParameterBag parameter, DataTreeBranch payloadData) + { + return ParsePayloadToData(GetDefine(parameter), Command.ECommandDublicte.SetRequest, payloadData); + } + internal static byte[] SetResponseMessageData(ParameterBag parameter, DataTreeBranch payloadData) + { + return ParsePayloadToData(GetDefine(parameter), Command.ECommandDublicte.SetResponse, payloadData); + } + + private static List definedDataTreeObjects; + public static IReadOnlyCollection DefinedDataTreeObjects + { + get + { + fillDefinedDataTreeObjects(); + return definedDataTreeObjects; + } + } + + private static void fillDefinedDataTreeObjects() + { + if (definedDataTreeObjects != null) + return; + + definedDataTreeObjects = new List(); + + definedDataTreeObjects.AddRange(Tools.FindClassesWithAttribute()); + } + + public static Type GetDefinedDataTreeObjectType(MetadataJSONObjectDefine define, Command.ECommandDublicte commandType) + { + return GetDefinedDataTreeObjectType((ERDM_Parameter)define.PID, commandType); + } + public static Type GetDefinedDataTreeObjectType(MetadataJSONObjectDefine define, ERDM_Command command) + { + Command.ECommandDublicte commandType = Tools.ConvertCommandDublicteToCommand(command); + return GetDefinedDataTreeObjectType((ERDM_Parameter)define.PID, commandType); + } + public static Type GetDefinedDataTreeObjectType(ERDM_Parameter parameter, ERDM_Command command) + { + Command.ECommandDublicte commandType = Tools.ConvertCommandDublicteToCommand(command); + return GetDefinedDataTreeObjectType(parameter, commandType); + } + public static Type GetDefinedDataTreeObjectType(ERDM_Parameter parameter, Command.ECommandDublicte commandType) + { + return DefinedDataTreeObjects.Where(t => + { + if (t.GetCustomAttributes().Any(attribute => attribute.Parameter == parameter && attribute.Command == commandType)) + return true; + return false; + }).FirstOrDefault(); + } + } +} diff --git a/RDMSharp/Metadata/MetadataJSONObjectDefine.cs b/RDMSharp/Metadata/MetadataJSONObjectDefine.cs new file mode 100644 index 0000000..a3b52b7 --- /dev/null +++ b/RDMSharp/Metadata/MetadataJSONObjectDefine.cs @@ -0,0 +1,224 @@ +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace RDMSharp.Metadata +{ + public class MetadataJSONObjectDefine + { + [JsonPropertyName("name")] + public string Name { get; } + + [JsonPropertyName("displayName")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? DisplayName { get; } + + [JsonPropertyName("notes")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Notes { get; } + [JsonPropertyName("manufacturer_id")] + public ushort ManufacturerID { get; } + + [JsonPropertyName("device_model_id")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ushort? DeviceModelID { get; } + + [JsonPropertyName("software_version_id")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public uint? SoftwareVersionID { get; } + + [JsonPropertyName("pid")] + public ushort PID { get; } + + [JsonPropertyName("version")] + public ushort Version { get; } + + [JsonPropertyName("get_request_subdevice_range")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(11)] + public SubdevicesForRequests[]? GetRequestSubdeviceRange { get; } + [JsonPropertyName("get_response_subdevice_range")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(13)] + public SubdevicesForResponses[]? GetResponseSubdeviceRange { get; } + [JsonPropertyName("set_request_subdevice_range")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(15)] + public SubdevicesForRequests[]? SetRequestsSubdeviceRange { get; } + [JsonPropertyName("set_response_subdevice_range")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(17)] + public SubdevicesForResponses[]? SetResponseSubdeviceRange { get; } + + [JsonPropertyName("get_request")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(12)] + public Command? GetRequest { get; } + [JsonPropertyName("get_response")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(14)] + public Command? GetResponse { get; } + [JsonPropertyName("set_request")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(16)] + public Command? SetRequest { get; } + [JsonPropertyName("set_response")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyOrder(18)] + public Command? SetResponse { get; } + + [JsonConstructor] + public MetadataJSONObjectDefine( + string name, + string? displayName, + string? notes, + ushort manufacturerID, + ushort? deviceModelID, + uint? softwareVersionID, + ushort pID, + ushort version, + SubdevicesForRequests[]? getRequestSubdeviceRange, + SubdevicesForResponses[]? getResponseSubdeviceRange, + SubdevicesForRequests[]? setRequestsSubdeviceRange, + SubdevicesForResponses[]? setResponseSubdeviceRange, + Command? getRequest, + Command? getResponse, + Command? setRequest, + Command? setResponse) + { + if (getRequest.HasValue ^ getResponse.HasValue) + throw new JsonException($"Both {nameof(getRequest)} & {nameof(getResponse)} and have to be defined in {name}"); + + if (setRequest.HasValue ^ setResponse.HasValue) + throw new JsonException($"Both {nameof(setRequest)} & {nameof(setResponse)} and have to be defined in {name}"); + + Name = name; + DisplayName = displayName; + Notes = notes; + ManufacturerID = manufacturerID; + DeviceModelID = deviceModelID; + SoftwareVersionID = softwareVersionID; + PID = pID; + Version = version; + + GetRequestSubdeviceRange = getRequestSubdeviceRange; + GetResponseSubdeviceRange = getResponseSubdeviceRange; + SetRequestsSubdeviceRange = setRequestsSubdeviceRange; + SetResponseSubdeviceRange = setResponseSubdeviceRange; + + GetRequest = getRequest; + GetResponse = getResponse; + SetRequest = setRequest; + SetResponse = setResponse; + + if (getRequest.HasValue) + GetRequest = setReferenceObjects(getRequest.Value); + if (getResponse.HasValue) + GetResponse = setReferenceObjects(getResponse.Value); + if (setRequest.HasValue) + SetRequest = setReferenceObjects(setRequest.Value); + if (setResponse.HasValue) + SetResponse = setReferenceObjects(setResponse.Value); + + + Command setReferenceObjects(Command command) + { + if (command.SingleField.HasValue) + { + var result= setReferenceObjects(command.SingleField.Value); + if (!result.Equals(command.SingleField.Value)) + return new Command(result); + } + + if (command.ListOfFields != null) + { + List listOfFields = new List(); + foreach (OneOfTypes oneOf in command.ListOfFields) + { + var result = setReferenceObjects(oneOf); + if (!result.Equals(oneOf)) + listOfFields.Add(result); + else + listOfFields.Add(oneOf); + } + if (!listOfFields.SequenceEqual(command.ListOfFields)) + return new Command(listOfFields.ToArray()); + } + + return command; + + OneOfTypes setReferenceObjects(OneOfTypes oneOf) + { + if (!oneOf.ReferenceType.HasValue) + return oneOf; + + ReferenceType reference = oneOf.ReferenceType.Value; + + switch (reference.Command) + { + case Command.ECommandDublicte.GetRequest: + if (!getRequest.HasValue) + throw new JsonException($"The Referenced Command ({reference.Command.ToString()})is not defined"); + reference = new ReferenceType(reference.URI, getRequest.Value.ListOfFields[reference.Pointer].ObjectType); + break; + + case Command.ECommandDublicte.GetResponse: + if (!getResponse.HasValue) + throw new JsonException($"The Referenced Command ({reference.Command.ToString()})is not defined"); + reference = new ReferenceType(reference.URI, getResponse.Value.ListOfFields[reference.Pointer].ObjectType); + break; + + case Command.ECommandDublicte.SetRequest: + if (!setRequest.HasValue) + throw new JsonException($"The Referenced Command ({reference.Command.ToString()})is not defined"); + reference = new ReferenceType(reference.URI, setRequest.Value.ListOfFields[reference.Pointer].ObjectType); + break; + + case Command.ECommandDublicte.SetResponse: + if (!setResponse.HasValue) + throw new JsonException($"The Referenced Command ({reference.Command.ToString()})is not defined"); + reference = new ReferenceType(reference.URI, setResponse.Value.ListOfFields[reference.Pointer].ObjectType); + break; + } + return new OneOfTypes(reference); + } + } + } + + public void GetCommand(Command.ECommandDublicte eCommand,out Command? command) + { + command = null; + switch (eCommand) + { + case Command.ECommandDublicte.GetRequest: + command = GetRequest.Value; + break; + case Command.ECommandDublicte.GetResponse: + command = GetResponse.Value; + break; + case Command.ECommandDublicte.SetRequest: + command = SetRequest.Value; + break; + case Command.ECommandDublicte.SetResponse: + command = SetResponse.Value; + break; + } + if (command.HasValue) + if (command.Value.EnumValue.HasValue) + GetCommand(command.Value.EnumValue.Value, out command); + + } + + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(Notes)) + return $"{ManufacturerID:X4} {PID:X4} {Name} ({Notes})"; + + return $"{ManufacturerID:X4} {PID:X4} {Name}"; + } + } +} diff --git a/RDMSharp/Metadata/MetadataVersion.cs b/RDMSharp/Metadata/MetadataVersion.cs new file mode 100644 index 0000000..1b3d237 --- /dev/null +++ b/RDMSharp/Metadata/MetadataVersion.cs @@ -0,0 +1,73 @@ +using System; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; + +[assembly: InternalsVisibleTo("RDMSharpTests")] + +namespace RDMSharp.Metadata +{ + public readonly struct MetadataVersion + { + public readonly string Version; + public readonly string Path; + public readonly string Name; + public readonly bool IsSchema; + public MetadataVersion(string path) : this(getVersion(path), getName(path), getIsSchema(path), path) + { + } + public MetadataVersion(string version, string name, bool isSchema, string path) + { + Version = version; + Path = path; + Name = name; + IsSchema = isSchema; + } + internal static string getVersion(string path) + { + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentNullException(nameof(path)); + + if (!path.ToLower().EndsWith(".json")) + throw new ArgumentException($"The given Paths should end with .json ({nameof(path)})"); + + string pattern = @"_(\d+)\._(\d+)\._(\d+)"; + var match = Regex.Match(path, pattern); + + if (match.Success) + { + return match.Value.Replace("_", ""); + } + else + throw new FormatException($"Can't extract Version from Path: {path}"); + } + internal static bool getIsSchema(string path) + { + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentNullException(nameof(path)); + + if (!path.ToLower().EndsWith(".json")) + throw new ArgumentException($"The given Paths should end with .json ({nameof(path)})"); + + return path.ToLower().EndsWith("schema.json"); + } + internal static string getName(string path) + { + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentNullException(nameof(path)); + + string pattern = @"[^\.]+\.[json]+$"; + var match = Regex.Match(path, pattern); + + if (match.Success) + { + return match.Value; + } + else + throw new FormatException($"The given Paths should end with .json ({nameof(path)})"); + } + public override string ToString() + { + return $"{Name} [{Version}]"; + } + } +} diff --git a/RDMSharp/Metadata/ParameterBag.cs b/RDMSharp/Metadata/ParameterBag.cs new file mode 100644 index 0000000..c9df038 --- /dev/null +++ b/RDMSharp/Metadata/ParameterBag.cs @@ -0,0 +1,77 @@ +using System; + +namespace RDMSharp.Metadata +{ + internal readonly struct ParameterBag : IEquatable + { + public readonly ERDM_Parameter PID { get; } + public readonly ushort ManufacturerID { get; } + public readonly ushort? DeviceModelID { get; } + public readonly uint? SoftwareVersionID { get; } + public ParameterBag() + { + throw new NotSupportedException("Its not allowed to have an default of this Type"); + } + public ParameterBag(ERDM_Parameter pid, ushort manufacturerID = 0, ushort? deviceModelID = null, uint? softwareVersionID = null) + { + if ((ushort)pid >= 0x8000) + { + if (manufacturerID == 0) + throw new ArgumentNullException($"{nameof(pid)} in range 0x8000 -0xFFFF requires {nameof(manufacturerID)} != 0"); + } + else + { + manufacturerID = 0; + deviceModelID = null; + softwareVersionID = null; + } + + PID = pid; + ManufacturerID = manufacturerID; + DeviceModelID = deviceModelID; + SoftwareVersionID = softwareVersionID; + } + public override string ToString() + { + if (ManufacturerID != 0) + { + if (DeviceModelID != null) + { + if (SoftwareVersionID != null) + return $"{PID} ManufacturerID: {ManufacturerID}, DeviceModelID: {DeviceModelID}, SoftwareVersionID: {SoftwareVersionID}"; + return $"{PID} ManufacturerID: {ManufacturerID}, DeviceModelID: {DeviceModelID}"; + } + return $"{PID} ManufacturerID: {ManufacturerID}"; + } + return $"{PID}"; + } + + public override bool Equals(object obj) + { + return obj is ParameterBag bag && Equals(bag); + } + + public bool Equals(ParameterBag other) + { + return PID == other.PID && + ManufacturerID == other.ManufacturerID && + DeviceModelID == other.DeviceModelID && + SoftwareVersionID == other.SoftwareVersionID; + } + + public override int GetHashCode() + { + return HashCode.Combine(PID, ManufacturerID, DeviceModelID, SoftwareVersionID); + } + + public static bool operator ==(ParameterBag left, ParameterBag right) + { + return left.Equals(right); + } + + public static bool operator !=(ParameterBag left, ParameterBag right) + { + return !(left == right); + } + } +} diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EBatteryExtension.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EBatteryExtension.cs index 4f88650..3d6412b 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EBatteryExtension.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EBatteryExtension.cs @@ -1,5 +1,10 @@ -namespace RDMSharp.ParameterWrapper.SGM -{ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.ParameterWrapper.SGM +{ + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.BATTERY_EXTENSION, Command.ECommandDublicte.GetResponse,"")] + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.BATTERY_EXTENSION, Command.ECommandDublicte.SetRequest,"")] public enum EBatteryExtension : byte { DISABLED = 0, diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimMode.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimMode.cs index 378cea1..91eb8e9 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimMode.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimMode.cs @@ -1,5 +1,10 @@ -namespace RDMSharp.ParameterWrapper.SGM -{ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.ParameterWrapper.SGM +{ + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.DIM_MODE, Command.ECommandDublicte.GetResponse,"")] + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.DIM_MODE, Command.ECommandDublicte.SetRequest,"")] public enum EDimMode : byte { STANDARD = 0, diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimmingCurve.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimmingCurve.cs index 0cbcabc..a164020 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimmingCurve.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EDimmingCurve.cs @@ -1,5 +1,10 @@ -namespace RDMSharp.ParameterWrapper.SGM -{ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.ParameterWrapper.SGM +{ + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.DIMMING_CURVE, Command.ECommandDublicte.GetResponse,"")] + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.DIMMING_CURVE, Command.ECommandDublicte.SetRequest,"")] public enum EDimmingCurve : byte { RAW = 0, diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EFanMode.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EFanMode.cs index c91add8..55837e7 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EFanMode.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EFanMode.cs @@ -1,5 +1,10 @@ -namespace RDMSharp.ParameterWrapper.SGM -{ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.ParameterWrapper.SGM +{ + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.FAN_MODE, Command.ECommandDublicte.GetResponse,"")] + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.FAN_MODE, Command.ECommandDublicte.SetRequest,"")] public enum EFanMode : byte { AUTO = 0, diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EInvertPixelOrder.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EInvertPixelOrder.cs index 8f6ae96..b400d5e 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EInvertPixelOrder.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/EInvertPixelOrder.cs @@ -1,5 +1,10 @@ -namespace RDMSharp.ParameterWrapper.SGM -{ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp.ParameterWrapper.SGM +{ + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.INVERT_PIXEL_ORDER, Command.ECommandDublicte.GetResponse,"")] + [DataTreeEnum(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.INVERT_PIXEL_ORDER, Command.ECommandDublicte.SetRequest,"")] public enum EInvertPixelOrder : byte { STANDARD = 0, diff --git a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/RefreshRate.cs b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/RefreshRate.cs index b28f4ca..a541e9c 100644 --- a/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/RefreshRate.cs +++ b/RDMSharp/ParameterWrapper/Catalogue/Manufacturer/SGM/RefreshRate.cs @@ -1,7 +1,12 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; namespace RDMSharp.ParameterWrapper.SGM -{ +{ + [DataTreeObject(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.REFRESH_RATE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(EManufacturer.SGM_Technology_For_Lighting_SPA, (ERDM_Parameter)(ushort)EParameter.REFRESH_RATE, Command.ECommandDublicte.SetRequest)] + public readonly struct RefreshRate : IEquatable { public const uint FREQUENCY_MULTIPLYER = 197647; diff --git a/RDMSharp/RDM/AbstractSendReceivePipeline.cs b/RDMSharp/RDM/AbstractSendReceivePipeline.cs new file mode 100644 index 0000000..5e02022 --- /dev/null +++ b/RDMSharp/RDM/AbstractSendReceivePipeline.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace RDMSharp.RDM +{ + public abstract class AbstractSendReceivePipeline + { + public abstract Task SendMesage(RDMMessage message); + public abstract Task ReceiveMesage(RDMMessage message); + } +} diff --git a/RDMSharp/RDM/AsyncRDMRequestHelper.cs b/RDMSharp/RDM/AsyncRDMRequestHelper.cs index 9041b17..109da03 100644 --- a/RDMSharp/RDM/AsyncRDMRequestHelper.cs +++ b/RDMSharp/RDM/AsyncRDMRequestHelper.cs @@ -33,7 +33,7 @@ public void Dispose() this.IsDisposing= false; } - public bool ReceiveMethode(RDMMessage rdmMessage) + public bool ReceiveMessage(RDMMessage rdmMessage) { if (this.IsDisposing || this.IsDisposed) return false; @@ -67,7 +67,7 @@ public bool ReceiveMethode(RDMMessage rdmMessage) } - public async Task RequestParameter(RDMMessage requerst) + public async Task RequestMessage(RDMMessage requerst) { try { diff --git a/RDMSharp/RDM/Device/AbstractRDMDevice.cs b/RDMSharp/RDM/Device/AbstractRDMDevice.cs index c2453fc..e5aae1d 100644 --- a/RDMSharp/RDM/Device/AbstractRDMDevice.cs +++ b/RDMSharp/RDM/Device/AbstractRDMDevice.cs @@ -1,10 +1,12 @@ using Microsoft.Extensions.Logging; +using RDMSharp.Metadata; using RDMSharp.ParameterWrapper; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Reflection.Metadata; using System.Threading.Tasks; namespace RDMSharp @@ -14,7 +16,6 @@ public abstract class AbstractRDMDevice : IRDMDevice private static readonly Random random = new Random(); private protected static readonly ILogger Logger = null; private protected static RDMParameterWrapperCatalogueManager pmManager => RDMParameterWrapperCatalogueManager.GetInstance(); - private protected static DeviceInfoParameterWrapper deviceInfoParameterWrapper => (DeviceInfoParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.DEVICE_INFO); private protected static SensorValueParameterWrapper sensorValueParameterWrapper => (SensorValueParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.SENSOR_VALUE); private protected static SlotInfoParameterWrapper slotInfoParameterWrapper => (SlotInfoParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.SLOT_INFO); private protected static DefaultSlotValueParameterWrapper defaultSlotValueParameterWrapper => (DefaultSlotValueParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.DEFAULT_SLOT_VALUE); @@ -26,10 +27,14 @@ public abstract class AbstractRDMDevice : IRDMDevice public event PropertyChangedEventHandler PropertyChanged; public UID UID { get; private set; } + public SubDevice Subdevice { get; private set; } public DateTime LastSeen { get; private set; } public bool Present { get; internal set; } public bool DiscoveryMuted { get; private set; } + private List subDevices; + public IReadOnlyCollection SubDevices { get { return subDevices.AsReadOnly(); } } + public virtual RDMDeviceInfo DeviceInfo { get; private protected set; } private RDMDeviceModel deviceModel; @@ -53,17 +58,73 @@ public abstract class AbstractRDMDevice : IRDMDevice public virtual bool IsGenerated { get; private protected set; } public bool AllDataPulled { get; private set; } - public AbstractRDMDevice(UID uid) + public AbstractRDMDevice(UID uid): this(uid, SubDevice.Root) + { + } + + public AbstractRDMDevice(UID uid, SubDevice subDevice) { - asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMRequestMessage); UID = uid; + Subdevice = subDevice; + subDevices = new List(); + + asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMRequestMessage); + initialize(); } + private async void initialize() { if (!IsGenerated) - await sendRDMRequestMessage(deviceInfoParameterWrapper.BuildGetRequestMessage()); + await requestDeviceInfo(); + } + + private async Task runPeerToPeerProcess(PeerToPeerProcess ptpProcess) + { + await ptpProcess.Run(asyncRDMRequestHelper); + } + + #region Requests + + private async Task requestDeviceInfo() + { + PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, UID, Subdevice, new ParameterBag(ERDM_Parameter.DEVICE_INFO)); + await runPeerToPeerProcess(ptpProcess); + if (ptpProcess.ResponsePayloadObject.ParsedObject is RDMDeviceInfo deviceInfo) + { + DeviceInfo = deviceInfo; + parameterValues.AddOrUpdate(ERDM_Parameter.DEVICE_INFO, deviceInfo, (o, p) => deviceInfo); + await getDeviceModelAndCollectAllParameters(); + } } + private async Task requestSensorValue(byte sensorId) + { + DataTreeBranch dataTreeBranch = new DataTreeBranch(new DataTree("sensor",0, sensorId)); + PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, UID, Subdevice, new ParameterBag(ERDM_Parameter.SENSOR_VALUE), dataTreeBranch); + await runPeerToPeerProcess(ptpProcess); + if (ptpProcess.ResponsePayloadObject.ParsedObject is RDMDeviceInfo deviceInfo) + { + DeviceInfo = deviceInfo; + parameterValues.AddOrUpdate(ERDM_Parameter.DEVICE_INFO, deviceInfo, (o, p) => deviceInfo); + await getDeviceModelAndCollectAllParameters(); + } + } + + #endregion + private async Task getDeviceModelAndCollectAllParameters() + { + if (deviceModel != null) + return; + deviceModel = RDMDeviceModel.getDeviceModel(UID, Subdevice, DeviceInfo, new Func(SendRDMMessage)); + if (!deviceModel.IsInitialized) + { + deviceModel.Initialized += DeviceModel_Initialized; + await deviceModel.Initialize(); + } + else + await collectAllParameters(); + } + private protected void SetGeneratedParameterValue(ERDM_Parameter parameter, object value) { @@ -169,7 +230,7 @@ protected async Task ReceiveRDMMessage(RDMMessage rdmMessage) LastSeen = DateTime.UtcNow; - if (asyncRDMRequestHelper.ReceiveMethode(rdmMessage)) + if (asyncRDMRequestHelper.ReceiveMessage(rdmMessage)) return; if ((rdmMessage.NackReason?.Length ?? 0) != 0) @@ -183,7 +244,7 @@ protected async Task ReceiveRDMMessage(RDMMessage rdmMessage) } private async Task requestParameter(RDMMessage rdmMessage) { - return await asyncRDMRequestHelper.RequestParameter(rdmMessage); + return await asyncRDMRequestHelper.RequestMessage(rdmMessage); } private async void DeviceModel_Initialized(object sender, EventArgs e) { @@ -551,17 +612,7 @@ private async Task processResponseMessage(RDMMessage rdmMessage) DeviceInfo = deviceInfo; - if (deviceModel != null) - break; - - deviceModel = RDMDeviceModel.getDeviceModel(UID, deviceInfo, new Func(SendRDMMessage)); - if (!deviceModel.IsInitialized) - { - deviceModel.Initialized += DeviceModel_Initialized; - await deviceModel.Initialize(); - } - else - await collectAllParameters(); + await getDeviceModelAndCollectAllParameters(); break; diff --git a/RDMSharp/RDM/Device/ParameterDataCacheBag.cs b/RDMSharp/RDM/Device/ParameterDataCacheBag.cs new file mode 100644 index 0000000..75d198e --- /dev/null +++ b/RDMSharp/RDM/Device/ParameterDataCacheBag.cs @@ -0,0 +1,26 @@ +namespace RDMSharp +{ + public readonly struct ParameterDataCacheBag + { + public readonly ERDM_Parameter Parameter; + public readonly object Index; + + public ParameterDataCacheBag(ERDM_Parameter parameter, object index) + { + Parameter = parameter; + Index = index; + } + public ParameterDataCacheBag(ERDM_Parameter parameter) + { + Parameter = parameter; + } + + public override string ToString() + { + if (Index == null) + return $"{Parameter}"; + else + return $"{Parameter}: {Index}"; + } + } +} \ No newline at end of file diff --git a/RDMSharp/RDM/Device/RDMDeviceModel.cs b/RDMSharp/RDM/Device/RDMDeviceModel.cs index 3a73af9..e503419 100644 --- a/RDMSharp/RDM/Device/RDMDeviceModel.cs +++ b/RDMSharp/RDM/Device/RDMDeviceModel.cs @@ -1,10 +1,13 @@ -using RDMSharp.ParameterWrapper; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.ParameterWrapper; using RDMSharp.ParameterWrapper.Generic; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Reflection; using System.Threading.Tasks; namespace RDMSharp @@ -13,38 +16,35 @@ public sealed class RDMDeviceModel : IRDMDeviceModel { private static ConcurrentDictionary knownDeviceModels; public static IReadOnlyCollection KnownDeviceModels => knownDeviceModels.Values.ToList(); - internal static RDMDeviceModel getDeviceModel(UID uid, RDMDeviceInfo deviceInfo, Func sendRdmFunktion) + internal static RDMDeviceModel getDeviceModel(UID uid, SubDevice subDevice, RDMDeviceInfo deviceInfo, Func sendRdmFunktion) { knownDeviceModels ??= new ConcurrentDictionary(); var kdm = knownDeviceModels.Values.FirstOrDefault(dm => dm.IsModelOf(uid, deviceInfo)); if (kdm == null) { - kdm = new RDMDeviceModel(uid, deviceInfo, sendRdmFunktion); + kdm = new RDMDeviceModel(uid, subDevice, deviceInfo, sendRdmFunktion); knownDeviceModels.TryAdd(kdm.GetHashCode(), kdm); } return kdm; - } - - private static readonly Random random = new Random(); - private static RDMParameterWrapperCatalogueManager pmManager => RDMParameterWrapperCatalogueManager.GetInstance(); - private static DeviceInfoParameterWrapper deviceInfoParameterWrapper => (DeviceInfoParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.DEVICE_INFO); - private static SupportedParametersParameterWrapper supportedParametersParameterWrapper => (SupportedParametersParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.SUPPORTED_PARAMETERS); - private static SensorDefinitionParameterWrapper sensorDefinitionParameterWrapper => (SensorDefinitionParameterWrapper)pmManager.GetRDMParameterWrapperByID(ERDM_Parameter.SENSOR_DEFINITION); + } public ushort ManufacturerID { get; private set; } public EManufacturer Manufacturer { get; private set; } - public UID CurrentUsedUID { get; private set; } + public UID CurrentUsedUID { get; private set; } + public SubDevice CurrentUsedSubDevice { get; private set; } public event EventHandler Initialized; public bool IsInitialized { get; private set; } = false; - private readonly AsyncRDMRequestHelper asyncRDMRequestHelper; + private AsyncRDMRequestHelper asyncRDMRequestHelper; private readonly ConcurrentDictionary manufacturerParameter = new ConcurrentDictionary(); + private ConcurrentDictionary parameterValuesDataTreeBranch = new ConcurrentDictionary(); + private ConcurrentDictionary parameterValuesDependeciePropertyBag = new ConcurrentDictionary(); private ConcurrentDictionary parameterValues = new ConcurrentDictionary(); public IReadOnlyDictionary ParameterValues @@ -60,7 +60,10 @@ private set if (this.DeviceInfo == value) return; - this.parameterValues[ERDM_Parameter.DEVICE_INFO] = value; + this.parameterValues[ERDM_Parameter.DEVICE_INFO] = value; + var dataTreeBranch = DataTreeBranch.FromObject(value, ERDM_Command.GET_COMMAND_RESPONSE, ERDM_Parameter.DEVICE_INFO); + updateParameterValuesDependeciePropertyBag(ERDM_Parameter.DEVICE_INFO, dataTreeBranch); + parameterValuesDataTreeBranch[new ParameterDataCacheBag(ERDM_Parameter.DEVICE_INFO)] = dataTreeBranch; PropertyChanged?.InvokeFailSafe(this, new PropertyChangedEventArgs(nameof(DeviceInfo))); } } @@ -68,20 +71,20 @@ private set private ConcurrentDictionary supportedParameters = new ConcurrentDictionary(); public IReadOnlyCollection SupportedParameters { - get { return this.supportedParameters.Where(sp => sp.Value).Select(sp => sp.Key).Where(p => ((ushort)p > 0x000F)).ToArray().AsReadOnly(); } + get { return this.supportedParameters.Where(sp => sp.Value).Select(sp => sp.Key).Where(p => ((ushort)p > 0x000F)).OrderBy(p => p).ToArray().AsReadOnly(); } } public IReadOnlyCollection SupportedBlueprintParameters { - get { return this.SupportedParameters.Where(p => pmManager.GetRDMParameterWrapperByID(p) is IRDMBlueprintParameterWrapper).ToArray().AsReadOnly(); } + get { return this.SupportedParameters.Intersect(Constants.BLUEPRINT_MODEL_PARAMETERS).OrderBy(p => p).ToList().AsReadOnly(); } } public IReadOnlyCollection SupportedNonBlueprintParameters { - get { return this.SupportedParameters.Where(p => pmManager.GetRDMParameterWrapperByID(p) is not IRDMBlueprintParameterWrapper).ToArray().AsReadOnly(); } + get { return this.SupportedParameters.Except(SupportedBlueprintParameters).OrderBy(p => p).ToList().AsReadOnly(); } } public IReadOnlyCollection KnownNotSupportedParameters { - get { return this.supportedParameters.Where(sp => !sp.Value).Select(sp => sp.Key).ToArray().AsReadOnly(); } + get { return this.supportedParameters.Where(sp => !sp.Value).Select(sp => sp.Key).OrderBy(p => p).ToArray().AsReadOnly(); } } @@ -92,124 +95,141 @@ public IReadOnlyCollection KnownNotSupportedParameters public event PropertyChangedEventHandler PropertyChanged; private readonly Func sendRdmFunktion; - internal RDMDeviceModel(UID uid, RDMDeviceInfo deviceInfo, Func sendRdmFunktion) + internal RDMDeviceModel(UID uid, SubDevice sudevice, RDMDeviceInfo deviceInfo, Func sendRdmFunktion) { this.sendRdmFunktion = sendRdmFunktion; DeviceInfo = deviceInfo; - this.CurrentUsedUID = uid; + CurrentUsedUID = uid; + CurrentUsedSubDevice = sudevice; ManufacturerID = uid.ManufacturerID; Manufacturer = (EManufacturer)uid.ManufacturerID; - - asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMMessage); } internal async Task Initialize() { if (IsInitialized) return; - await processMessage(await requestParameter(supportedParametersParameterWrapper.BuildGetRequestMessage())); - - var sp = this.SupportedParameters.ToArray(); - foreach (ERDM_Parameter parameter in sp) - { - var pw = pmManager.GetRDMParameterWrapperByID(parameter); + asyncRDMRequestHelper = new AsyncRDMRequestHelper(sendRDMMessage); - switch (pw) - { - case ParameterDescriptionParameterWrapper parameterDescription: - foreach (ERDM_Parameter p in this.SupportedParameters.Where(p => !ERDM_Parameter.IsDefined(typeof(ERDM_Parameter), p))) - await processMessage(await requestParameter((pw as ParameterDescriptionParameterWrapper).BuildGetRequestMessage(p))); - break; - case SupportedParametersParameterWrapper supportedParameters: - break; - } + await requestSupportedParameters(); + await requestBlueprintParameters(); - //if (parameter == ERDM_Parameter.SENSOR_DEFINITION) - //{ - // await this.RequestSensorDefinitions(uid); - // continue; - //} + asyncRDMRequestHelper.Dispose(); + asyncRDMRequestHelper = null; - if (pw is not IRDMBlueprintParameterWrapper) - continue; + IsInitialized = true; + Initialized?.Invoke(this, EventArgs.Empty); + } - RDMMessage request = null; - if (pw is IRDMBlueprintDescriptionListParameterWrapper blueprintDL) - { - foreach (IRDMParameterWrapper _pm in blueprintDL.DescriptiveParameters.Select(pid => pmManager.GetRDMParameterWrapperByID(pid))) - await doCurrentWrapper(_pm); - //if (blueprintDL.DescriptiveParameters?.Contains(blueprintDL.ValueParameterID) == false) - // await doCurrentWrapper(pmManager.GetRDMParameterWrapperByID(blueprintDL.ValueParameterID)); - await doCurrentWrapper(pw); - } - else - await doCurrentWrapper(pw); + private async Task runPeerToPeerProcess(PeerToPeerProcess ptpProcess) + { + await ptpProcess?.Run(asyncRDMRequestHelper); + } - async Task doCurrentWrapper(IRDMParameterWrapper wrapper) - { - if (this.parameterValues.ContainsKey(wrapper.Parameter)) - return; - - switch (wrapper) - { - case IRDMGetParameterWrapperWithEmptyGetRequest emptyGet: - request = emptyGet.BuildGetRequestMessage(); - if (request != null) - await processMessage(await requestParameter(request)); - return; - case IRDMGetParameterWrapperRequestRanged getParameter: - await doRange(getParameter); - return; + private void updateParameterValuesDependeciePropertyBag(ERDM_Parameter parameter, DataTreeBranch dataTreeBranch) + { + object obj = dataTreeBranch.ParsedObject; + if (obj == null) + return; - //case IRDMGetParameterWrapperRequestContravariance getContravarianceByte: - // doRange(getContravarianceByte); - // return; + foreach (var p in obj.GetType().GetProperties().Where(p => p.GetCustomAttributes().Any()).ToList()) + { + object value = p.GetValue(obj); + foreach (var item in p.GetCustomAttributes()) + parameterValuesDependeciePropertyBag.AddOrUpdate(item.Bag, value, (o1, o2) => value); + } + } - //case IRDMGetParameterWrapperRequestContravariance getContravarianceObject: - // break; - //case IRDMGetParameterWrapperRequestContravariance getContravarianceObject: - // break; + #region Requests + private async Task requestSupportedParameters() + { + ParameterBag parameterBag = new ParameterBag(ERDM_Parameter.SUPPORTED_PARAMETERS); + PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, CurrentUsedUID, CurrentUsedSubDevice, parameterBag); + await runPeerToPeerProcess(ptpProcess); - default: - break; - } + if (!ptpProcess.ResponsePayloadObject.IsUnset) + parameterValuesDataTreeBranch.AddOrUpdate(new ParameterDataCacheBag(parameterBag.PID), ptpProcess.ResponsePayloadObject, (o1, o2) => ptpProcess.ResponsePayloadObject); + if (ptpProcess.ResponsePayloadObject.ParsedObject is ERDM_Parameter[] parameters) + { + foreach (var para in parameters) + { + if (!this.supportedParameters.TryGetValue(para, out _)) + supportedParameters.TryAdd(para, true); + } + } + } - if (request == null) - return; + private async Task requestBlueprintParameters() + { + foreach (ERDM_Parameter parameter in this.SupportedBlueprintParameters) + { + ParameterBag parameterBag = new ParameterBag(parameter, ManufacturerID, DeviceInfo.DeviceModelId, DeviceInfo.SoftwareVersionId); + var define = MetadataFactory.GetDefine(parameterBag); + if (define.GetRequest.HasValue) + { + if (define.GetRequest.Value.GetIsEmpty()) + await requestParameterWithEmptyPayload(parameterBag, define); + else + await requestParameterWithPayload(parameterBag, define); + } + } + } + private async Task requestParameterWithEmptyPayload(ParameterBag parameterBag, MetadataJSONObjectDefine define) + { + PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, CurrentUsedUID, CurrentUsedSubDevice, parameterBag); + await runPeerToPeerProcess(ptpProcess); + if (!ptpProcess.ResponsePayloadObject.IsUnset) + { + updateParameterValuesDependeciePropertyBag(parameterBag.PID, ptpProcess.ResponsePayloadObject); + parameterValuesDataTreeBranch.AddOrUpdate(new ParameterDataCacheBag(parameterBag.PID), ptpProcess.ResponsePayloadObject, (o1, o2) => ptpProcess.ResponsePayloadObject); + object valueToStore = ptpProcess.ResponsePayloadObject.ParsedObject ?? ptpProcess.ResponsePayloadObject; + this.parameterValues.AddOrUpdate(parameterBag.PID, valueToStore, (o1, o2) => valueToStore); + } + } + private async Task requestParameterWithPayload(ParameterBag parameterBag, MetadataJSONObjectDefine define) + { + var req = define.GetRequest.Value.GetRequiredProperties(); + if (req.Length == 1 && req[0] is IIntegerType intType) + { + try + { + string name = intType.Name; + IComparable dependecyValue = (IComparable)parameterValuesDependeciePropertyBag.FirstOrDefault(bag => bag.Key.Parameter == parameterBag.PID && bag.Key.Command == Metadata.JSON.Command.ECommandDublicte.GetRequest && string.Equals(bag.Key.Name, name)).Value; - await processMessage(await requestParameter(request)); - async Task doRange(IRDMGetParameterWrapperRequestRanged getParameterWrapperRequest) + object i = intType.GetMinimum(); + object max = intType.GetMaximum(); + object count = Convert.ChangeType(0, i.GetType()); + while (dependecyValue.CompareTo(count) > 0) { - ERDM_Parameter descriptive; - object dVal = null; - IRequestRange range = null; - if (getParameterWrapperRequest is IRDMBlueprintDescriptionListParameterWrapper blueprintDL) - { - descriptive = blueprintDL.DescriptiveParameters.FirstOrDefault(); - if (descriptive != default) - this.parameterValues.TryGetValue(descriptive, out dVal); - } - if (dVal == null) - return; - range = getParameterWrapperRequest.GetRequestRange(dVal); - if (range == null) + if (!intType.IsInRange(i)) + continue; + + if (((IComparable)max).CompareTo(i) == -1) return; - foreach (var r in range.ToEnumerator()) + + DataTreeBranch dataTreeBranch = new DataTreeBranch(new DataTree(name, 0, i)); + PeerToPeerProcess ptpProcess = new PeerToPeerProcess(ERDM_Command.GET_COMMAND, CurrentUsedUID, CurrentUsedSubDevice, parameterBag, dataTreeBranch); + await runPeerToPeerProcess(ptpProcess); + if (!ptpProcess.ResponsePayloadObject.IsUnset) { - request = getParameterWrapperRequest.BuildGetRequestMessage(r); - if (request != null) - await processMessage(await requestParameter(request)); + parameterValuesDataTreeBranch.AddOrUpdate(new ParameterDataCacheBag(parameterBag.PID, i), ptpProcess.ResponsePayloadObject, (o1, o2) => ptpProcess.ResponsePayloadObject); } + i = intType.IncrementJumpRange(i); + count = intType.Increment(count); } } + catch(Exception e) + { + + } } - IsInitialized = true; - Initialized?.Invoke(this, EventArgs.Empty); } + #endregion + private async Task sendRDMMessage(RDMMessage rdmMessage) { @@ -225,125 +245,7 @@ internal async Task ReceiveRDMMessage(RDMMessage rdmMessage) if (!rdmMessage.Command.HasFlag(ERDM_Command.RESPONSE)) return; - if (asyncRDMRequestHelper.ReceiveMethode(rdmMessage)) - return; - - await processMessage(rdmMessage); - } - - private async Task requestParameter(RDMMessage rdmMessage) - { - return await asyncRDMRequestHelper.RequestParameter(rdmMessage); - } - - private async Task processMessage(RequestResult result) - { - if (IsInitialized) - return; - - if (result.Success) - await processMessage(result.Response); - else if (result.Cancel) - return; - else - { - await Task.Delay(TimeSpan.FromTicks(random.Next(4500, 5500))); - await processMessage(await requestParameter(result.Request)); - } - } - private async Task processMessage(RDMMessage rdmMessage) - { - if (IsInitialized) - return; - - var pw = pmManager.GetRDMParameterWrapperByID(rdmMessage.Parameter); - switch (pw) - { - case SupportedParametersParameterWrapper _supportedParameters: - if (rdmMessage.Value is not ERDM_Parameter[] parameters) - break; - - foreach (var para in parameters) - { - if (!this.supportedParameters.TryGetValue(para, out _)) - supportedParameters.TryAdd(para, true); - } - break; - - case ParameterDescriptionParameterWrapper _parameterDescription when rdmMessage.Value is RDMParameterDescription pd: - if (manufacturerParameter.ContainsKey(pd.ParameterId)) - break; - switch (pd.DataType) - { - case ERDM_DataType.ASCII: - manufacturerParameter.TryAdd(pd.ParameterId, new ASCIIParameterWrapper(pd)); - break; - case ERDM_DataType.SIGNED_BYTE: - manufacturerParameter.TryAdd(pd.ParameterId, new SignedByteParameterWrapper(pd)); - break; - case ERDM_DataType.UNSIGNED_BYTE: - manufacturerParameter.TryAdd(pd.ParameterId, new UnsignedByteParameterWrapper(pd)); - break; - case ERDM_DataType.SIGNED_WORD: - manufacturerParameter.TryAdd(pd.ParameterId, new SignedWordParameterWrapper(pd)); - break; - case ERDM_DataType.UNSIGNED_WORD: - manufacturerParameter.TryAdd(pd.ParameterId, new UnsignedWordParameterWrapper(pd)); - break; - case ERDM_DataType.SIGNED_DWORD: - manufacturerParameter.TryAdd(pd.ParameterId, new SignedDWordParameterWrapper(pd)); - break; - case ERDM_DataType.UNSIGNED_DWORD: - manufacturerParameter.TryAdd(pd.ParameterId, new UnsignedDWordParameterWrapper(pd)); - break; - - case ERDM_DataType.BIT_FIELD: - default: - manufacturerParameter.TryAdd(pd.ParameterId, new NotDefinedParameterWrapper(pd)); - break; - - } - break; - - case IRDMBlueprintDescriptionListParameterWrapper blueprintDL: - ConcurrentDictionary list = null; - if (parameterValues.TryGetValue(rdmMessage.Parameter, out object value)) - list = value as ConcurrentDictionary; - - if (list == null) - parameterValues[rdmMessage.Parameter] = list = new ConcurrentDictionary(); - - if (list == null) - return; - - if (rdmMessage.Value == null) - return; - - if (rdmMessage.Value is IRDMPayloadObjectIndex indexObject) - list.AddOrUpdate(indexObject.Index, rdmMessage.Value, (o, p) => rdmMessage.Value); - - break; - case IRDMBlueprintParameterWrapper blueprint: - parameterValues[rdmMessage.Parameter] = rdmMessage.Value; - break; - default: - if (rdmMessage.Value is IRDMPayloadObjectOneOf oneOf) - { - var bdl = pmManager.ParameterWrappers.OfType().FirstOrDefault(p => p.ValueParameterID == rdmMessage.Parameter); - switch (bdl) - { - case IRDMGetParameterWrapperRequest @byte: - for (byte b = (byte)oneOf.MinIndex; b < (byte)oneOf.Count + (byte)oneOf.MinIndex; b++) - await processMessage(await requestParameter(@byte.BuildGetRequestMessage(b))); - break; - case IRDMGetParameterWrapperRequest @ushort: - for (ushort u = (ushort)oneOf.MinIndex; u < (ushort)oneOf.Count + (ushort)oneOf.MinIndex; u++) - await processMessage(await requestParameter(@ushort.BuildGetRequestMessage(u))); - break; - } - } - break; - } + asyncRDMRequestHelper?.ReceiveMessage(rdmMessage); } public bool IsModelOf(UID uid, RDMDeviceInfo other) diff --git a/RDMSharp/RDM/Discovery/AbstractDiscoveryTool.cs b/RDMSharp/RDM/Discovery/AbstractDiscoveryTool.cs index 8c18351..826bdee 100644 --- a/RDMSharp/RDM/Discovery/AbstractDiscoveryTool.cs +++ b/RDMSharp/RDM/Discovery/AbstractDiscoveryTool.cs @@ -34,7 +34,7 @@ public AbstractDiscoveryTool() protected void ReceiveRDMMessage(RDMMessage rdmMessage) { - asyncRDMRequestHelper.ReceiveMethode(rdmMessage); + asyncRDMRequestHelper.ReceiveMessage(rdmMessage); } public async Task> PerformDiscovery(IProgress progress = null, bool full = true) @@ -99,7 +99,7 @@ private async Task DiscoverDevicesBinarySearch(UID uidStart, UID uidEnd, RDMDisc ParameterData = new DiscUniqueBranchRequest(uidStart, uidEnd).ToPayloadData() }; context.IncreaseMessageCounter(); - var res = await asyncRDMRequestHelper.RequestParameter(m); + var res = await asyncRDMRequestHelper.RequestMessage(m); if (res.Success) { success = res.Success; @@ -202,7 +202,7 @@ private async Task DiscoverDevicesBinarySearch(UID uidStart, UID uidEnd, RDMDisc Parameter = ERDM_Parameter.DISC_MUTE, DestUID = uid }; - var res = await asyncRDMRequestHelper.RequestParameter(n); + var res = await asyncRDMRequestHelper.RequestMessage(n); if (res.Success) { muted = res.Success; diff --git a/RDMSharp/RDM/Enum/ERDM_BrokerStatus.cs b/RDMSharp/RDM/Enum/ERDM_BrokerStatus.cs index 26b33f8..97d80a8 100644 --- a/RDMSharp/RDM/Enum/ERDM_BrokerStatus.cs +++ b/RDMSharp/RDM/Enum/ERDM_BrokerStatus.cs @@ -1,5 +1,9 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.BROKER_STATUS, Command.ECommandDublicte.SetRequest,"")] public enum ERDM_BrokerStatus : byte { DISABLED = 0x00, diff --git a/RDMSharp/RDM/Enum/ERDM_DisplayInvert.cs b/RDMSharp/RDM/Enum/ERDM_DisplayInvert.cs index 2a58318..c99ab2b 100644 --- a/RDMSharp/RDM/Enum/ERDM_DisplayInvert.cs +++ b/RDMSharp/RDM/Enum/ERDM_DisplayInvert.cs @@ -1,5 +1,10 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.DISPLAY_INVERT, Command.ECommandDublicte.GetResponse, "setting")] + [DataTreeEnum(ERDM_Parameter.DISPLAY_INVERT, Command.ECommandDublicte.SetRequest, "setting")] public enum ERDM_DisplayInvert : byte { OFF = 0x00, diff --git a/RDMSharp/RDM/Enum/ERDM_IdentifyMode.cs b/RDMSharp/RDM/Enum/ERDM_IdentifyMode.cs index 38ba3f8..7b5ff3b 100644 --- a/RDMSharp/RDM/Enum/ERDM_IdentifyMode.cs +++ b/RDMSharp/RDM/Enum/ERDM_IdentifyMode.cs @@ -1,6 +1,11 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { //E1.37-1 + [DataTreeEnum(ERDM_Parameter.IDENTIFY_MODE, Command.ECommandDublicte.GetResponse, "mode")] + [DataTreeEnum(ERDM_Parameter.IDENTIFY_MODE, Command.ECommandDublicte.SetRequest, "mode")] public enum ERDM_IdentifyMode : byte { QUIET = 0x00, diff --git a/RDMSharp/RDM/Enum/ERDM_LampMode.cs b/RDMSharp/RDM/Enum/ERDM_LampMode.cs index e4a9157..845705e 100644 --- a/RDMSharp/RDM/Enum/ERDM_LampMode.cs +++ b/RDMSharp/RDM/Enum/ERDM_LampMode.cs @@ -1,16 +1,19 @@ -using System.ComponentModel; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.ComponentModel; -namespace RDMSharp +namespace RDMSharp; + +[DataTreeEnum(ERDM_Parameter.LAMP_ON_MODE, Command.ECommandDublicte.GetResponse, "mode")] +[DataTreeEnum(ERDM_Parameter.LAMP_ON_MODE, Command.ECommandDublicte.SetRequest, "mode")] +public enum ERDM_LampMode : byte { - public enum ERDM_LampMode : byte - { - [Description("Lamp Stays off until directly instructed to Strike.")] - ON_MODE_OFF = 0x00, - [Description("Lamp Strikes upon receiving a DMX512 signal.")] - ON_MODE_DMX = 0x01, - [Description("Lamp Strikes automatically at Power-up.")] - ON_MODE_ON = 0x02, - [Description("Lamp Strikes after Calibration or Homing procedure.")] - ON_MODE_AFTER_CAL = 0x03, - } -} + [Description("Lamp Stays off until directly instructed to Strike.")] + ON_MODE_OFF = 0x00, + [Description("Lamp Strikes upon receiving a DMX512 signal.")] + ON_MODE_DMX = 0x01, + [Description("Lamp Strikes automatically at Power-up.")] + ON_MODE_ON = 0x02, + [Description("Lamp Strikes after Calibration or Homing procedure.")] + ON_MODE_AFTER_CAL = 0x03, +} \ No newline at end of file diff --git a/RDMSharp/RDM/Enum/ERDM_LampState.cs b/RDMSharp/RDM/Enum/ERDM_LampState.cs index c26ca8c..13553df 100644 --- a/RDMSharp/RDM/Enum/ERDM_LampState.cs +++ b/RDMSharp/RDM/Enum/ERDM_LampState.cs @@ -1,7 +1,11 @@ -using System.ComponentModel; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.ComponentModel; namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.LAMP_STATE, Command.ECommandDublicte.GetResponse, "state")] + [DataTreeEnum(ERDM_Parameter.LAMP_STATE, Command.ECommandDublicte.SetRequest, "state")] public enum ERDM_LampState : byte { [Description("Off")] diff --git a/RDMSharp/RDM/Enum/ERDM_MergeMode.cs b/RDMSharp/RDM/Enum/ERDM_MergeMode.cs index 940bd48..55bce42 100644 --- a/RDMSharp/RDM/Enum/ERDM_MergeMode.cs +++ b/RDMSharp/RDM/Enum/ERDM_MergeMode.cs @@ -1,5 +1,10 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.PRESET_MERGEMODE, Command.ECommandDublicte.GetResponse, "mode")] + [DataTreeEnum(ERDM_Parameter.PRESET_MERGEMODE, Command.ECommandDublicte.SetRequest, "mode")] public enum ERDM_MergeMode : byte { DEFAULT = 0x00, diff --git a/RDMSharp/RDM/Enum/ERDM_Parameter.cs b/RDMSharp/RDM/Enum/ERDM_Parameter.cs index 5cd25dd..8034c98 100644 --- a/RDMSharp/RDM/Enum/ERDM_Parameter.cs +++ b/RDMSharp/RDM/Enum/ERDM_Parameter.cs @@ -1,8 +1,15 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { /// /// https://www.rdmprotocol.org/rdm/developers/developer-resources/ - /// + /// + [DataTreeEnum(ERDM_Parameter.SUPPORTED_PARAMETERS, Command.ECommandDublicte.GetResponse, "pid", true, "pids")] + [DataTreeEnum(ERDM_Parameter.PARAMETER_DESCRIPTION, Command.ECommandDublicte.GetRequest, "pid")] + [DataTreeEnum(ERDM_Parameter.METADATA_JSON, Command.ECommandDublicte.GetRequest, "pid")] + [DataTreeEnum(ERDM_Parameter.METADATA_PARAMETER_VERSION, Command.ECommandDublicte.GetRequest, "pid")] public enum ERDM_Parameter : ushort { NONE = 0x0000, diff --git a/RDMSharp/RDM/Enum/ERDM_PowerState.cs b/RDMSharp/RDM/Enum/ERDM_PowerState.cs index ab97ecf..df40f43 100644 --- a/RDMSharp/RDM/Enum/ERDM_PowerState.cs +++ b/RDMSharp/RDM/Enum/ERDM_PowerState.cs @@ -1,5 +1,10 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.POWER_STATE, Command.ECommandDublicte.GetResponse, "state")] + [DataTreeEnum(ERDM_Parameter.POWER_STATE, Command.ECommandDublicte.SetRequest, "state")] public enum ERDM_PowerState : byte { FULL_OFF = 0x00, diff --git a/RDMSharp/RDM/Enum/ERDM_ProductDetail.cs b/RDMSharp/RDM/Enum/ERDM_ProductDetail.cs index 57c1be6..c351c53 100644 --- a/RDMSharp/RDM/Enum/ERDM_ProductDetail.cs +++ b/RDMSharp/RDM/Enum/ERDM_ProductDetail.cs @@ -1,5 +1,9 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.PRODUCT_DETAIL_ID_LIST, Command.ECommandDublicte.GetResponse, "product_detail_id", true, "product_detail_ids")] public enum ERDM_ProductDetail : ushort { NONE = 0x0000, diff --git a/RDMSharp/RDM/Enum/ERDM_ResetType.cs b/RDMSharp/RDM/Enum/ERDM_ResetType.cs index 1e74b99..ce8422a 100644 --- a/RDMSharp/RDM/Enum/ERDM_ResetType.cs +++ b/RDMSharp/RDM/Enum/ERDM_ResetType.cs @@ -1,5 +1,9 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.RESET_DEVICE, Command.ECommandDublicte.SetRequest, "state")] public enum ERDM_ResetType : byte { Warm = 0x01, diff --git a/RDMSharp/RDM/Enum/ERDM_ShippingLockState.cs b/RDMSharp/RDM/Enum/ERDM_ShippingLockState.cs index d13a6c0..cfe0d5c 100644 --- a/RDMSharp/RDM/Enum/ERDM_ShippingLockState.cs +++ b/RDMSharp/RDM/Enum/ERDM_ShippingLockState.cs @@ -1,6 +1,11 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { //E1.37-5 + [DataTreeEnum(ERDM_Parameter.SHIPPING_LOCK, Command.ECommandDublicte.GetResponse, "lock_state")] + [DataTreeEnum(ERDM_Parameter.SHIPPING_LOCK, Command.ECommandDublicte.SetRequest, "lock_state")] public enum ERDM_ShippingLockState : byte { /// diff --git a/RDMSharp/RDM/Enum/ERDM_Status.cs b/RDMSharp/RDM/Enum/ERDM_Status.cs index 0607316..e2e286b 100644 --- a/RDMSharp/RDM/Enum/ERDM_Status.cs +++ b/RDMSharp/RDM/Enum/ERDM_Status.cs @@ -1,5 +1,11 @@ -namespace RDMSharp +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; + +namespace RDMSharp { + [DataTreeEnum(ERDM_Parameter.STATUS_MESSAGES, Command.ECommandDublicte.GetRequest, "status_type")] + [DataTreeEnum(ERDM_Parameter.SUB_DEVICE_STATUS_REPORT_THRESHOLD, Command.ECommandDublicte.GetResponse, "status_type")] + [DataTreeEnum(ERDM_Parameter.SUB_DEVICE_STATUS_REPORT_THRESHOLD, Command.ECommandDublicte.SetRequest, "status_type")] public enum ERDM_Status : byte { NONE = 0x00, diff --git a/RDMSharp/RDM/PDL.cs b/RDMSharp/RDM/PDL.cs new file mode 100644 index 0000000..e213398 --- /dev/null +++ b/RDMSharp/RDM/PDL.cs @@ -0,0 +1,70 @@ +using System; +using System.Linq; + +namespace RDMSharp.RDM +{ + public readonly struct PDL + { + public const uint MAX_LENGTH = 0xE7 * 0xFF; + public readonly uint? Value { get; } + public readonly uint? MinLength { get; } + public readonly uint? MaxLength { get; } + + public PDL() + { + Value = 0; + } + public PDL(uint value) : this() + { + if (value >= MAX_LENGTH) + throw new ArgumentOutOfRangeException($"The Parameter {nameof(value)} should be in range of 0 - {MAX_LENGTH}"); + + Value = value; + } + public PDL(uint minLength, uint maxLength) : this() + { + if (minLength > MAX_LENGTH) + throw new ArgumentOutOfRangeException($"The Parameter {nameof(minLength)} should be in range of 0 - {MAX_LENGTH}"); + if (maxLength > MAX_LENGTH) + throw new ArgumentOutOfRangeException($"The Parameter {nameof(maxLength)} should be in range of 0 - {MAX_LENGTH}"); + + if (minLength == maxLength) + Value = minLength; + else + { + MinLength = Math.Min(minLength, maxLength); + MaxLength = Math.Max(minLength, maxLength); + Value = null; + } + } + public PDL(params PDL[] pdls) + { + uint value = 0, min = 0, max = 0; + + foreach (PDL pdl in pdls.Where(p => p.Value.HasValue)) + value += pdl.Value.Value; + + foreach (PDL pdl in pdls.Where(p => p.MinLength.HasValue)) + min += pdl.MinLength.Value; + foreach (PDL pdl in pdls.Where(p => p.MaxLength.HasValue)) + max += pdl.MaxLength.Value; + + if (min == max) + Value = Math.Min(MAX_LENGTH, value + min); + else + { + MinLength = Math.Min(MAX_LENGTH, value + Math.Min(min, max)); + MaxLength = Math.Min(MAX_LENGTH, value + Math.Max(min, max)); + Value = null; + } + } + + public bool IsValid(int length) + { + if (Value.HasValue) + return Value == length; + + return MinLength <= length && length <= MaxLength; + } + } +} diff --git a/RDMSharp/RDM/PayloadObject/AcknowledgeTimer.cs b/RDMSharp/RDM/PayloadObject/AcknowledgeTimer.cs index 702611b..6880491 100644 --- a/RDMSharp/RDM/PayloadObject/AcknowledgeTimer.cs +++ b/RDMSharp/RDM/PayloadObject/AcknowledgeTimer.cs @@ -7,7 +7,7 @@ public class AcknowledgeTimer : AbstractRDMPayloadObject { [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2208")] public AcknowledgeTimer( - TimeSpan estimidatedResponseTime = default) : this((ushort)(estimidatedResponseTime.TotalSeconds / 10)) + TimeSpan estimidatedResponseTime = default) : this((ushort)(estimidatedResponseTime.TotalSeconds * 10.0)) { if (estimidatedResponseTime.TotalSeconds / 10 > ushort.MaxValue) throw new ArgumentOutOfRangeException("The Timer is to long for the Resolution of 16-bit ushort"); @@ -16,7 +16,7 @@ private AcknowledgeTimer( ushort _estimidatedResponseTimeRaw = default) { this.estimidatedResponseTimeRaw = _estimidatedResponseTimeRaw; - this.EstimidatedResponseTime = TimeSpan.FromSeconds(this.estimidatedResponseTimeRaw * 10); + this.EstimidatedResponseTime = TimeSpan.FromSeconds(this.estimidatedResponseTimeRaw / 10.0); } public TimeSpan EstimidatedResponseTime { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyDescriptionResponse.cs b/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyDescriptionResponse.cs index a7de493..85b5b94 100644 --- a/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyDescriptionResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyDescriptionResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class GetBackgroundQueuedStatusPolicyDescriptionResponse : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public GetBackgroundQueuedStatusPolicyDescriptionResponse( - byte policyId = 1, - string description = default) + [DataTreeObjectParameter("policy")] byte policyId = 1, + [DataTreeObjectParameter("description")] string description = default) { this.PolicyId = policyId; diff --git a/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyResponse.cs b/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyResponse.cs index 26a735c..f08b0a6 100644 --- a/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetBackgroundQueuedStatusPolicyResponse.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.BACKGROUND_QUEUED_STATUS_POLICY, Command.ECommandDublicte.GetResponse)] public class GetBackgroundQueuedStatusPolicyResponse : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public GetBackgroundQueuedStatusPolicyResponse( - byte policyId = 1, - byte policies = default) + [DataTreeObjectParameter("policy_setting")] byte policyId = 1, + [DataTreeObjectParameter("policy_setting_count")] byte policies = default) { this.PolicyId = policyId; this.Policies = policies; diff --git a/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsRequest.cs b/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsRequest.cs index d0357fc..a455989 100644 --- a/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsRequest.cs +++ b/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsRequest.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.BINDING_CONTROL_FIELDS, Command.ECommandDublicte.GetRequest)] public class GetBindingAndControlFieldsRequest : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetBindingAndControlFieldsRequest( - ushort endpointId = default, - UID uid = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("uid")] UID uid = default) { this.EndpointId = endpointId; this.UID = uid; diff --git a/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsResponse.cs b/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsResponse.cs index 016e086..e78fe35 100644 --- a/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetBindingAndControlFieldsResponse.cs @@ -1,14 +1,18 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.BINDING_CONTROL_FIELDS, Command.ECommandDublicte.GetResponse)] public class GetBindingAndControlFieldsResponse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetBindingAndControlFieldsResponse( - ushort endpointId = default, - UID uid = default, - ushort controlField = default, - UID bindingUID = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("uid")] UID uid = default, + [DataTreeObjectParameter("control")] ushort controlField = default, + [DataTreeObjectParameter("binding_uid")] UID bindingUID = default) { this.EndpointId = endpointId; this.UID = uid; diff --git a/RDMSharp/RDM/PayloadObject/GetBrokerStatusResponse.cs b/RDMSharp/RDM/PayloadObject/GetBrokerStatusResponse.cs index 445bfad..a0303fe 100644 --- a/RDMSharp/RDM/PayloadObject/GetBrokerStatusResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetBrokerStatusResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.BROKER_STATUS, Command.ECommandDublicte.GetRequest)] public class GetBrokerStatusResponse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetBrokerStatusResponse( - bool setAllowed = default, - ERDM_BrokerStatus brokerStatus = default) + [DataTreeObjectParameter("setAllowed")] bool setAllowed = default, + [DataTreeObjectParameter("brokerStatus")] ERDM_BrokerStatus brokerStatus = default) { this.SetAllowed = setAllowed; this.BrokerStatus = brokerStatus; diff --git a/RDMSharp/RDM/PayloadObject/GetCommunicationStatusNullStartCodeResponse.cs b/RDMSharp/RDM/PayloadObject/GetCommunicationStatusNullStartCodeResponse.cs index ee5201d..f3f338c 100644 --- a/RDMSharp/RDM/PayloadObject/GetCommunicationStatusNullStartCodeResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetCommunicationStatusNullStartCodeResponse.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.COMMS_STATUS_NSC, Command.ECommandDublicte.GetResponse)] public class GetCommunicationStatusNullStartCodeResponse : AbstractRDMPayloadObject { public GetCommunicationStatusNullStartCodeResponse( @@ -20,6 +23,34 @@ public GetCommunicationStatusNullStartCodeResponse( MaximumSlotCount = maximumSlotCount; NumberOfPacketsWithAnError = numberOfPacketsWithAnError; } + [DataTreeObjectConstructor] + public GetCommunicationStatusNullStartCodeResponse( + [DataTreeObjectParameter("supported")] bool[] supported, + [DataTreeObjectParameter("additive_checksum")] uint additiveChecksumOfMostRecentPacket, + [DataTreeObjectParameter("packet_count")] uint packetCount, + [DataTreeObjectParameter("most_recent_slot_count")] ushort mostRecentSlotCount, + [DataTreeObjectParameter("min_slot_count")] ushort minimumSlotCount, + [DataTreeObjectParameter("max_slot_count")] ushort maximumSlotCount, + [DataTreeObjectParameter("error_count")] uint numberOfPacketsWithAnError) + { + if (supported[0]) + AdditiveChecksumOfMostRecentPacket = additiveChecksumOfMostRecentPacket; + + if (supported[1]) + PacketCount = packetCount; + + if (supported[2]) + MostRecentSlotCount = mostRecentSlotCount; + + if (supported[3]) + MinimumSlotCount = minimumSlotCount; + + if (supported[4]) + MaximumSlotCount = maximumSlotCount; + + if (supported[5]) + NumberOfPacketsWithAnError = numberOfPacketsWithAnError; + } public uint? AdditiveChecksumOfMostRecentPacket { get; private set; } public uint? PacketCount { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageRequest.cs b/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageRequest.cs index c6f6986..8c90cb9 100644 --- a/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageRequest.cs +++ b/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageRequest.cs @@ -1,14 +1,18 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DEVICE_INFO_OFFSTAGE, Command.ECommandDublicte.GetRequest)] public class GetDeviceInfoOffstageRequest : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetDeviceInfoOffstageRequest( - byte rootPersonality = 1, - ushort subDeviceRequested = 0, - byte subDevicePersonalityRequested = 0) + [DataTreeObjectParameter("root_personality")] byte rootPersonality = 1, + [DataTreeObjectParameter("subdevice")] ushort subDeviceRequested = 0, + [DataTreeObjectParameter("subdevice_personality")] byte subDevicePersonalityRequested = 0) { RootPersonality = rootPersonality; SubDeviceRequested = subDeviceRequested; diff --git a/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageResponse.cs b/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageResponse.cs index 21357db..d5768a0 100644 --- a/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetDeviceInfoOffstageResponse.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DEVICE_INFO_OFFSTAGE, Command.ECommandDublicte.GetResponse)] public class GetDeviceInfoOffstageResponse : AbstractRDMPayloadObject { public GetDeviceInfoOffstageResponse( @@ -17,6 +20,40 @@ public GetDeviceInfoOffstageResponse( DeviceInfo = deviceInfo; } + [DataTreeObjectConstructor] + public GetDeviceInfoOffstageResponse( + [DataTreeObjectParameter("root_personality")] byte rootPersonality, + [DataTreeObjectParameter("subdevice")] ushort subDeviceRequested, + [DataTreeObjectParameter("subdevice_personality")] byte subDevicePersonalityRequested, + [DataTreeObjectParameter("protocol_major")] byte rdmProtocolVersionMajor, + [DataTreeObjectParameter("protocol_minor")] byte rdmProtocolVersionMinor, + [DataTreeObjectParameter("device_model_id")] ushort deviceModelId, + [DataTreeObjectParameter("product_category")] ushort productCategory, + [DataTreeObjectParameter("software_version_id")] uint softwareVersionId, + [DataTreeObjectParameter("dmx_footprint")] ushort dmx512Footprint, + [DataTreeObjectParameter("current_personality")] byte dmx512CurrentPersonality, + [DataTreeObjectParameter("personality_count")] byte dmx512NumberOfPersonalities, + [DataTreeObjectParameter("dmx_start_address")] ushort dmx512StartAddress, + [DataTreeObjectParameter("sub_device_count")] ushort subDeviceCount, + [DataTreeObjectParameter("sensor_count")] byte sensorCount) + : this(rootPersonality, + subDeviceRequested, + subDevicePersonalityRequested, + new RDMDeviceInfo( + rdmProtocolVersionMajor, + rdmProtocolVersionMinor, + deviceModelId, + productCategory, + softwareVersionId, + dmx512Footprint, + dmx512CurrentPersonality, + dmx512NumberOfPersonalities, + dmx512StartAddress, + subDeviceCount, + sensorCount)) + { + } + public byte RootPersonality { get; private set; } public ushort SubDeviceRequested { get; private set; } public byte SubDevicePersonalityRequested { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/GetDiscoveryStateResponse.cs b/RDMSharp/RDM/PayloadObject/GetDiscoveryStateResponse.cs index 43881f7..4fead44 100644 --- a/RDMSharp/RDM/PayloadObject/GetDiscoveryStateResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetDiscoveryStateResponse.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DISCOVERY_STATE, Command.ECommandDublicte.GetResponse)] public class GetDiscoveryStateResponse : AbstractRDMPayloadObject { public GetDiscoveryStateResponse( @@ -14,6 +17,15 @@ public GetDiscoveryStateResponse( this.DiscoveryState = discoveryState; } + [DataTreeObjectConstructor] + public GetDiscoveryStateResponse( + [DataTreeObjectParameter("endpoint_id")] ushort endpointId, + [DataTreeObjectParameter("device_count")] ushort deviceCount, + [DataTreeObjectParameter("state")] byte discoveryState): + this(endpointId, deviceCount, (ERDM_DiscoveryState)discoveryState) + { + } + public ushort EndpointId { get; private set; } public ushort DeviceCount { get; private set; } public ERDM_DiscoveryState DiscoveryState { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/GetEndpointListResponse.cs b/RDMSharp/RDM/PayloadObject/GetEndpointListResponse.cs index 03d6ffc..b02b462 100644 --- a/RDMSharp/RDM/PayloadObject/GetEndpointListResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetEndpointListResponse.cs @@ -1,13 +1,19 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_LIST, Command.ECommandDublicte.GetResponse)] public class GetEndpointListResponse : AbstractRDMPayloadObject { - public GetEndpointListResponse(uint listChangedNumber = 0, params EndpointDescriptor[] endpoints) + [DataTreeObjectConstructor] + public GetEndpointListResponse( + [DataTreeObjectParameter("list_change_number")] uint listChangedNumber = 0, + [DataTreeObjectParameter("endpoints")] params EndpointDescriptor[] endpoints) { this.ListChangedNumber = listChangedNumber; this.Endpoints = endpoints; diff --git a/RDMSharp/RDM/PayloadObject/GetEndpointResponderListChangeResponse.cs b/RDMSharp/RDM/PayloadObject/GetEndpointResponderListChangeResponse.cs index 039fc53..505049d 100644 --- a/RDMSharp/RDM/PayloadObject/GetEndpointResponderListChangeResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetEndpointResponderListChangeResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_RESPONDER_LIST_CHANGE, Command.ECommandDublicte.GetResponse)] public class GetEndpointResponderListChangeResponse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetEndpointResponderListChangeResponse( - ushort endpointId = default, - uint listChangeNumber = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("list_change_number")] uint listChangeNumber = default) { this.EndpointId = endpointId; this.ListChangeNumber = listChangeNumber; diff --git a/RDMSharp/RDM/PayloadObject/GetEndpointRespondersResponse.cs b/RDMSharp/RDM/PayloadObject/GetEndpointRespondersResponse.cs index ac3ccbe..82b3e12 100644 --- a/RDMSharp/RDM/PayloadObject/GetEndpointRespondersResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetEndpointRespondersResponse.cs @@ -1,12 +1,18 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_RESPONDERS, Command.ECommandDublicte.GetResponse)] public class GetEndpointRespondersResponse : AbstractRDMPayloadObject { - public GetEndpointRespondersResponse(uint listChangedNumber = 0, params UID[] uids) + [DataTreeObjectConstructor] + public GetEndpointRespondersResponse( + [DataTreeObjectParameter("list_change_number")] uint listChangedNumber = 0, + [DataTreeObjectParameter("uids")] params UID[] uids) { this.ListChangedNumber = listChangedNumber; this.UIDs = uids; diff --git a/RDMSharp/RDM/PayloadObject/GetEndpointTimingDescriptionResponse.cs b/RDMSharp/RDM/PayloadObject/GetEndpointTimingDescriptionResponse.cs index 8ab79f6..7a2221e 100644 --- a/RDMSharp/RDM/PayloadObject/GetEndpointTimingDescriptionResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetEndpointTimingDescriptionResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.ENDPOINT_TIMING_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class GetEndpointTimingDescriptionResponse : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public GetEndpointTimingDescriptionResponse( - byte timingtId = 1, - string description = default) + [DataTreeObjectParameter("setting")] byte timingtId = 1, + [DataTreeObjectParameter("description")] string description = default) { this.TimingId = timingtId; diff --git a/RDMSharp/RDM/PayloadObject/GetEndpointTimingResponse.cs b/RDMSharp/RDM/PayloadObject/GetEndpointTimingResponse.cs index ace20a8..c412999 100644 --- a/RDMSharp/RDM/PayloadObject/GetEndpointTimingResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetEndpointTimingResponse.cs @@ -1,14 +1,18 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.ENDPOINT_TIMING, Command.ECommandDublicte.GetResponse)] public class GetEndpointTimingResponse : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public GetEndpointTimingResponse( - ushort endpointId = default, - byte timingId = 1, - byte timings = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("setting")] byte timingId = 1, + [DataTreeObjectParameter("setting_count")] byte timings = default) { this.EndpointId = endpointId; this.TimingId = timingId; diff --git a/RDMSharp/RDM/PayloadObject/GetHardwareAddressResponse.cs b/RDMSharp/RDM/PayloadObject/GetHardwareAddressResponse.cs index 406d943..5fb2255 100644 --- a/RDMSharp/RDM/PayloadObject/GetHardwareAddressResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetHardwareAddressResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.INTERFACE_HARDWARE_ADDRESS_TYPE, Command.ECommandDublicte.GetResponse)] public class GetHardwareAddressResponse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetHardwareAddressResponse( - uint interfaceId = 0, - MACAddress hardwareAddress = default) + [DataTreeObjectParameter("id")] uint interfaceId = 0, + [DataTreeObjectParameter("address")] MACAddress hardwareAddress = default) { this.InterfaceId = interfaceId; this.HardwareAddress = hardwareAddress; diff --git a/RDMSharp/RDM/PayloadObject/GetIPv4CurrentAddressResponse.cs b/RDMSharp/RDM/PayloadObject/GetIPv4CurrentAddressResponse.cs index 1967b54..9876a87 100644 --- a/RDMSharp/RDM/PayloadObject/GetIPv4CurrentAddressResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetIPv4CurrentAddressResponse.cs @@ -1,9 +1,12 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Net; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.IPV4_CURRENT_ADDRESS, Command.ECommandDublicte.GetResponse)] public class GetIPv4CurrentAddressResponse : AbstractRDMPayloadObject { public GetIPv4CurrentAddressResponse( @@ -20,6 +23,15 @@ public GetIPv4CurrentAddressResponse( this.Netmask = netmask; this.DHCPStatus = dhcpStatus; } + [DataTreeObjectConstructor] + public GetIPv4CurrentAddressResponse( + [DataTreeObjectParameter("id")] uint interfaceId, + [DataTreeObjectParameter("address")] IPv4Address ipAddress, + [DataTreeObjectParameter("netmask")] byte netmask, + [DataTreeObjectParameter("dhcp_status")] byte dhcpStatus) + :this(interfaceId, ipAddress, netmask, (ERDM_DHCPStatusMode)dhcpStatus) + { + } public uint InterfaceId { get; private set; } public IPAddress IPAddress { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/GetInterfaceListResponse.cs b/RDMSharp/RDM/PayloadObject/GetInterfaceListResponse.cs index d27b8fc..f40b291 100644 --- a/RDMSharp/RDM/PayloadObject/GetInterfaceListResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetInterfaceListResponse.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.LIST_INTERFACES, Command.ECommandDublicte.GetResponse)] public class GetInterfaceListResponse : AbstractRDMPayloadObject { - public GetInterfaceListResponse(params InterfaceDescriptor[] interfaces) + [DataTreeObjectConstructor] + public GetInterfaceListResponse([DataTreeObjectParameter("interfaces")] params InterfaceDescriptor[] interfaces) { this.Interfaces = interfaces; } diff --git a/RDMSharp/RDM/PayloadObject/GetInterfaceNameResponse.cs b/RDMSharp/RDM/PayloadObject/GetInterfaceNameResponse.cs index 49bd95a..6473df2 100644 --- a/RDMSharp/RDM/PayloadObject/GetInterfaceNameResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetInterfaceNameResponse.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.INTERFACE_LABEL, Command.ECommandDublicte.GetResponse)] public class GetInterfaceNameResponse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetInterfaceNameResponse( - uint interfaceId = 0, - string label = "") + [DataTreeObjectParameter("id")] uint interfaceId = 0, + [DataTreeObjectParameter("label")] string label = "") { this.InterfaceId = interfaceId; diff --git a/RDMSharp/RDM/PayloadObject/GetLockStateResponse.cs b/RDMSharp/RDM/PayloadObject/GetLockStateResponse.cs index a429a89..ad983cd 100644 --- a/RDMSharp/RDM/PayloadObject/GetLockStateResponse.cs +++ b/RDMSharp/RDM/PayloadObject/GetLockStateResponse.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.LOCK_STATE, Command.ECommandDublicte.GetResponse)] public class GetLockStateResponse : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public GetLockStateResponse( - byte currentLockStateId = 1, - byte lockStates = 0) + [DataTreeObjectParameter("state")] byte currentLockStateId = 1, + [DataTreeObjectParameter("state_count")] byte lockStates = 0) { this.CurrentLockStateId = currentLockStateId; this.LockStates = lockStates; diff --git a/RDMSharp/RDM/PayloadObject/GetSetComponentScope.cs b/RDMSharp/RDM/PayloadObject/GetSetComponentScope.cs index 39996ca..40ad163 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetComponentScope.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetComponentScope.cs @@ -1,4 +1,6 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Linq; using System.Net; @@ -6,16 +8,19 @@ using System.Text; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.COMPONENT_SCOPE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.COMPONENT_SCOPE, Command.ECommandDublicte.SetRequest)] public class GetSetComponentScope : AbstractRDMPayloadObject - { + { + [DataTreeObjectConstructor] public GetSetComponentScope( - ushort scopeSlot = default, - string scopeString = default, - ERDM_StaticConfig staticConfigType = default, - IPAddress staticBrokerIPv4 = default, - IPAddress staticBrokerIPv6 = default, - ushort staticBrokerPort = default) + [DataTreeObjectParameter("scopeSlot")] ushort scopeSlot = default, + [DataTreeObjectParameter("scopeSlot")] string scopeString = default, + [DataTreeObjectParameter("scopeSlot")] ERDM_StaticConfig staticConfigType = default, + [DataTreeObjectParameter("scopeSlot")] IPAddress staticBrokerIPv4 = default, + [DataTreeObjectParameter("scopeSlot")] IPAddress staticBrokerIPv6 = default, + [DataTreeObjectParameter("scopeSlot")] ushort staticBrokerPort = default) { if (string.IsNullOrWhiteSpace(scopeString)) diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointBackgroundDiscovery.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointBackgroundDiscovery.cs index 14eb81d..5624868 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointBackgroundDiscovery.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointBackgroundDiscovery.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.BACKGROUND_DISCOVERY, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.BACKGROUND_DISCOVERY, Command.ECommandDublicte.SetRequest)] public class GetSetEndpointBackgroundDiscovery : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetEndpointBackgroundDiscovery( - ushort endpointId = default, - bool backgroundDiscovery = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("enabled")] bool backgroundDiscovery = default) { this.EndpointId = endpointId; this.BackgroundDiscovery = backgroundDiscovery; diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointIdentify.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointIdentify.cs index a9faf8b..cdb0248 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointIdentify.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointIdentify.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.IDENTIFY_ENDPOINT, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.IDENTIFY_ENDPOINT, Command.ECommandDublicte.SetRequest)] public class GetSetIdentifyEndpoint : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetIdentifyEndpoint( - ushort endpointId = default, - bool identifyState = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("identify_state")] bool identifyState = default) { this.EndpointId = endpointId; this.IdentifyState = identifyState; diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointLabel.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointLabel.cs index ef64ccf..9e242b8 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointLabel.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointLabel.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_LABEL, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.ENDPOINT_LABEL, Command.ECommandDublicte.SetRequest)] public class GetSetEndpointLabel : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetEndpointLabel( - ushort endpointId = default, - string endpointLabel = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("label")] string endpointLabel = default) { this.EndpointId = endpointId; diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointMode.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointMode.cs index bf80773..419ad41 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointMode.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointMode.cs @@ -1,7 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_MODE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.ENDPOINT_MODE, Command.ECommandDublicte.SetRequest)] public class GetSetEndpointMode : AbstractRDMPayloadObject { public GetSetEndpointMode( @@ -12,6 +16,14 @@ public GetSetEndpointMode( this.EndpointMode = endpointMode; } + [DataTreeObjectConstructor] + public GetSetEndpointMode( + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("mode")] byte endpointMode = default): + this(endpointId, (ERDM_EndpointMode)endpointMode) + { + } + public ushort EndpointId { get; private set; } public ERDM_EndpointMode EndpointMode { get; private set; } public const int PDL = 0x03; diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointRDMTrafficEnable.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointRDMTrafficEnable.cs index 622d27a..31340cb 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointRDMTrafficEnable.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointRDMTrafficEnable.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.RDM_TRAFFIC_ENABLE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.RDM_TRAFFIC_ENABLE, Command.ECommandDublicte.SetRequest)] public class GetSetEndpointRDMTrafficEnable : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetEndpointRDMTrafficEnable( - ushort endpointId = default, - bool rdmTrafficEnabled = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("rdm_enabled")] bool rdmTrafficEnabled = default) { this.EndpointId = endpointId; this.RDMTrafficEnabled = rdmTrafficEnabled; diff --git a/RDMSharp/RDM/PayloadObject/GetSetEndpointToUniverse.cs b/RDMSharp/RDM/PayloadObject/GetSetEndpointToUniverse.cs index f14fa54..1b43796 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetEndpointToUniverse.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetEndpointToUniverse.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_TO_UNIVERSE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.ENDPOINT_TO_UNIVERSE, Command.ECommandDublicte.SetRequest)] public class GetSetEndpointToUniverse : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetEndpointToUniverse( - ushort endpointId = default, - ushort universe = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("universe")] ushort universe = default) { this.EndpointId = endpointId; this.Universe = universe; diff --git a/RDMSharp/RDM/PayloadObject/GetSetIPV4_xxx_Mode.cs b/RDMSharp/RDM/PayloadObject/GetSetIPV4_xxx_Mode.cs index 1dd9307..e1a8b21 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetIPV4_xxx_Mode.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetIPV4_xxx_Mode.cs @@ -1,12 +1,19 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.IPV4_DHCP_MODE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.IPV4_DHCP_MODE, Command.ECommandDublicte.SetRequest)] + [DataTreeObject(ERDM_Parameter.IPV4_ZEROCONF_MODE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.IPV4_ZEROCONF_MODE, Command.ECommandDublicte.SetRequest)] public class GetSetIPV4_xxx_Mode : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetIPV4_xxx_Mode( - uint interfaceId = 0, - bool enabled = false) + [DataTreeObjectParameter("id")] uint interfaceId = 0, + [DataTreeObjectParameter("mode")] bool enabled = false) { this.InterfaceId = interfaceId; this.Enabled = enabled; diff --git a/RDMSharp/RDM/PayloadObject/GetSetIPv4DefaultRoute.cs b/RDMSharp/RDM/PayloadObject/GetSetIPv4DefaultRoute.cs index a53a874..1826d4b 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetIPv4DefaultRoute.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetIPv4DefaultRoute.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.IPV4_DEFAULT_ROUTE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.IPV4_DEFAULT_ROUTE, Command.ECommandDublicte.SetRequest)] public class GetSetIPv4DefaultRoute : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetIPv4DefaultRoute( - uint interfaceId = 0, - IPv4Address ipAddress = default) + [DataTreeObjectParameter("id")] uint interfaceId = 0, + [DataTreeObjectParameter("default_route")] IPv4Address ipAddress = default) { this.InterfaceId = interfaceId; this.IPAddress = ipAddress; diff --git a/RDMSharp/RDM/PayloadObject/GetSetIPv4NameServer.cs b/RDMSharp/RDM/PayloadObject/GetSetIPv4NameServer.cs index f9b4689..9ab8fd3 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetIPv4NameServer.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetIPv4NameServer.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DNS_IPV4_NAME_SERVER, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.DNS_IPV4_NAME_SERVER, Command.ECommandDublicte.SetRequest)] public class GetSetIPv4NameServer : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetIPv4NameServer( - byte nameServerIndex = 0, - IPv4Address ipAddress = default) + [DataTreeObjectParameter("index")] byte nameServerIndex = 0, + [DataTreeObjectParameter("address")] IPv4Address ipAddress = default) { this.NameServerIndex = nameServerIndex; this.IPAddress = ipAddress; diff --git a/RDMSharp/RDM/PayloadObject/GetSetIPv4StaticAddress.cs b/RDMSharp/RDM/PayloadObject/GetSetIPv4StaticAddress.cs index 1a58020..fef4493 100644 --- a/RDMSharp/RDM/PayloadObject/GetSetIPv4StaticAddress.cs +++ b/RDMSharp/RDM/PayloadObject/GetSetIPv4StaticAddress.cs @@ -1,14 +1,19 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.IPV4_STATIC_ADDRESS, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.IPV4_STATIC_ADDRESS, Command.ECommandDublicte.SetRequest)] public class GetSetIPv4StaticAddress : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public GetSetIPv4StaticAddress( - uint interfaceId = 0, - IPv4Address ipAddress = default, - byte netmask = 24) + [DataTreeObjectParameter("id")] uint interfaceId = 0, + [DataTreeObjectParameter("address")] IPv4Address ipAddress = default, + [DataTreeObjectParameter("netmask")] byte netmask = 24) { this.InterfaceId = interfaceId; this.IPAddress = ipAddress; diff --git a/RDMSharp/RDM/PayloadObject/RDMCommunicationStatus.cs b/RDMSharp/RDM/PayloadObject/RDMCommunicationStatus.cs index ccd226c..417b56c 100644 --- a/RDMSharp/RDM/PayloadObject/RDMCommunicationStatus.cs +++ b/RDMSharp/RDM/PayloadObject/RDMCommunicationStatus.cs @@ -1,14 +1,18 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.COMMS_STATUS, Command.ECommandDublicte.GetResponse)] public class RDMCommunicationStatus : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMCommunicationStatus( - ushort shortMessage = 0, - ushort lengthMismatch = 0, - ushort checksumFail = 0) + [DataTreeObjectParameter("short_message")] ushort shortMessage = 0, + [DataTreeObjectParameter("length_mismatch")] ushort lengthMismatch = 0, + [DataTreeObjectParameter("checksum_fail")] ushort checksumFail = 0) { this.ShortMessage = shortMessage; this.LengthMismatch = lengthMismatch; diff --git a/RDMSharp/RDM/PayloadObject/RDMCurve.cs b/RDMSharp/RDM/PayloadObject/RDMCurve.cs index 1a0a003..a68a561 100644 --- a/RDMSharp/RDM/PayloadObject/RDMCurve.cs +++ b/RDMSharp/RDM/PayloadObject/RDMCurve.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.CURVE, Command.ECommandDublicte.GetResponse)] public class RDMCurve : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public RDMCurve( - byte currentCurveId = 1, - byte curves = 0) + [DataTreeObjectParameter("curve")] byte currentCurveId = 1, + [DataTreeObjectParameter("curve_count")] byte curves = 0) { this.CurrentCurveId = currentCurveId; this.Curves = curves; diff --git a/RDMSharp/RDM/PayloadObject/RDMCurveDescription.cs b/RDMSharp/RDM/PayloadObject/RDMCurveDescription.cs index ed4b66a..43fae13 100644 --- a/RDMSharp/RDM/PayloadObject/RDMCurveDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMCurveDescription.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.CURVE_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMCurveDescription : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMCurveDescription( - byte curveId = 1, - string description = "") + [DataTreeObjectParameter("curve")] byte curveId = 1, + [DataTreeObjectParameter("description")] string description = "") { this.CurveId = curveId; diff --git a/RDMSharp/RDM/PayloadObject/RDMDMXBlockAddress.cs b/RDMSharp/RDM/PayloadObject/RDMDMXBlockAddress.cs index 78a4888..ba28802 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDMXBlockAddress.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDMXBlockAddress.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DMX_BLOCK_ADDRESS, Command.ECommandDublicte.GetResponse)] public class RDMDMXBlockAddress : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMDMXBlockAddress( - ushort totalSubDeviceFootprint = 0, - ushort baseDMX512Address = 0) + [DataTreeObjectParameter("total_subdevice_footprint")] ushort totalSubDeviceFootprint = 0, + [DataTreeObjectParameter("base_dmx_address")] ushort baseDMX512Address = 0) { this.TotalSubDeviceFootprint = totalSubDeviceFootprint; this.BaseDMX512Address = baseDMX512Address; diff --git a/RDMSharp/RDM/PayloadObject/RDMDMXPersonality.cs b/RDMSharp/RDM/PayloadObject/RDMDMXPersonality.cs index 01025b2..dd1e7ad 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDMXPersonality.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDMXPersonality.cs @@ -1,19 +1,26 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.DMX_PERSONALITY, Command.ECommandDublicte.GetResponse)] public class RDMDMXPersonality : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public RDMDMXPersonality( - byte currentPersonality = 1, - byte ofPersonalities = 0) + [DataTreeObjectParameter("personality")] byte currentPersonality = 1, + [DataTreeObjectParameter("personality_count")] byte ofPersonalities = 0) { this.CurrentPersonality = currentPersonality; this.OfPersonalities = ofPersonalities; } + [DataTreeObjectProperty("personality", 0)] public byte CurrentPersonality { get; private set; } + + [DataTreeObjectProperty("personality_count", 1)] public byte OfPersonalities { get; private set; } public override Type IndexType => CurrentPersonality.GetType(); diff --git a/RDMSharp/RDM/PayloadObject/RDMDMXPersonalityDescription.cs b/RDMSharp/RDM/PayloadObject/RDMDMXPersonalityDescription.cs index 9b4c2e5..3b316df 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDMXPersonalityDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDMXPersonalityDescription.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.DMX_PERSONALITY_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMDMXPersonalityDescription : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMDMXPersonalityDescription( - byte personalityId = 1, - ushort slots = 0, - string description = "") + [DataTreeObjectParameter("personality")] byte personalityId = 1, + [DataTreeObjectParameter("dmx_slots_required")] ushort slots = 0, + [DataTreeObjectParameter("description")] string description = "") { this.PersonalityId = personalityId; this.Slots = slots; @@ -19,10 +23,16 @@ public RDMDMXPersonalityDescription( description = description.Substring(0, 32); this.Description = description; - } - - public byte PersonalityId { get; private set; } - public ushort Slots { get; private set; } + } + + + [DataTreeObjectProperty("personality", 0)] + public byte PersonalityId { get; private set; } + + [DataTreeObjectProperty("dmx_slots_required", 1)] + public ushort Slots { get; private set; } + + [DataTreeObjectProperty("description", 2)] public string Description { get; private set; } public object MinIndex => (byte)1; diff --git a/RDMSharp/RDM/PayloadObject/RDMDMX_xxxx_Mode.cs b/RDMSharp/RDM/PayloadObject/RDMDMX_xxxx_Mode.cs index da8c13c..b06c870 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDMX_xxxx_Mode.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDMX_xxxx_Mode.cs @@ -1,15 +1,22 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DMX_FAIL_MODE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.DMX_FAIL_MODE, Command.ECommandDublicte.SetRequest)] + [DataTreeObject(ERDM_Parameter.DMX_STARTUP_MODE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.DMX_STARTUP_MODE, Command.ECommandDublicte.SetRequest)] public class RDMDMX_xxxx_Mode : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMDMX_xxxx_Mode( - ushort scene = 0, - ushort delay = 0, - ushort holdTime = 0, - byte level = 0) + [DataTreeObjectParameter("scene_num")] ushort scene = 0, + [DataTreeObjectParameter(ERDM_Parameter.DMX_FAIL_MODE, "loss_of_signal_delay_time"), DataTreeObjectParameter(ERDM_Parameter.DMX_STARTUP_MODE, "startup_delay_time")] ushort delay = 0, + [DataTreeObjectParameter("hold_time")] ushort holdTime = 0, + [DataTreeObjectParameter("level")] byte level = 0) { this.Scene = scene; this.Delay = delay; diff --git a/RDMSharp/RDM/PayloadObject/RDMDefaultSlotValue.cs b/RDMSharp/RDM/PayloadObject/RDMDefaultSlotValue.cs index 2264797..7d60615 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDefaultSlotValue.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDefaultSlotValue.cs @@ -1,13 +1,18 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; +using static System.Reflection.Metadata.BlobBuilder; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.DEFAULT_SLOT_VALUE, Command.ECommandDublicte.GetResponse, true, "slots")] public class RDMDefaultSlotValue : AbstractRDMPayloadObject - { + { + [DataTreeObjectConstructor] public RDMDefaultSlotValue( - ushort slotOffset = 0, - byte defaultSlotValue = 0) + [DataTreeObjectParameter("id")] ushort slotOffset = 0, + [DataTreeObjectParameter("default_value")] byte defaultSlotValue = 0) { this.SlotOffset = slotOffset; this.DefaultSlotValue = defaultSlotValue; diff --git a/RDMSharp/RDM/PayloadObject/RDMDeviceInfo.cs b/RDMSharp/RDM/PayloadObject/RDMDeviceInfo.cs index a720f27..0b8535f 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDeviceInfo.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDeviceInfo.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DEVICE_INFO, Command.ECommandDublicte.GetResponse)] public class RDMDeviceInfo : AbstractRDMPayloadObject { public RDMDeviceInfo( @@ -32,19 +35,73 @@ public RDMDeviceInfo( SubDeviceCount = subDeviceCount; SensorCount = sensorCount; } + [DataTreeObjectConstructor] + public RDMDeviceInfo( + [DataTreeObjectParameter("protocol_major")] byte rdmProtocolVersionMajor, + [DataTreeObjectParameter("protocol_minor")] byte rdmProtocolVersionMinor, + [DataTreeObjectParameter("device_model_id")] ushort deviceModelId, + [DataTreeObjectParameter("product_category")] ushort productCategory, + [DataTreeObjectParameter("software_version_id")] uint softwareVersionId, + [DataTreeObjectParameter("dmx_footprint")] ushort dmx512Footprint, + [DataTreeObjectParameter("current_personality")] byte dmx512CurrentPersonality, + [DataTreeObjectParameter("personality_count")] byte dmx512NumberOfPersonalities, + [DataTreeObjectParameter("dmx_start_address")] ushort dmx512StartAddress, + [DataTreeObjectParameter("sub_device_count")] ushort subDeviceCount, + [DataTreeObjectParameter("sensor_count")] byte sensorCount): + this(rdmProtocolVersionMajor, + rdmProtocolVersionMinor, + deviceModelId, + (ERDM_ProductCategoryCoarse)(byte)(productCategory >> 8), + (ERDM_ProductCategoryFine)productCategory, + softwareVersionId, + dmx512Footprint, + dmx512CurrentPersonality, + dmx512NumberOfPersonalities, + dmx512StartAddress, + subDeviceCount, + sensorCount) + { + } + [DataTreeObjectProperty("protocol_major", 0)] public byte RdmProtocolVersionMajor { get; private set; } + + [DataTreeObjectProperty("protocol_minor", 1)] public byte RdmProtocolVersionMinor { get; private set; } + + [DataTreeObjectProperty("device_model_id", 2)] public ushort DeviceModelId { get; private set; } public ERDM_ProductCategoryCoarse ProductCategoryCoarse { get; private set; } public ERDM_ProductCategoryFine ProductCategoryFine { get; private set; } + + [DataTreeObjectProperty("product_category", 3)] + public ushort ProductCategory => (ushort)ProductCategoryFine; + + [DataTreeObjectProperty("software_version_id", 4)] public uint SoftwareVersionId { get; private set; } + + [DataTreeObjectProperty("dmx_footprint", 5)] public ushort? Dmx512Footprint { get; private set; } + + [DataTreeObjectProperty("current_personality", 6)] public byte? Dmx512CurrentPersonality { get; private set; } + + [DataTreeObjectDependecieProperty("personality", ERDM_Parameter.DMX_PERSONALITY_DESCRIPTION, Command.ECommandDublicte.GetRequest)] + [DataTreeObjectDependecieProperty("personality", ERDM_Parameter.DMX_PERSONALITY_ID, Command.ECommandDublicte.GetRequest)] + [DataTreeObjectProperty("personality_count", 7)] public byte Dmx512NumberOfPersonalities { get; private set; } + + [DataTreeObjectProperty("dmx_start_address", 8)] public ushort? Dmx512StartAddress { get; private set; } + + [DataTreeObjectProperty("sub_device_count", 9)] public ushort SubDeviceCount { get; private set; } + + [DataTreeObjectDependecieProperty("sensor", ERDM_Parameter.SENSOR_DEFINITION, Command.ECommandDublicte.GetRequest)] + [DataTreeObjectDependecieProperty("sensor", ERDM_Parameter.SENSOR_VALUE, Command.ECommandDublicte.GetRequest)] + [DataTreeObjectProperty("sensor_count", 10)] public byte SensorCount { get; private set; } + public const int PDL = 19; public override string ToString() diff --git a/RDMSharp/RDM/PayloadObject/RDMDimmerInfo.cs b/RDMSharp/RDM/PayloadObject/RDMDimmerInfo.cs index d576232..7b159b4 100644 --- a/RDMSharp/RDM/PayloadObject/RDMDimmerInfo.cs +++ b/RDMSharp/RDM/PayloadObject/RDMDimmerInfo.cs @@ -1,19 +1,23 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DIMMER_INFO, Command.ECommandDublicte.GetResponse)] public class RDMDimmerInfo : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMDimmerInfo( - ushort minimumLevelLowerLimit = 0xFFFF, - ushort minimumLevelUpperLimit = 0xFFFF, - ushort maximumLevelLowerLimit = 0xFFFF, - ushort maximumLevelUpperLimit = 0xFFFF, - byte numberOfSupportedCurves = 0, - byte levelsResolution = 1, - bool minimumLevelSplitLevelsSupported = false) + [DataTreeObjectParameter("min_level_lower_limit")] ushort minimumLevelLowerLimit = 0xFFFF, + [DataTreeObjectParameter("min_level_upper_limit")] ushort minimumLevelUpperLimit = 0xFFFF, + [DataTreeObjectParameter("max_level_lower_limit")] ushort maximumLevelLowerLimit = 0xFFFF, + [DataTreeObjectParameter("max_level_upper_limit")] ushort maximumLevelUpperLimit = 0xFFFF, + [DataTreeObjectParameter("curve_count")] byte numberOfSupportedCurves = 0, + [DataTreeObjectParameter("levels_resolution_bits")] byte levelsResolution = 1, + [DataTreeObjectParameter("min_level_split_levels_supported")] bool minimumLevelSplitLevelsSupported = false) { if (levelsResolution < 0x01 || levelsResolution > 0x10) throw new ArgumentOutOfRangeException($"{nameof(levelsResolution)} shold be a value between 1 and 31 but is {levelsResolution}"); diff --git a/RDMSharp/RDM/PayloadObject/RDMLockStateDescription.cs b/RDMSharp/RDM/PayloadObject/RDMLockStateDescription.cs index 73c63e0..df36ff7 100644 --- a/RDMSharp/RDM/PayloadObject/RDMLockStateDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMLockStateDescription.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.LOCK_STATE_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMLockStateDescription : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMLockStateDescription( - byte lockStateId = 1, - string description = "") + [DataTreeObjectParameter("state")] byte lockStateId = 1, + [DataTreeObjectParameter("description")] string description = "") { this.LockStateId = lockStateId; diff --git a/RDMSharp/RDM/PayloadObject/RDMMetadataJson.cs b/RDMSharp/RDM/PayloadObject/RDMMetadataJson.cs index b491b9e..6e9f73c 100644 --- a/RDMSharp/RDM/PayloadObject/RDMMetadataJson.cs +++ b/RDMSharp/RDM/PayloadObject/RDMMetadataJson.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.METADATA_JSON, Command.ECommandDublicte.GetResponse)] public class RDMMetadataJson : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMMetadataJson( - ERDM_Parameter parameterId, - string json) + [DataTreeObjectParameter("pid")] ERDM_Parameter parameterId, + [DataTreeObjectParameter("json")] string json) { this.ParameterId = parameterId; this.JSON = json; diff --git a/RDMSharp/RDM/PayloadObject/RDMMetadataParameterVersion.cs b/RDMSharp/RDM/PayloadObject/RDMMetadataParameterVersion.cs index 66a98df..dc6c72f 100644 --- a/RDMSharp/RDM/PayloadObject/RDMMetadataParameterVersion.cs +++ b/RDMSharp/RDM/PayloadObject/RDMMetadataParameterVersion.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.METADATA_PARAMETER_VERSION, Command.ECommandDublicte.GetResponse)] public class RDMMetadataParameterVersion : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMMetadataParameterVersion( - ERDM_Parameter parameterId, - ushort version) + [DataTreeObjectParameter("pid")] ERDM_Parameter parameterId, + [DataTreeObjectParameter("version")] ushort version) { this.ParameterId = parameterId; this.Version = version; diff --git a/RDMSharp/RDM/PayloadObject/RDMMinimumLevel.cs b/RDMSharp/RDM/PayloadObject/RDMMinimumLevel.cs index 3285331..ca11a86 100644 --- a/RDMSharp/RDM/PayloadObject/RDMMinimumLevel.cs +++ b/RDMSharp/RDM/PayloadObject/RDMMinimumLevel.cs @@ -1,14 +1,19 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.MINIMUM_LEVEL, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.MINIMUM_LEVEL, Command.ECommandDublicte.SetRequest)] public class RDMMinimumLevel : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMMinimumLevel( - ushort minimumLevelIncrease = 0, - ushort minimumLevelDecrease = 0, - bool onBelowMinimum = false) + [DataTreeObjectParameter("min_level_increasing")] ushort minimumLevelIncrease = 0, + [DataTreeObjectParameter("min_level_decreasing")] ushort minimumLevelDecrease = 0, + [DataTreeObjectParameter("on_below_min")] bool onBelowMinimum = false) { this.MinimumLevelIncrease = minimumLevelIncrease; this.MinimumLevelDecrease = minimumLevelDecrease; diff --git a/RDMSharp/RDM/PayloadObject/RDMModulationFrequency.cs b/RDMSharp/RDM/PayloadObject/RDMModulationFrequency.cs index c23ef28..382a20f 100644 --- a/RDMSharp/RDM/PayloadObject/RDMModulationFrequency.cs +++ b/RDMSharp/RDM/PayloadObject/RDMModulationFrequency.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.MODULATION_FREQUENCY, Command.ECommandDublicte.GetResponse)] public class RDMModulationFrequency : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public RDMModulationFrequency( - byte modulationFrequencyId = 1, - byte modulationFrequencys = 0) + [DataTreeObjectParameter("setting")] byte modulationFrequencyId = 1, + [DataTreeObjectParameter("uint8")] byte modulationFrequencys = 0) { this.ModulationFrequencyId = modulationFrequencyId; this.ModulationFrequencys = modulationFrequencys; diff --git a/RDMSharp/RDM/PayloadObject/RDMModulationFrequencyDescription.cs b/RDMSharp/RDM/PayloadObject/RDMModulationFrequencyDescription.cs index b9bd7eb..1fbd6c2 100644 --- a/RDMSharp/RDM/PayloadObject/RDMModulationFrequencyDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMModulationFrequencyDescription.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.MODULATION_FREQUENCY_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMModulationFrequencyDescription : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMModulationFrequencyDescription( - byte modulationFrequencyId = 1, - uint? frequency = null, - string description = "") + [DataTreeObjectParameter("setting")] byte modulationFrequencyId = 1, + [DataTreeObjectParameter("frequency")] uint? frequency = null, + [DataTreeObjectParameter("description")] string description = "") { this.ModulationFrequencyId = modulationFrequencyId; diff --git a/RDMSharp/RDM/PayloadObject/RDMOutputResponseTime.cs b/RDMSharp/RDM/PayloadObject/RDMOutputResponseTime.cs index 2e33f3a..d832d56 100644 --- a/RDMSharp/RDM/PayloadObject/RDMOutputResponseTime.cs +++ b/RDMSharp/RDM/PayloadObject/RDMOutputResponseTime.cs @@ -1,13 +1,17 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.OUTPUT_RESPONSE_TIME, Command.ECommandDublicte.GetResponse)] public class RDMOutputResponseTime : AbstractRDMPayloadObjectOneOf - { + { + [DataTreeObjectConstructor] public RDMOutputResponseTime( - byte currentResponseTimeId = 1, - byte responseTimes = 0) + [DataTreeObjectParameter("setting")] byte currentResponseTimeId = 1, + [DataTreeObjectParameter("setting_count")] byte responseTimes = 0) { this.CurrentResponseTimeId = currentResponseTimeId; this.ResponseTimes = responseTimes; diff --git a/RDMSharp/RDM/PayloadObject/RDMOutputResponseTimeDescription.cs b/RDMSharp/RDM/PayloadObject/RDMOutputResponseTimeDescription.cs index 1075ab1..d034517 100644 --- a/RDMSharp/RDM/PayloadObject/RDMOutputResponseTimeDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMOutputResponseTimeDescription.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.OUTPUT_RESPONSE_TIME_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMOutputResponseTimeDescription : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMOutputResponseTimeDescription( - byte outputResponseTimeId = 1, - string description = "") + [DataTreeObjectParameter("setting")] byte outputResponseTimeId = 1, + [DataTreeObjectParameter("description")] string description = "") { this.OutputResponseTimeId = outputResponseTimeId; diff --git a/RDMSharp/RDM/PayloadObject/RDMParameterDescription.cs b/RDMSharp/RDM/PayloadObject/RDMParameterDescription.cs index 40bcb57..ebdd036 100644 --- a/RDMSharp/RDM/PayloadObject/RDMParameterDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMParameterDescription.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.PARAMETER_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMParameterDescription : AbstractRDMPayloadObject { [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060")] @@ -37,6 +40,22 @@ public RDMParameterDescription( this.Description = description; } + [DataTreeObjectConstructor] + public RDMParameterDescription( + [DataTreeObjectParameter("pid")] ushort parameterId, + [DataTreeObjectParameter("pdl")] byte pdlSize, + [DataTreeObjectParameter("data_type")] byte dataType, + [DataTreeObjectParameter("command_class")] byte commandClass, + [DataTreeObjectParameter("type")] byte type, //Obsolete + [DataTreeObjectParameter("unit")] byte unit, + [DataTreeObjectParameter("unit_prefix")] byte prefix, + [DataTreeObjectParameter("min_valid_value")] int minValidValue, + [DataTreeObjectParameter("max_valid_value")] int maxValidValue, + [DataTreeObjectParameter("default_value")] int defaultValue, + [DataTreeObjectParameter("description")] string description) + : this(parameterId, pdlSize, (ERDM_DataType)dataType, (ERDM_CommandClass)commandClass, type, (ERDM_SensorUnit)unit, (ERDM_UnitPrefix)prefix, minValidValue, maxValidValue, defaultValue, description) + { + } public ushort ParameterId { get; private set; } public byte PDLSize { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/RDMPersonalityId.cs b/RDMSharp/RDM/PayloadObject/RDMPersonalityId.cs index 167fe06..3457f99 100644 --- a/RDMSharp/RDM/PayloadObject/RDMPersonalityId.cs +++ b/RDMSharp/RDM/PayloadObject/RDMPersonalityId.cs @@ -1,15 +1,18 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DMX_PERSONALITY_ID, Command.ECommandDublicte.GetResponse)] public class RDMPersonalityId : AbstractRDMPayloadObject, IRDMPayloadObjectIndex { + [DataTreeObjectConstructor] public RDMPersonalityId( - byte personalityId = 0, - ushort majorPersonalityId = 0, - ushort minorPersonalityId = 0) + [DataTreeObjectParameter("personality")] byte personalityId = 0, + [DataTreeObjectParameter("major_id")] ushort majorPersonalityId = 0, + [DataTreeObjectParameter("minor_id")] ushort minorPersonalityId = 0) { this.PersonalityId = personalityId; this.MinorPersonalityId = majorPersonalityId; diff --git a/RDMSharp/RDM/PayloadObject/RDMPresetInfo.cs b/RDMSharp/RDM/PayloadObject/RDMPresetInfo.cs index 087910c..8c210ff 100644 --- a/RDMSharp/RDM/PayloadObject/RDMPresetInfo.cs +++ b/RDMSharp/RDM/PayloadObject/RDMPresetInfo.cs @@ -1,30 +1,34 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.PRESET_INFO, Command.ECommandDublicte.GetResponse)] public class RDMPresetInfo : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMPresetInfo( - bool levelFieldSupported = false, - bool presetSequenceSupported = false, - bool splitTimesSupported = false, - bool dmx512FailInfiniteDelayTimeSupported = false, - bool dmx512FailInfiniteHoldTimeSupported = false, - bool startupInfiniteHoldTimeSupported = false, - ushort maximumSceneNumber = 0, - ushort minimumPresetFadeTimeSupported = 0, - ushort maximumPresetFadeTimeSupported = 0, - ushort minimumPresetWaitTimeSupported = 0, - ushort maximumPresetWaitTimeSupported = 0, - ushort? minimumDMX512FailDelayTimeSupported = null, - ushort? maximumDMX512FailDelayTimeSupported = null, - ushort? minimumDMX512FailDelayHoldSupported = null, - ushort? maximumDMX512FailDelayHoldSupported = null, - ushort? minimumStartupDelayTimeSupported = null, - ushort? maximumStartupDelayTimeSupported = null, - ushort? minimumStartupDelayHoldSupported = null, - ushort? maximumStartupDelayHoldSupported = null) + [DataTreeObjectParameter("level_field_supported")] bool levelFieldSupported = false, + [DataTreeObjectParameter("preset_sequence_supported")] bool presetSequenceSupported = false, + [DataTreeObjectParameter("split_times_supported")] bool splitTimesSupported = false, + [DataTreeObjectParameter("dmx_fail_infinite_delay_time_supported")] bool dmx512FailInfiniteDelayTimeSupported = false, + [DataTreeObjectParameter("dmx_fail_infinite_hold_time_supported")] bool dmx512FailInfiniteHoldTimeSupported = false, + [DataTreeObjectParameter("startup_infinite_hold_time_supported")] bool startupInfiniteHoldTimeSupported = false, + [DataTreeObjectParameter("max_scene_number")] ushort maximumSceneNumber = 0, + [DataTreeObjectParameter("preset_min_fade_time")] ushort minimumPresetFadeTimeSupported = 0, + [DataTreeObjectParameter("preset_max_fade_time")] ushort maximumPresetFadeTimeSupported = 0, + [DataTreeObjectParameter("preset_min_wait_time")] ushort minimumPresetWaitTimeSupported = 0, + [DataTreeObjectParameter("preset_max_wait_time")] ushort maximumPresetWaitTimeSupported = 0, + [DataTreeObjectParameter("dmx_fail_min_delay_time")] ushort? minimumDMX512FailDelayTimeSupported = null, + [DataTreeObjectParameter("dmx_fail_max_delay_time")] ushort? maximumDMX512FailDelayTimeSupported = null, + [DataTreeObjectParameter("dmx_fail_min_hold_time")] ushort? minimumDMX512FailDelayHoldSupported = null, + [DataTreeObjectParameter("dmx_fail_max_hold_time")] ushort? maximumDMX512FailDelayHoldSupported = null, + [DataTreeObjectParameter("startup_min_delay_time")] ushort? minimumStartupDelayTimeSupported = null, + [DataTreeObjectParameter("startup_max_delay_time")] ushort? maximumStartupDelayTimeSupported = null, + [DataTreeObjectParameter("startup_min_hold_time")] ushort? minimumStartupDelayHoldSupported = null, + [DataTreeObjectParameter("startup_max_hold_time")] ushort? maximumStartupDelayHoldSupported = null) { this.LevelFieldSupported = levelFieldSupported; this.PresetSequenceSupported = presetSequenceSupported; diff --git a/RDMSharp/RDM/PayloadObject/RDMPresetPlayback.cs b/RDMSharp/RDM/PayloadObject/RDMPresetPlayback.cs index c5fbbca..51095a9 100644 --- a/RDMSharp/RDM/PayloadObject/RDMPresetPlayback.cs +++ b/RDMSharp/RDM/PayloadObject/RDMPresetPlayback.cs @@ -1,13 +1,18 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.PRESET_PLAYBACK, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.PRESET_PLAYBACK, Command.ECommandDublicte.SetRequest)] public class RDMPresetPlayback : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMPresetPlayback( - ushort mode = 0, - byte level = 0) + [DataTreeObjectParameter("mode")] ushort mode = 0, + [DataTreeObjectParameter("level")] byte level = 0) { this.Mode = mode; this.Level = level; diff --git a/RDMSharp/RDM/PayloadObject/RDMPresetStatus.cs b/RDMSharp/RDM/PayloadObject/RDMPresetStatus.cs index bd75149..a373d94 100644 --- a/RDMSharp/RDM/PayloadObject/RDMPresetStatus.cs +++ b/RDMSharp/RDM/PayloadObject/RDMPresetStatus.cs @@ -1,8 +1,13 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.PRESET_STATUS, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.PRESET_STATUS, Command.ECommandDublicte.SetRequest)] + [DataTreeObject(ERDM_Parameter.CAPTURE_PRESET, Command.ECommandDublicte.SetRequest)] public class RDMPresetStatus : AbstractRDMPayloadObject { public RDMPresetStatus( @@ -19,6 +24,17 @@ public RDMPresetStatus( this.Programmed = programmed; } + [DataTreeObjectConstructor] + public RDMPresetStatus( + [DataTreeObjectParameter("scene_num")] ushort sceneId, + [DataTreeObjectParameter("up_fade_time")] ushort upFadeTime, + [DataTreeObjectParameter("down_fade_time")] ushort downFadeTime, + [DataTreeObjectParameter("wait_time")] ushort waitTime, + [DataTreeObjectParameter("programmed")] byte programmed) + : this(sceneId, upFadeTime, downFadeTime, waitTime, (ERDM_PresetProgrammed)programmed) + { + } + public ushort SceneId { get; private set; } /// /// Tenths of a second diff --git a/RDMSharp/RDM/PayloadObject/RDMProxiedDeviceCount.cs b/RDMSharp/RDM/PayloadObject/RDMProxiedDeviceCount.cs index cf5537f..c9b7665 100644 --- a/RDMSharp/RDM/PayloadObject/RDMProxiedDeviceCount.cs +++ b/RDMSharp/RDM/PayloadObject/RDMProxiedDeviceCount.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.PROXIED_DEVICES_COUNT, Command.ECommandDublicte.GetResponse)] public class RDMProxiedDeviceCount : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMProxiedDeviceCount( - ushort deviceCount = 0, - bool listChange = false) + [DataTreeObjectParameter("device_count")] ushort deviceCount = 0, + [DataTreeObjectParameter("list_change")] bool listChange = false) { this.DeviceCount = deviceCount; this.ListChange = listChange; diff --git a/RDMSharp/RDM/PayloadObject/RDMProxiedDevices.cs b/RDMSharp/RDM/PayloadObject/RDMProxiedDevices.cs index 7a48484..b78be32 100644 --- a/RDMSharp/RDM/PayloadObject/RDMProxiedDevices.cs +++ b/RDMSharp/RDM/PayloadObject/RDMProxiedDevices.cs @@ -1,12 +1,16 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; using System.Text; namespace RDMSharp { + //[DataTreeObject(ERDM_Parameter.PROXIED_DEVICES, Command.ECommandDublicte.GetResponse, path: "device_uids")] Dont use this because its an Arrya and this is handled faster public class RDMProxiedDevices : AbstractRDMPayloadObject { - public RDMProxiedDevices(params UID[] devices) + [DataTreeObjectConstructor] + public RDMProxiedDevices(/*[DataTreeObjectParameter("device_uid", true)]*/ params UID[] devices) { this.Devices = devices; } diff --git a/RDMSharp/RDM/PayloadObject/RDMRealTimeClock.cs b/RDMSharp/RDM/PayloadObject/RDMRealTimeClock.cs index 80c3963..0161580 100644 --- a/RDMSharp/RDM/PayloadObject/RDMRealTimeClock.cs +++ b/RDMSharp/RDM/PayloadObject/RDMRealTimeClock.cs @@ -1,17 +1,22 @@ -using System; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System; using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.REAL_TIME_CLOCK, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.REAL_TIME_CLOCK, Command.ECommandDublicte.SetRequest)] public class RDMRealTimeClock : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMRealTimeClock( - ushort year = 2003, - byte month = 1, - byte day = 1, - byte hour = 0, - byte minute = 0, - byte second = 0) + [DataTreeObjectParameter("year")] ushort year = 2003, + [DataTreeObjectParameter("month")] byte month = 1, + [DataTreeObjectParameter("day")] byte day = 1, + [DataTreeObjectParameter("hour")] byte hour = 0, + [DataTreeObjectParameter("minute")] byte minute = 0, + [DataTreeObjectParameter("second")] byte second = 0) { if (year < 2003) throw new ArgumentOutOfRangeException($"{nameof(year)} shold be a value between 2003 and 65535 but is {year}"); diff --git a/RDMSharp/RDM/PayloadObject/RDMSelfTestDescription.cs b/RDMSharp/RDM/PayloadObject/RDMSelfTestDescription.cs index 7a18323..5882723 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSelfTestDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSelfTestDescription.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.SELF_TEST_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMSelfTestDescription : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMSelfTestDescription( - byte selfTestRequester = 0, - string description = "") + [DataTreeObjectParameter("self_test_num")] byte selfTestRequester = 0, + [DataTreeObjectParameter("label")] string description = "") { this.SelfTestRequester = selfTestRequester; diff --git a/RDMSharp/RDM/PayloadObject/RDMSensorDefinition.cs b/RDMSharp/RDM/PayloadObject/RDMSensorDefinition.cs index ac43653..99affb1 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSensorDefinition.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSensorDefinition.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.SENSOR_DEFINITION, Command.ECommandDublicte.GetResponse)] public class RDMSensorDefinition : AbstractRDMPayloadObject, IRDMPayloadObjectIndex { public RDMSensorDefinition( @@ -36,6 +39,33 @@ public RDMSensorDefinition( description = description.Substring(0, 32); this.Description = description; + } + + [DataTreeObjectConstructor] + public RDMSensorDefinition( + [DataTreeObjectParameter("sensor")] byte sensorId, + [DataTreeObjectParameter("type")] byte type, + [DataTreeObjectParameter("unit")] byte unit, + [DataTreeObjectParameter("unit_prefix")] byte prefix, + [DataTreeObjectParameter("range_min_value")] short rangeMinimum, + [DataTreeObjectParameter("range_max_value")] short rangeMaximum, + [DataTreeObjectParameter("normal_min_value")] short normalMinimum, + [DataTreeObjectParameter("normal_max_value")] short normalMaximum, + [DataTreeObjectParameter("recorded_value_support/recorded_value_supported")] bool recordedValueSupported, + [DataTreeObjectParameter("recorded_value_support/low_high_detected_values_supported")] bool lowestHighestValueSupported, + [DataTreeObjectParameter("description")] string description) + : this(sensorId, + (ERDM_SensorType)type, + (ERDM_SensorUnit)unit, + (ERDM_UnitPrefix)prefix, + rangeMinimum, + rangeMaximum, + normalMinimum, + normalMaximum, + lowestHighestValueSupported, + recordedValueSupported, + description) + { } public byte SensorId { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/RDMSensorTypeCustomDefine.cs b/RDMSharp/RDM/PayloadObject/RDMSensorTypeCustomDefine.cs index cbb7aa4..b17a775 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSensorTypeCustomDefine.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSensorTypeCustomDefine.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.SENSOR_TYPE_CUSTOM, Command.ECommandDublicte.GetResponse)] public class RDMSensorTypeCustomDefine : AbstractRDMPayloadObject, IRDMPayloadObjectIndex { + [DataTreeObjectConstructor] public RDMSensorTypeCustomDefine( - byte id, - string label) + [DataTreeObjectParameter("sensor_type")] byte id, + [DataTreeObjectParameter("label")] string label) { this.Id = id; this.Label = label; diff --git a/RDMSharp/RDM/PayloadObject/RDMSensorUnitCustomDefine.cs b/RDMSharp/RDM/PayloadObject/RDMSensorUnitCustomDefine.cs index b4ccd48..6a628e3 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSensorUnitCustomDefine.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSensorUnitCustomDefine.cs @@ -1,13 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.SENSOR_UNIT_CUSTOM, Command.ECommandDublicte.GetResponse)] public class RDMSensorUnitCustomDefine : AbstractRDMPayloadObject, IRDMPayloadObjectIndex { + [DataTreeObjectConstructor] public RDMSensorUnitCustomDefine( - byte id, - string label) + [DataTreeObjectParameter("sensor_unit")] byte id, + [DataTreeObjectParameter("label")] string label) { this.Id = id; this.Label = label; diff --git a/RDMSharp/RDM/PayloadObject/RDMSensorValue.cs b/RDMSharp/RDM/PayloadObject/RDMSensorValue.cs index 473a7f9..b115545 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSensorValue.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSensorValue.cs @@ -1,16 +1,21 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.SENSOR_VALUE, Command.ECommandDublicte.GetResponse)] + [DataTreeObject(ERDM_Parameter.SENSOR_VALUE, Command.ECommandDublicte.SetResponse)] public class RDMSensorValue : AbstractRDMPayloadObject, IRDMPayloadObjectIndex - { + { + [DataTreeObjectConstructor] public RDMSensorValue( - byte sensorId = 0, - short presentvalue = 0, - short lowestValue = 0, - short highestValue = 0, - short recordedValue = 0) + [DataTreeObjectParameter("sensor")] byte sensorId = 0, + [DataTreeObjectParameter("value")] short presentvalue = 0, + [DataTreeObjectParameter("lowest_detected")] short lowestValue = 0, + [DataTreeObjectParameter("highest_detected")] short highestValue = 0, + [DataTreeObjectParameter("recorded_value")] short recordedValue = 0) { this.SensorId = sensorId; this.PresentValue = presentvalue; @@ -19,10 +24,19 @@ public RDMSensorValue( this.RecordedValue = recordedValue; } + [DataTreeObjectProperty("sensor", 0)] public byte SensorId { get; private set; } + + [DataTreeObjectProperty("value", 1)] public short PresentValue { get; private set; } + + [DataTreeObjectProperty("lowest_detected", 2)] public short LowestValue { get; private set; } + + [DataTreeObjectProperty("highest_detected", 3)] public short HighestValue { get; private set; } + + [DataTreeObjectProperty("recorded_value", 4)] public short RecordedValue { get; private set; } public object MinIndex => (byte)0; diff --git a/RDMSharp/RDM/PayloadObject/RDMSlotDescription.cs b/RDMSharp/RDM/PayloadObject/RDMSlotDescription.cs index 400da5a..0af3634 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSlotDescription.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSlotDescription.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.SLOT_DESCRIPTION, Command.ECommandDublicte.GetResponse)] public class RDMSlotDescription : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public RDMSlotDescription( - ushort slotId = 0, - string description = "") + [DataTreeObjectParameter("slot")] ushort slotId = 0, + [DataTreeObjectParameter("description")] string description = "") { this.SlotId = slotId; @@ -19,8 +23,12 @@ public RDMSlotDescription( this.Description = description; } + [DataTreeObjectProperty("slot", 0)] public ushort SlotId { get; private set; } + + [DataTreeObjectProperty("description", 1)] public string Description { get; private set; } + public const int PDL_MIN = 2; public const int PDL_MAX = PDL_MIN + 32; diff --git a/RDMSharp/RDM/PayloadObject/RDMSlotInfo.cs b/RDMSharp/RDM/PayloadObject/RDMSlotInfo.cs index 51797b4..7dc28ea 100644 --- a/RDMSharp/RDM/PayloadObject/RDMSlotInfo.cs +++ b/RDMSharp/RDM/PayloadObject/RDMSlotInfo.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.SLOT_INFO, Command.ECommandDublicte.GetResponse, true, "slots")] public class RDMSlotInfo : AbstractRDMPayloadObject { public RDMSlotInfo( @@ -15,8 +18,22 @@ public RDMSlotInfo( this.SlotLabelId = slotLabelId; } + [DataTreeObjectConstructor] + public RDMSlotInfo( + [DataTreeObjectParameter("id")] ushort slotOffset, + [DataTreeObjectParameter("type")] byte slotType, + [DataTreeObjectParameter("label_id")] byte slotLabelId) + : this(slotOffset, (ERDM_SlotType)slotType, (ERDM_SlotCategory)slotLabelId) + { + } + + [DataTreeObjectProperty("id", 0)] public ushort SlotOffset { get; private set; } + + [DataTreeObjectProperty("type", 1)] public ERDM_SlotType SlotType { get; private set; } + + [DataTreeObjectProperty("label_id", 3)] public ERDM_SlotCategory SlotLabelId { get; private set; } public const int PDL = 5; diff --git a/RDMSharp/RDM/PayloadObject/RDMStatusMessage.cs b/RDMSharp/RDM/PayloadObject/RDMStatusMessage.cs index dfa997d..3674b64 100644 --- a/RDMSharp/RDM/PayloadObject/RDMStatusMessage.cs +++ b/RDMSharp/RDM/PayloadObject/RDMStatusMessage.cs @@ -1,8 +1,11 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Text; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.STATUS_MESSAGES, Command.ECommandDublicte.GetResponse)] public class RDMStatusMessage : AbstractRDMPayloadObject { public RDMStatusMessage( @@ -19,6 +22,17 @@ public RDMStatusMessage( this.DataValue2 = dataValue2; } + [DataTreeObjectConstructor] + public RDMStatusMessage( + [DataTreeObjectParameter("slots/subdevice_id")] ushort subDeviceId, + [DataTreeObjectParameter("slots/status_type")] byte statusType, + [DataTreeObjectParameter("slots/status_message_id")] byte statusMessage, + [DataTreeObjectParameter("slots/data_value_1")] short dataValue1, + [DataTreeObjectParameter("slots/data_value_2")] short dataValue2) + : this(subDeviceId, (ERDM_Status)statusType, (ERDM_StatusMessage)statusMessage, dataValue1, dataValue2) + { + } + public ushort SubDeviceId { get; private set; } public ERDM_Status StatusType { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/SetDiscoveryStateRequest.cs b/RDMSharp/RDM/PayloadObject/SetDiscoveryStateRequest.cs index afc7c26..9f92081 100644 --- a/RDMSharp/RDM/PayloadObject/SetDiscoveryStateRequest.cs +++ b/RDMSharp/RDM/PayloadObject/SetDiscoveryStateRequest.cs @@ -1,16 +1,26 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.DISCOVERY_STATE, Command.ECommandDublicte.SetResponse)] public class SetDiscoveryStateRequest : AbstractRDMPayloadObject { public SetDiscoveryStateRequest( - ushort endpointId = default, - ERDM_DiscoveryState discoveryState = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("state")] ERDM_DiscoveryState discoveryState = default) { this.EndpointId = endpointId; this.DiscoveryState = discoveryState; } + [DataTreeObjectConstructor] + public SetDiscoveryStateRequest( + [DataTreeObjectParameter("endpoint_id")] ushort endpointId, + [DataTreeObjectParameter("state")] byte discoveryState) + : this(endpointId, (ERDM_DiscoveryState)discoveryState) + { + } public ushort EndpointId { get; private set; } public ERDM_DiscoveryState DiscoveryState { get; private set; } diff --git a/RDMSharp/RDM/PayloadObject/SetEndpointTimingRequest.cs b/RDMSharp/RDM/PayloadObject/SetEndpointTimingRequest.cs index e8342b7..8b3130c 100644 --- a/RDMSharp/RDM/PayloadObject/SetEndpointTimingRequest.cs +++ b/RDMSharp/RDM/PayloadObject/SetEndpointTimingRequest.cs @@ -1,12 +1,17 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.ENDPOINT_TIMING, Command.ECommandDublicte.SetRequest)] + public class SetEndpointTimingRequest : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public SetEndpointTimingRequest( - ushort endpointId = default, - byte timingId = default) + [DataTreeObjectParameter("endpoint_id")] ushort endpointId = default, + [DataTreeObjectParameter("setting")] byte timingId = default) { this.EndpointId = endpointId; this.TimingId = timingId; diff --git a/RDMSharp/RDM/PayloadObject/SetLockPinRequest.cs b/RDMSharp/RDM/PayloadObject/SetLockPinRequest.cs index 28eb461..62304f9 100644 --- a/RDMSharp/RDM/PayloadObject/SetLockPinRequest.cs +++ b/RDMSharp/RDM/PayloadObject/SetLockPinRequest.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.LOCK_PIN, Command.ECommandDublicte.SetRequest)] public class SetLockPinRequest : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public SetLockPinRequest( - ushort newPinCode = 0, - ushort currentPinCode = 0) + [DataTreeObjectParameter("new_pin_code")] ushort newPinCode = 0, + [DataTreeObjectParameter("current_pin_code")] ushort currentPinCode = 0) { this.NewPinCode = newPinCode; this.CurrentPinCode = currentPinCode; diff --git a/RDMSharp/RDM/PayloadObject/SetLockStateRequest.cs b/RDMSharp/RDM/PayloadObject/SetLockStateRequest.cs index 91acbf6..c814540 100644 --- a/RDMSharp/RDM/PayloadObject/SetLockStateRequest.cs +++ b/RDMSharp/RDM/PayloadObject/SetLockStateRequest.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; namespace RDMSharp { + [DataTreeObject(ERDM_Parameter.LOCK_STATE, Command.ECommandDublicte.SetRequest)] public class SetLockStateRequest : AbstractRDMPayloadObject { + [DataTreeObjectConstructor] public SetLockStateRequest( - ushort pinCode = 0, - byte lockStateId = 0) + [DataTreeObjectParameter("pin_code")] ushort pinCode = 0, + [DataTreeObjectParameter("state")] byte lockStateId = 0) { this.PinCode = pinCode; this.LockStateId = lockStateId; diff --git a/RDMSharp/RDM/PayloadObject/TCPCommsEntry.cs b/RDMSharp/RDM/PayloadObject/TCPCommsEntry.cs index 7926668..7582513 100644 --- a/RDMSharp/RDM/PayloadObject/TCPCommsEntry.cs +++ b/RDMSharp/RDM/PayloadObject/TCPCommsEntry.cs @@ -1,18 +1,22 @@ -using System.Collections.Generic; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; namespace RDMSharp -{ +{ + [DataTreeObject(ERDM_Parameter.TCP_COMMS_STATUS, Command.ECommandDublicte.GetResponse)] public class TCPCommsEntry : AbstractRDMPayloadObject - { + { + [DataTreeObjectConstructor] public TCPCommsEntry( - string scopeString = default, - IPAddress brokerAddress = default, - ushort brokerPort = default, - ushort unhealthyTCPEvents = default) + [DataTreeObjectParameter("scopeString")] string scopeString = default, + [DataTreeObjectParameter("brokerAddress")] IPAddress brokerAddress = default, + [DataTreeObjectParameter("brokerPort")] ushort brokerPort = default, + [DataTreeObjectParameter("unhealthyTCPEvents")] ushort unhealthyTCPEvents = default) { if (string.IsNullOrWhiteSpace(scopeString)) diff --git a/RDMSharp/RDM/PeerToPeerProcess.cs b/RDMSharp/RDM/PeerToPeerProcess.cs new file mode 100644 index 0000000..7ae6b39 --- /dev/null +++ b/RDMSharp/RDM/PeerToPeerProcess.cs @@ -0,0 +1,120 @@ +using RDMSharp.Metadata; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using static RDMSharp.Metadata.JSON.Command; + +namespace RDMSharp +{ + internal class PeerToPeerProcess + { + internal enum EPeerToPeerProcessState + { + Waiting, + Running, + Finished, + Failed + } + public readonly ERDM_Command Command; + public readonly UID UID; + public readonly SubDevice SubDevice; + public readonly ParameterBag ParameterBag; + public readonly DataTreeBranch RequestPayloadObject; + public DataTreeBranch ResponsePayloadObject { get; private set; } = DataTreeBranch.Unset; + + public MetadataJSONObjectDefine Define { get; private set; } + public EPeerToPeerProcessState State { get; private set; } = EPeerToPeerProcessState.Waiting; + + public Exception Exception { get; private set; } + + private RDMMessage request = null; + private RDMMessage response = null; + public PeerToPeerProcess(ERDM_Command command, UID uid, SubDevice subDevice, ParameterBag parameterBag, DataTreeBranch? payloadObject = null) + { + if (command != ERDM_Command.GET_COMMAND) + if (command != ERDM_Command.SET_COMMAND) + throw new ArgumentException($"{nameof(command)} should be {ERDM_Command.GET_COMMAND} or {ERDM_Command.SET_COMMAND}"); + + Command = command; + UID = uid; + SubDevice = subDevice; + ParameterBag = parameterBag; + RequestPayloadObject = payloadObject ?? DataTreeBranch.Unset; + + Define = MetadataFactory.GetDefine(ParameterBag); + } + + public async Task Run(AsyncRDMRequestHelper asyncRDMRequestHelper) + { + await run(asyncRDMRequestHelper); + } + + private async Task run(AsyncRDMRequestHelper asyncRDMRequestHelper) + { + try + { + if (State != EPeerToPeerProcessState.Waiting) + return; + + if (asyncRDMRequestHelper == null) + throw new ArgumentNullException(nameof(asyncRDMRequestHelper)); + + State = EPeerToPeerProcessState.Running; + + ECommandDublicte commandRequest = ECommandDublicte.GetRequest; + if (Command == ERDM_Command.SET_COMMAND) + commandRequest = ECommandDublicte.SetRequest; + + ECommandDublicte commandResponse = ECommandDublicte.GetResponse; + if (Command == ERDM_Command.SET_COMMAND) + commandResponse = ECommandDublicte.SetResponse; + + byte[] parameterData = MetadataFactory.ParsePayloadToData(Define, commandRequest, RequestPayloadObject); + request = new RDMMessage() + { + Command = Command, + DestUID = UID, + SubDevice = SubDevice, + Parameter = ParameterBag.PID, + ParameterData = parameterData + }; + List bytes = new List(); + while (State == EPeerToPeerProcessState.Running) + { + var responseResult = await asyncRDMRequestHelper.RequestMessage(request); + if (!responseResult.Success) + { + State = EPeerToPeerProcessState.Failed; + return; + } + response = responseResult.Response; + if (response.ResponseType == ERDM_ResponseType.ACK_TIMER && response.Value is AcknowledgeTimer timer) + { + await Task.Delay(timer.EstimidatedResponseTime); + request.Parameter = ERDM_Parameter.QUEUED_MESSAGE; + //Send Message on next loop + continue; + } + bytes.AddRange(response.ParameterData); + if (response.ResponseType == ERDM_ResponseType.ACK) + { + ResponsePayloadObject = MetadataFactory.ParseDataToPayload(Define, commandResponse, bytes.ToArray()); + State = EPeerToPeerProcessState.Finished; + return; + } + if (response.ResponseType == ERDM_ResponseType.ACK_OVERFLOW) + { + //Do nothing else send another Request + //Send Message on next loop + continue; + } + } + } + catch (Exception e) + { + this.Exception = e; + State = EPeerToPeerProcessState.Failed; + } + } + } +} \ No newline at end of file diff --git a/RDMSharp/RDM/Tools.cs b/RDMSharp/RDM/Tools.cs index 4214ccc..a5f934c 100644 --- a/RDMSharp/RDM/Tools.cs +++ b/RDMSharp/RDM/Tools.cs @@ -7,10 +7,55 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Reflection; using System.Text; +using static RDMSharp.Metadata.JSON.Command; namespace RDMSharp { + public static class Constants + { + public static readonly ERDM_Parameter[] BLUEPRINT_MODEL_PARAMETERS = new ERDM_Parameter[] + { + ERDM_Parameter.PARAMETER_DESCRIPTION, + ERDM_Parameter.MANUFACTURER_LABEL, + ERDM_Parameter.MANUFACTURER_URL, + ERDM_Parameter.DEVICE_MODEL_DESCRIPTION, + ERDM_Parameter.PRODUCT_DETAIL_ID_LIST, + ERDM_Parameter.PRODUCT_URL, + ERDM_Parameter.FIRMWARE_URL, + + ERDM_Parameter.METADATA_JSON_URL, + ERDM_Parameter.METADATA_JSON, + ERDM_Parameter.METADATA_PARAMETER_VERSION, + + ERDM_Parameter.DMX_PERSONALITY_DESCRIPTION, + ERDM_Parameter.DMX_PERSONALITY_ID, + + ERDM_Parameter.SENSOR_DEFINITION, + ERDM_Parameter.SENSOR_VALUE, + ERDM_Parameter.SENSOR_TYPE_CUSTOM, + ERDM_Parameter.SENSOR_UNIT_CUSTOM, + + ERDM_Parameter.CURVE_DESCRIPTION, + ERDM_Parameter.DIMMER_INFO, + ERDM_Parameter.MODULATION_FREQUENCY_DESCRIPTION, + ERDM_Parameter.OUTPUT_RESPONSE_TIME_DESCRIPTION, + ERDM_Parameter.LOCK_STATE_DESCRIPTION, + + ERDM_Parameter.SELF_TEST_DESCRIPTION, + ERDM_Parameter.STATUS_ID_DESCRIPTION, + ERDM_Parameter.LANGUAGE_CAPABILITIES, + ERDM_Parameter.SOFTWARE_VERSION_LABEL, + }; + + public static readonly ERDM_Parameter[] BLUEPRINT_MODEL_PERSONALITY_PARAMETERS = new ERDM_Parameter[] + { + ERDM_Parameter.SLOT_DESCRIPTION, + ERDM_Parameter.SLOT_INFO, + ERDM_Parameter.DEFAULT_SLOT_VALUE + }; + } public static class Tools { public static int GenerateHashCode(this IEnumerable enumerable) @@ -82,6 +127,13 @@ public static TAttribute GetAttribute(this Enum value) .GetCustomAttributes(false) .OfType() .SingleOrDefault(); + } + public static List FindClassesWithAttribute() where TAttribute : Attribute + { + Assembly assembly = Assembly.GetExecutingAssembly(); + return assembly.GetTypes() + .Where(t => (t.IsClass || t.IsEnum) && t.GetCustomAttributes().Any(a => a is TAttribute)) + .ToList(); } public static byte[] ValueToData(params bool[] bits) @@ -192,8 +244,14 @@ public static byte[] ValueToData(object value, int trim = 32) case long @long: return DoEightByte((ulong)@long); case ulong @ulong: - return DoEightByte(@ulong); - + return DoEightByte(@ulong); +#if NET7_0_OR_GREATER + case Int128 @long: + return DoSixteenByte((UInt128)@long); + case UInt128 @ulong: + return DoSixteenByte(@ulong); +#endif + case string @string: if (trim >= 1) if (@string.Length > trim) @@ -213,18 +271,22 @@ public static byte[] ValueToData(object value, int trim = 32) byte[] DoOneByte(byte b) => new byte[] { b }; byte[] DoTwoByte(ushort s) => new byte[] { (byte)(s >> 8), (byte)s }; byte[] DoFourByte(uint i) => new byte[] { (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i }; - byte[] DoEightByte(ulong i) => new byte[] { (byte)(i >> 56), (byte)(i >> 48), (byte)(i >> 40), (byte)(i >> 32), (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i }; + byte[] DoEightByte(ulong i) => new byte[] { (byte)(i >> 56), (byte)(i >> 48), (byte)(i >> 40), (byte)(i >> 32), (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i }; +#if NET7_0_OR_GREATER + byte[] DoSixteenByte(UInt128 i) => new byte[] { (byte)(i >> 120), (byte)(i >> 112), (byte)(i >> 104), (byte)(i >> 96), (byte)(i >> 88), (byte)(i >> 80), (byte)(i >> 72), (byte)(i >> 64), (byte)(i >> 56), (byte)(i >> 48), (byte)(i >> 40), (byte)(i >> 32), (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte)i }; +#endif } - - public static byte DataToByte(ref byte[] data) + + public static byte DataToByte(ref byte[] data) { const int length = 1; if (data.Length < length) throw new IndexOutOfRangeException(); - byte res = (byte)data[0]; + byte result = (byte)data[0]; + data = data.Skip(length).ToArray(); - return res; + return result; } public static sbyte DataToSByte(ref byte[] data) { @@ -232,9 +294,10 @@ public static sbyte DataToSByte(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - sbyte res = (sbyte)data[0]; + sbyte result = (sbyte)data[0]; + data = data.Skip(length).ToArray(); - return res; + return result; } public static short DataToShort(ref byte[] data) { @@ -242,9 +305,10 @@ public static short DataToShort(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - short res = (short)((data[0] << 8) | data[1]); + short result = (short)((data[0] << 8) | data[1]); + data = data.Skip(length).ToArray(); - return res; + return result; } public static ushort DataToUShort(ref byte[] data) { @@ -252,9 +316,10 @@ public static ushort DataToUShort(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - ushort res = (ushort)((data[0] << 8) | data[1]); + ushort result = (ushort)((data[0] << 8) | data[1]); + data = data.Skip(length).ToArray(); - return res; + return result; } public static int DataToInt(ref byte[] data) { @@ -262,9 +327,13 @@ public static int DataToInt(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - int res = (int)((data[0] << 24) | (data[1] << 16) | data[2] << 8 | data[3]); + int result = (int)data[0] << 24 | + (int)data[1] << 16 | + (int)data[2] << 8 | + (int)data[3]; + data = data.Skip(length).ToArray(); - return res; + return result; } public static uint DataToUInt(ref byte[] data) { @@ -272,9 +341,13 @@ public static uint DataToUInt(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - uint res = (uint)((data[0] << 24) | (data[1] << 16) | data[2] << 8 | data[3]); + uint result = (uint)data[0] << 24 | + (uint)data[1] << 16 | + (uint)data[2] << 8 | + (uint)data[3]; + data = data.Skip(length).ToArray(); - return res; + return result; } public static long DataToLong(ref byte[] data) { @@ -282,9 +355,17 @@ public static long DataToLong(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - long res = (long)((((long)data[0]) << 56) | (((long)data[1]) << 48) | (((long)data[2]) << 40) | (((long)data[3]) << 32) | (((long)data[4]) << 24) | (((long)data[5]) << 16) | ((long)data[6]) << 8 | ((long)data[7])); + long result = (long)data[0] << 56 | + (long)data[1] << 48 | + (long)data[2] << 40 | + (long)data[3] << 32 | + (long)data[4] << 24 | + (long)data[5] << 16 | + (long)data[6] << 8 | + (long)data[7]; + data = data.Skip(length).ToArray(); - return res; + return result; } public static ulong DataToULong(ref byte[] data) { @@ -292,10 +373,72 @@ public static ulong DataToULong(ref byte[] data) if (data.Length < length) throw new IndexOutOfRangeException(); - ulong res = (ulong)((((ulong)data[0]) << 56) | (((ulong)data[1]) << 48) | (((ulong)data[2]) << 40) | (((ulong)data[3]) << 32) | (((ulong)data[4]) << 24) | (((ulong)data[5]) << 16) | ((ulong)data[6]) << 8 | ((ulong)data[7])); + ulong result = (ulong)data[0] << 56 | + (ulong)data[1] << 48 | + (ulong)data[2] << 40 | + (ulong)data[3] << 32 | + (ulong)data[4] << 24 | + (ulong)data[5] << 16 | + (ulong)data[6] << 8 | + (ulong)data[7]; + data = data.Skip(length).ToArray(); - return res; - } + return result; + } +#if NET7_0_OR_GREATER + public static Int128 DataToInt128(ref byte[] data) + { + const int length = 16; + if (data.Length < length) + throw new IndexOutOfRangeException(); + + Int128 result = (Int128)data[0] << 120 | + (Int128)data[1] << 112 | + (Int128)data[2] << 104 | + (Int128)data[3] << 96 | + (Int128)data[4] << 88 | + (Int128)data[5] << 80 | + (Int128)data[6] << 72 | + (Int128)data[7] << 64 | + (Int128)data[8] << 56 | + (Int128)data[9] << 48 | + (Int128)data[10] << 40 | + (Int128)data[11] << 32 | + (Int128)data[12] << 24 | + (Int128)data[13] << 16 | + (Int128)data[14] << 8 | + (Int128)data[15]; + + data = data.Skip(length).ToArray(); + return result; + } + public static UInt128 DataToUInt128(ref byte[] data) + { + const int length = 16; + if (data.Length < length) + throw new IndexOutOfRangeException(); + + UInt128 result = (UInt128)data[0] << 120 | + (UInt128)data[1] << 112 | + (UInt128)data[2] << 104 | + (UInt128)data[3] << 96 | + (UInt128)data[4] << 88 | + (UInt128)data[5] << 80 | + (UInt128)data[6] << 72 | + (UInt128)data[7] << 64 | + (UInt128)data[8] << 56 | + (UInt128)data[9] << 48 | + (UInt128)data[10] << 40 | + (UInt128)data[11] << 32 | + (UInt128)data[12] << 24 | + (UInt128)data[13] << 16 | + (UInt128)data[14] << 8 | + (UInt128)data[15]; + + data = data.Skip(length).ToArray(); + return result; + } +#endif public static UID DataToRDMUID(ref byte[] data) { const int length = 6; @@ -430,5 +573,20 @@ public static IReadOnlyDictionary AsReadOnly(this IDictionary return new ReadOnlyDictionary(source); } + public static ECommandDublicte ConvertCommandDublicteToCommand(ERDM_Command v) + { + switch (v) + { + case ERDM_Command.GET_COMMAND: + return ECommandDublicte.GetRequest; + case ERDM_Command.GET_COMMAND_RESPONSE: + return ECommandDublicte.GetResponse; + case ERDM_Command.SET_COMMAND: + return ECommandDublicte.SetRequest; + case ERDM_Command.SET_COMMAND_RESPONSE: + return ECommandDublicte.SetResponse; + } + throw new NotSupportedException(); + } } } diff --git a/RDMSharp/RDMSharp.csproj b/RDMSharp/RDMSharp.csproj index 14b7403..1c91d08 100644 --- a/RDMSharp/RDMSharp.csproj +++ b/RDMSharp/RDMSharp.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net6.0;net7.0;net8.0 + net6.0;net7.0;net8.0 LICENSE 0.0.13 https://github.com/DMXControl/RDMSharp @@ -32,6 +32,11 @@ - + + + + + + diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_ID.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_ID.json new file mode 100644 index 0000000..9d08e03 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_ID.json @@ -0,0 +1,14 @@ +{ + "name": "BOOT_SOFTWARE_VERSION_ID", + "manufacturer_id": 0, + "pid": 193, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "boot_software_version_id", + "type": "uint32" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_LABEL.json new file mode 100644 index 0000000..74a51c2 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/BOOT_SOFTWARE_VERSION_LABEL.json @@ -0,0 +1,16 @@ +{ + "name": "BOOT_SOFTWARE_VERSION_LABEL", + "manufacturer_id": 0, + "pid": 194, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "boot_software_version_label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CAPTURE_PRESET.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CAPTURE_PRESET.json new file mode 100644 index 0000000..5054209 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CAPTURE_PRESET.json @@ -0,0 +1,35 @@ +{ + "name": "CAPTURE_PRESET", + "notes": "Either the first field or all four fields can be given.", + "manufacturer_id": 0, + "pid": 4144, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "scene_num", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "up_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "down_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "wait_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CLEAR_STATUS_ID.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CLEAR_STATUS_ID.json new file mode 100644 index 0000000..56c00b8 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/CLEAR_STATUS_ID.json @@ -0,0 +1,9 @@ +{ + "name": "CLEAR_STATUS_ID", + "manufacturer_id": 0, + "pid": 50, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/COMMS_STATUS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/COMMS_STATUS.json new file mode 100644 index 0000000..bdf738d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/COMMS_STATUS.json @@ -0,0 +1,16 @@ +{ + "name": "COMMS_STATUS", + "manufacturer_id": 0, + "pid": 21, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { "name": "short_message", "type": "uint16" }, + { "name": "length_mismatch", "type": "uint16" }, + { "name": "checksum_fail", "type": "uint16" } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEFAULT_SLOT_VALUE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEFAULT_SLOT_VALUE.json new file mode 100644 index 0000000..9a85a1a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEFAULT_SLOT_VALUE.json @@ -0,0 +1,21 @@ +{ + "name": "DEFAULT_SLOT_VALUE", + "manufacturer_id": 0, + "pid": 290, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "slots", + "type": "list", + "itemType": { + "type": "compound", + "subtypes": [ + { "name": "id", "type": "uint16" }, + { "name": "default_value", "type": "uint8" } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_HOURS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_HOURS.json new file mode 100644 index 0000000..c4af096 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_HOURS.json @@ -0,0 +1,14 @@ +{ + "name": "DEVICE_HOURS", + "manufacturer_id": 0, + "pid": 1024, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "hours", "type": "uint32" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_INFO.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_INFO.json new file mode 100644 index 0000000..70dc7c3 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_INFO.json @@ -0,0 +1,109 @@ +{ + "name": "DEVICE_INFO", + "manufacturer_id": 0, + "pid": 96, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "protocol_major", "type": "uint8" }, + { "name": "protocol_minor", "type": "uint8" }, + { "name": "device_model_id", "type": "uint16" }, + { + "name": "product_category", + "type": "uint16", + "labels": [ + { "name": "NOT_DECLARED", "value": 0 }, + { "name": "FIXTURE", "value": 256 }, + { "name": "FIXTURE_FIXED", "value": 257 }, + { "name": "FIXTURE_MOVING_YOKE", "value": 258 }, + { "name": "FIXTURE_MOVING_MIRROR", "value": 259 }, + { "name": "FIXTURE_OTHER", "value": 511 }, + { "name": "FIXTURE_ACCESSORY", "value": 512 }, + { "name": "FIXTURE_ACCESSORY_COLOR", "value": 513 }, + { "name": "FIXTURE_ACCESSORY_YOKE", "value": 514 }, + { "name": "FIXTURE_ACCESSORY_MIRROR", "value": 515 }, + { "name": "FIXTURE_ACCESSORY_EFFECT", "value": 516 }, + { "name": "FIXTURE_ACCESSORY_BEAM", "value": 517 }, + { "name": "FIXTURE_ACCESSORY_OTHER", "value": 767 }, + { "name": "PROJECTOR", "value": 768 }, + { "name": "PROJECTOR_FIXED", "value": 769 }, + { "name": "PROJECTOR_MOVING_YOKE", "value": 770 }, + { "name": "PROJECTOR_MOVING_MIRROR", "value": 771 }, + { "name": "PROJECTOR_OTHER", "value": 1023 }, + { "name": "ATMOSPHERIC", "value": 1024 }, + { "name": "ATMOSPHERIC_EFFECT", "value": 1025 }, + { "name": "ATMOSPHERIC_PYRO", "value": 1026 }, + { "name": "ATMOSPHERIC_OTHER", "value": 1279 }, + { "name": "DIMMER", "value": 1280 }, + { "name": "DIMMER_AC_INCANDESCENT", "value": 1281 }, + { "name": "DIMMER_AC_FLUORESCENT", "value": 1282 }, + { "name": "DIMMER_AC_COLD_CATHODE", "value": 1283 }, + { "name": "DIMMER_AC_NONDIM", "value": 1284 }, + { "name": "DIMMER_AC_ELV", "value": 1285 }, + { "name": "DIMMER_AC_OTHER", "value": 1286 }, + { "name": "DIMMER_DC_LEVEL", "value": 1287 }, + { "name": "DIMMER_DC_PWM", "value": 1288 }, + { "name": "DIMMER_CS_LED", "value": 1289 }, + { "name": "DIMMER_OTHER", "value": 1535 }, + { "name": "POWER", "value": 1536 }, + { "name": "POWER_CONTROL", "value": 1537 }, + { "name": "POWER_SOURCE", "value": 1538 }, + { "name": "POWER_OTHER", "value": 1791 }, + { "name": "SCENIC", "value": 1792 }, + { "name": "SCENIC_DRIVE", "value": 1793 }, + { "name": "SCENIC_OTHER", "value": 2047 }, + { "name": "DATA", "value": 2048 }, + { "name": "DATA_DISTRIBUTION", "value": 2049 }, + { "name": "DATA_CONVERSION", "value": 2050 }, + { "name": "DATA_OTHER", "value": 2303 }, + { "name": "AV", "value": 2304 }, + { "name": "AV_AUDIO", "value": 2305 }, + { "name": "AV_VIDEO", "value": 2306 }, + { "name": "AV_OTHER", "value": 2559 }, + { "name": "MONITOR", "value": 2560 }, + { "name": "MONITOR_AC_LINE_POWER", "value": 2561 }, + { "name": "MONITOR_DC_POWER", "value": 2562 }, + { "name": "MONITOR_ENVIRONMENTAL", "value": 2563 }, + { "name": "MONITOR_OTHER", "value": 2815 }, + { "name": "CONTROL", "value": 28672 }, + { "name": "CONTROL_CONTROLLER", "value": 28673 }, + { "name": "CONTROL_BACKUP_DEVICE", "value": 28674 }, + { "name": "CONTROL_OTHER", "value": 28927 }, + { "name": "TEST", "value": 28928 }, + { "name": "TEST_EQUIPMENT", "value": 28929 }, + { "name": "TEST_OTHER", "value": 29183 }, + { "name": "OTHER", "value": 32767 } + ] + }, + { "name": "software_version_id", "type": "uint32" }, + { + "name": "dmx_footprint", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 512 } + ] + }, + { + "name": "current_personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "personality_count", "type": "uint8" }, + { + "name": "dmx_start_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "No Footprint", "value": 65535 } + ] + }, + { "name": "sub_device_count", "type": "uint16" }, + { "name": "sensor_count", "type": "uint8" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_LABEL.json new file mode 100644 index 0000000..37a523e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_LABEL.json @@ -0,0 +1,19 @@ +{ + "name": "DEVICE_LABEL", + "manufacturer_id": 0, + "pid": 130, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_MODEL_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_MODEL_DESCRIPTION.json new file mode 100644 index 0000000..ffee24b --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_MODEL_DESCRIPTION.json @@ -0,0 +1,16 @@ +{ + "name": "DEVICE_MODEL_DESCRIPTION", + "manufacturer_id": 0, + "pid": 128, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_POWER_CYCLES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_POWER_CYCLES.json new file mode 100644 index 0000000..d100b5f --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DEVICE_POWER_CYCLES.json @@ -0,0 +1,14 @@ +{ + "name": "DEVICE_POWER_CYCLES", + "manufacturer_id": 0, + "pid": 1029, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "power_cycle_count", "type": "uint32" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_INVERT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_INVERT.json new file mode 100644 index 0000000..8941c00 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_INVERT.json @@ -0,0 +1,23 @@ +{ + "name": "DISPLAY_INVERT", + "manufacturer_id": 0, + "pid": 1280, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "uint8", + "labels": [ + { "name": "Off", "value": 0 }, + { "name": "On", "value": 1 }, + { "name": "Auto", "value": 2 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_LEVEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_LEVEL.json new file mode 100644 index 0000000..7369a06 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DISPLAY_LEVEL.json @@ -0,0 +1,21 @@ +{ + "name": "DISPLAY_LEVEL", + "manufacturer_id": 0, + "pid": 1281, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "level", + "type": "uint8", + "labels": [ + { "name": "Off", "value": 0 }, + { "name": "Full", "value": 255 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY.json new file mode 100644 index 0000000..3e90e6e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY.json @@ -0,0 +1,23 @@ +{ + "name": "DMX_PERSONALITY", + "manufacturer_id": 0, + "pid": 224, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "personality_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { "$ref": "#/get_response/0" } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY_DESCRIPTION.json new file mode 100644 index 0000000..d4c953a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_PERSONALITY_DESCRIPTION.json @@ -0,0 +1,32 @@ +{ + "name": "DMX_PERSONALITY_DESCRIPTION", + "manufacturer_id": 0, + "pid": 225, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { "name": "personality", "type": "uint8" }, + { + "name": "dmx_slots_required", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 512 } + ] + }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_START_ADDRESS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_START_ADDRESS.json new file mode 100644 index 0000000..9ec7246 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/DMX_START_ADDRESS.json @@ -0,0 +1,32 @@ +{ + "name": "DMX_START_ADDRESS", + "manufacturer_id": 0, + "pid": 240, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "dmx_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "No Footprint", "value": 65535 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "dmx_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/FACTORY_DEFAULTS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/FACTORY_DEFAULTS.json new file mode 100644 index 0000000..59c01ae --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/FACTORY_DEFAULTS.json @@ -0,0 +1,17 @@ +{ + "name": "FACTORY_DEFAULTS", + "manufacturer_id": 0, + "pid": 144, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "status", + "type": "boolean" + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/IDENTIFY_DEVICE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/IDENTIFY_DEVICE.json new file mode 100644 index 0000000..550c141 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/IDENTIFY_DEVICE.json @@ -0,0 +1,21 @@ +{ + "name": "IDENTIFY_DEVICE", + "manufacturer_id": 0, + "pid": 4096, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "state", + "type": "boolean", + "labels": [ + { "name": "Off", "value": false }, + { "name": "On", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_HOURS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_HOURS.json new file mode 100644 index 0000000..468e8d4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_HOURS.json @@ -0,0 +1,14 @@ +{ + "name": "LAMP_HOURS", + "manufacturer_id": 0, + "pid": 1025, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "hours", "type": "uint32" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_ON_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_ON_MODE.json new file mode 100644 index 0000000..25c47b4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_ON_MODE.json @@ -0,0 +1,23 @@ +{ + "name": "LAMP_ON_MODE", + "manufacturer_id": 0, + "pid": 1028, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "mode", + "type": "uint8", + "labels": [ + { "name": "OFF", "value": 0 }, + { "name": "DMX", "value": 1 }, + { "name": "ON", "value": 2 }, + { "name": "AFTER_CAL", "value": 3 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STATE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STATE.json new file mode 100644 index 0000000..5bc6fdf --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STATE.json @@ -0,0 +1,25 @@ +{ + "name": "LAMP_STATE", + "manufacturer_id": 0, + "pid": 1027, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "state", + "type": "uint8", + "labels": [ + { "name": "LAMP_OFF", "value": 0 }, + { "name": "LAMP_ON", "value": 1 }, + { "name": "LAMP_STRIKE", "value": 2 }, + { "name": "LAMP_STANDBY", "value": 3 }, + { "name": "LAMP_NOT_PRESENT", "value": 4 }, + { "name": "LAMP_ERROR", "value": 127 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STRIKES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STRIKES.json new file mode 100644 index 0000000..0e4e4fa --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LAMP_STRIKES.json @@ -0,0 +1,14 @@ +{ + "name": "LAMP_STRIKES", + "manufacturer_id": 0, + "pid": 1026, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "strikes", "type": "uint32" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE.json new file mode 100644 index 0000000..f77b87a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE.json @@ -0,0 +1,21 @@ +{ + "name": "LANGUAGE", + "manufacturer_id": 0, + "pid": 176, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "language_code", + "type": "string", + "pattern": "^[a-zA-Z]{2}$", + "resources": [ "https://en.wikipedia.org/wiki/ISO_639-1" ], + "minLength": 2, + "maxLength": 2 + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE_CAPABILITIES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE_CAPABILITIES.json new file mode 100644 index 0000000..6cb7027 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/LANGUAGE_CAPABILITIES.json @@ -0,0 +1,22 @@ +{ + "name": "LANGUAGE_CAPABILITIES", + "manufacturer_id": 0, + "pid": 160, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "language_codes", + "type": "list", + "itemType": { + "name": "language_code", + "type": "string", + "pattern": "^[a-zA-Z]{2}$", + "resources": [ "https://en.wikipedia.org/wiki/ISO_639-1" ], + "minLength": 2, + "maxLength": 2 + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/MANUFACTURER_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/MANUFACTURER_LABEL.json new file mode 100644 index 0000000..516f466 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/MANUFACTURER_LABEL.json @@ -0,0 +1,16 @@ +{ + "name": "MANUFACTURER_LABEL", + "manufacturer_id": 0, + "pid": 129, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_INVERT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_INVERT.json new file mode 100644 index 0000000..127211c --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_INVERT.json @@ -0,0 +1,21 @@ +{ + "name": "PAN_INVERT", + "manufacturer_id": 0, + "pid": 1536, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "boolean", + "labels": [ + { "name": "Off", "value": false }, + { "name": "On", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_TILT_SWAP.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_TILT_SWAP.json new file mode 100644 index 0000000..e54cfec --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PAN_TILT_SWAP.json @@ -0,0 +1,21 @@ +{ + "name": "PAN_TILT_SWAP", + "manufacturer_id": 0, + "pid": 1538, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "boolean", + "labels": [ + { "name": "Off", "value": false }, + { "name": "On", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PARAMETER_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PARAMETER_DESCRIPTION.json new file mode 100644 index 0000000..1dcc40c --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PARAMETER_DESCRIPTION.json @@ -0,0 +1,101 @@ +{ + "name": "PARAMETER_DESCRIPTION", + "manufacturer_id": 0, + "pid": 81, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { "name": "pid", "type": "uint16" } + ], + "get_response": [ + { "name": "pid", "type": "uint16" }, + { "name": "pdl", "type": "uint8" }, + { "name": "data_type", "type": "uint8" }, + { + "name": "command_class", + "type": "uint8", + "labels": [ + { "name": "GET", "value": 1 }, + { "name": "SET", "value": 2 }, + { "name": "GET_SET", "value": 3 } + ], + "restrictToLabeled": true + }, + { "name": "type", "type": "uint8" }, + { + "name": "unit", + "type": "uint8", + "labels": [ + { "name": "NONE", "value": 0 }, + { "name": "CENTIGRADE", "value": 1 }, + { "name": "VOLTS_DC", "value": 2 }, + { "name": "VOLTS_AC_PEAK", "value": 3 }, + { "name": "VOLTS_AC_RMS", "value": 4 }, + { "name": "AMPERE_DC", "value": 5 }, + { "name": "AMPERE_AC_PEAK", "value": 6 }, + { "name": "AMPERE_AC_RMS", "value": 7 }, + { "name": "HERTZ", "value": 8 }, + { "name": "OHM", "value": 9 }, + { "name": "WATT", "value": 10 }, + { "name": "KILOGRAM", "value": 11 }, + { "name": "METERS", "value": 12 }, + { "name": "METERS_SQUARED", "value": 13 }, + { "name": "METERS_CUBED", "value": 14 }, + { "name": "KILOGRAMS_PER_METERS_CUBED", "value": 15 }, + { "name": "METERS_PER_SECOND", "value": 16 }, + { "name": "METERS_PER_SECOND_SQUARED", "value": 17 }, + { "name": "NEWTON", "value": 18 }, + { "name": "JOULE", "value": 19 }, + { "name": "PASCAL", "value": 20 }, + { "name": "SECOND", "value": 21 }, + { "name": "DEGREE", "value": 22 }, + { "name": "STERADIAN", "value": 23 }, + { "name": "CANDELA", "value": 24 }, + { "name": "LUMEN", "value": 25 }, + { "name": "LUX", "value": 26 }, + { "name": "IRE", "value": 27 }, + { "name": "BYTE", "value": 28 }, + { "name": "DECIBEL", "value": 29 }, + { "name": "DECIBEL_VOLT", "value": 30 }, + { "name": "DECIBEL_WATT", "value": 31 }, + { "name": "DECIBEL_METER", "value": 32 }, + { "name": "PERCENT", "value": 33 } + ] + }, + { + "name": "unit_prefix", + "type": "uint8", + "labels": [ + { "name": "NONE", "value": 0 }, + { "name": "DECI", "value": 1 }, + { "name": "CENTI", "value": 2 }, + { "name": "MILLI", "value": 3 }, + { "name": "MICRO", "value": 4 }, + { "name": "NANO", "value": 5 }, + { "name": "PICO", "value": 6 }, + { "name": "FEMTO", "value": 7 }, + { "name": "ATTO", "value": 8 }, + { "name": "ZEPTO", "value": 9 }, + { "name": "YOCTO", "value": 10 }, + { "name": "DECA", "value": 17 }, + { "name": "HEPTO", "value": 18 }, + { "name": "KILO", "value": 19 }, + { "name": "MEGA", "value": 20 }, + { "name": "GIGA", "value": 21 }, + { "name": "TERA", "value": 22 }, + { "name": "PETA", "value": 23 }, + { "name": "EXA", "value": 24 }, + { "name": "ZETTA", "value": 25 }, + { "name": "YOTTA", "value": 26 } + ] + }, + { "name": "min_valid_value", "type": "uint32" }, + { "name": "max_valid_value", "type": "uint32" }, + { "name": "default_value", "type": "uint32" }, + { + "name": "description", + "type": "string", + "maxLength": 32 + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PERFORM_SELF_TEST.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PERFORM_SELF_TEST.json new file mode 100644 index 0000000..95e7b24 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PERFORM_SELF_TEST.json @@ -0,0 +1,23 @@ +{ + "name": "PERFORM_SELF_TEST", + "manufacturer_id": 0, + "pid": 4128, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "self_tests_active", "type": "boolean" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "self_test_num", + "type": "uint8", + "labels": [ + { "name": "SELF_TEST_OFF", "value": 0 }, + { "name": "SELF_TEST_ALL", "value": 255 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/POWER_STATE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/POWER_STATE.json new file mode 100644 index 0000000..c379f26 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/POWER_STATE.json @@ -0,0 +1,24 @@ +{ + "name": "POWER_STATE", + "manufacturer_id": 0, + "pid": 4112, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "state", + "type": "uint8", + "labels": [ + { "name": "FULL_OFF", "value": 0 }, + { "name": "SHUTDOWN", "value": 1 }, + { "name": "STANDBY", "value": 2 }, + { "name": "NORMAL", "value": 255 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRESET_PLAYBACK.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRESET_PLAYBACK.json new file mode 100644 index 0000000..5ba91ee --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRESET_PLAYBACK.json @@ -0,0 +1,22 @@ +{ + "name": "PRESET_PLAYBACK", + "manufacturer_id": 0, + "pid": 4145, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "mode", + "type": "uint16", + "labels": [ + { "name": "OFF", "value": 0 }, + { "name": "ALL", "value": 65535 } + ] + }, + { "name": "level", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRODUCT_DETAIL_ID_LIST.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRODUCT_DETAIL_ID_LIST.json new file mode 100644 index 0000000..188c4e9 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PRODUCT_DETAIL_ID_LIST.json @@ -0,0 +1,99 @@ +{ + "name": "PRODUCT_DETAIL_ID_LIST", + "manufacturer_id": 0, + "pid": 112, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "product_detail_ids", + "type": "list", + "itemType": { + "name": "product_detail_id", + "type": "uint16", + "labels": [ + { "name": "NOT_DECLARED", "value": 0 }, + { "name": "ARC", "value": 1 }, + { "name": "METAL_HALIDE", "value": 2 }, + { "name": "INCANDESCENT", "value": 3 }, + { "name": "LED", "value": 4 }, + { "name": "FLUORESCENT", "value": 5 }, + { "name": "COLD_CATHODE", "value": 6 }, + { "name": "ELECTROLUMINESCENT", "value": 7 }, + { "name": "LASER", "value": 8 }, + { "name": "FLASHTUBE", "value": 9 }, + { "name": "COLOR_SCROLLER", "value": 256 }, + { "name": "COLOR_WHEEL", "value": 257 }, + { "name": "COLOR_CHANGE", "value": 258 }, + { "name": "IRIS_DOUSER", "value": 259 }, + { "name": "DIMMING_SHUTTER", "value": 260 }, + { "name": "PROFILE_SHUTTER", "value": 261 }, + { "name": "BARNDOOR_SHUTTER", "value": 262 }, + { "name": "EFFECTS_DISC", "value": 263 }, + { "name": "GOBO_ROTATOR", "value": 264 }, + { "name": "VIDEO", "value": 512 }, + { "name": "SLIDE", "value": 513 }, + { "name": "FILM", "value": 514 }, + { "name": "OIL_WHEEL", "value": 515 }, + { "name": "LCD_GATE", "value": 516 }, + { "name": "FOGGER_GLYCOL", "value": 768 }, + { "name": "FOGGER_MINERAL_OIL", "value": 769 }, + { "name": "FOGGER_WATER", "value": 770 }, + { "name": "CO2", "value": 771 }, + { "name": "LN2", "value": 772 }, + { "name": "BUBBLE", "value": 773 }, + { "name": "FLAME_PROPANE", "value": 774 }, + { "name": "FLAME_OTHER", "value": 775 }, + { "name": "OLFACTORY_STIMULATOR", "value": 776 }, + { "name": "SNOW", "value": 777 }, + { "name": "WATER_JET", "value": 778 }, + { "name": "WIND", "value": 779 }, + { "name": "CONFETTI", "value": 780 }, + { "name": "HAZARD", "value": 781 }, + { "name": "PHASE_CONTROL", "value": 1024 }, + { "name": "REVERSE_PHASE_CONTROL", "value": 1025 }, + { "name": "SINE", "value": 1026 }, + { "name": "PWM", "value": 1027 }, + { "name": "DC", "value": 1028 }, + { "name": "HF_BALLAST", "value": 1029 }, + { "name": "HFHV_NEON_BALLAST", "value": 1030 }, + { "name": "HFHV_EL", "value": 1031 }, + { "name": "MHR_BALLAST", "value": 1032 }, + { "name": "BIT_ANGLE_MODULATION", "value": 1033 }, + { "name": "HIGH_FREQUENCY_12V", "value": 1034 }, + { "name": "RELAY_MECHANICAL", "value": 1035 }, + { "name": "RELAY_ELECTRONIC", "value": 1036 }, + { "name": "SWITCH_ELECTRONIC", "value": 1037 }, + { "name": "CONTACTOR", "value": 1037 }, + { "name": "MIRROR_BALL_ROTATOR", "value": 1280 }, + { "name": "OTHER_ROTATOR", "value": 1281 }, + { "name": "KABUKI_DROP", "value": 1282 }, + { "name": "CURTAIN", "value": 1283 }, + { "name": "LINESET", "value": 1284 }, + { "name": "MOTOR_CONTROL", "value": 1285 }, + { "name": "DAMPER_CONTROL", "value": 1286 }, + { "name": "SPLITTER", "value": 1536 }, + { "name": "ETHERNET_NODE", "value": 1537 }, + { "name": "MERGE", "value": 1538 }, + { "name": "DATAPATCH", "value": 1539 }, + { "name": "WIRELESS_LINK", "value": 1540 }, + { "name": "PROTOCOL_CONVERTER", "value": 1793 }, + { "name": "ANALOG_DEMULTIPLEX", "value": 1794 }, + { "name": "ANALOG_MULTIPLEX", "value": 1795 }, + { "name": "SWITCH_PANEL", "value": 1796 }, + { "name": "ROUTER", "value": 2048 }, + { "name": "FADER", "value": 2049 }, + { "name": "MIXER", "value": 2050 }, + { "name": "CHANGEOVER_MANUAL", "value": 2304 }, + { "name": "CHANGEOVER_AUTO", "value": 2305 }, + { "name": "TEST", "value": 2036 }, + { "name": "GFI_RCD", "value": 2560 }, + { "name": "BATTERY", "value": 2561 }, + { "name": "CONTROLLABLE_BREAKER", "value": 2562 }, + { "name": "OTHER", "value": 32767 } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICES.json new file mode 100644 index 0000000..01ffafd --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICES.json @@ -0,0 +1,19 @@ +{ + "name": "PROXIED_DEVICES", + "manufacturer_id": 0, + "pid": 16, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { + "name": "device_uids", + "type": "list", + "itemType": { + "name": "device_uid", + "type": "bytes", + "format": "uid" + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICE_COUNT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICE_COUNT.json new file mode 100644 index 0000000..348fc8f --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/PROXIED_DEVICE_COUNT.json @@ -0,0 +1,12 @@ +{ + "name": "PROXIED_DEVICE_COUNT", + "manufacturer_id": 0, + "pid": 17, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { "name": "device_count", "type": "uint16" }, + { "name": "list_change", "type": "boolean" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/QUEUED_MESSAGE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/QUEUED_MESSAGE.json new file mode 100644 index 0000000..eed499b --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/QUEUED_MESSAGE.json @@ -0,0 +1,22 @@ +{ + "name": "QUEUED_MESSAGE", + "manufacturer_id": 0, + "pid": 32, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "status_type", + "type": "uint8", + "labels": [ + { "name": "STATUS_NONE", "value": 0 }, + { "name": "STATUS_GET_LAST_MESSAGE", "value": 1 }, + { "name": "STATUS_ADVISORY", "value": 2 }, + { "name": "STATUS_WARNING", "value": 3 }, + { "name": "STATUS_ERROR", "value": 4 } + ], + "restrictToLabeled": true + } + ], + "get_response": "different_pid" +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/REAL_TIME_CLOCK.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/REAL_TIME_CLOCK.json new file mode 100644 index 0000000..260937a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/REAL_TIME_CLOCK.json @@ -0,0 +1,55 @@ +{ + "name": "REAL_TIME_CLOCK", + "manufacturer_id": 0, + "pid": 1539, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "year", + "type": "uint16", + "ranges": [ + { "minimum": 2003, "maximum": 65535 } + ] + }, + { + "name": "month", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 12 } + ] + }, + { + "name": "day", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 31 } + ] + }, + { + "name": "hour", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 24 } + ] + }, + { + "name": "minute", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 59 } + ] + }, + { + "name": "second", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 60 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RECORD_SENSORS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RECORD_SENSORS.json new file mode 100644 index 0000000..636941e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RECORD_SENSORS.json @@ -0,0 +1,11 @@ +{ + "name": "RECORD_SENSORS", + "manufacturer_id": 0, + "pid": 514, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { "name": "sensor", "type": "uint8" } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RESET_DEVICE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RESET_DEVICE.json new file mode 100644 index 0000000..5ca68fa --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/RESET_DEVICE.json @@ -0,0 +1,19 @@ +{ + "name": "RESET_DEVICE", + "manufacturer_id": 0, + "pid": 4097, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "state", + "type": "uint8", + "labels": [ + { "name": "Warm Reset", "value": 1 }, + { "name": "Cold Reset", "value": 255 } + ], + "restrictToLabeled": true + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SELF_TEST_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SELF_TEST_DESCRIPTION.json new file mode 100644 index 0000000..918bf5c --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SELF_TEST_DESCRIPTION.json @@ -0,0 +1,19 @@ +{ + "name": "SELF_TEST_DESCRIPTION", + "manufacturer_id": 0, + "pid": 4129, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "self_test_num", "type": "uint8" } + ], + "get_response": [ + { "name": "self_test_num", "type": "uint8" }, + { + "name": "label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_DEFINITION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_DEFINITION.json new file mode 100644 index 0000000..b53cb79 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_DEFINITION.json @@ -0,0 +1,145 @@ +{ + "name": "SENSOR_DEFINITION", + "manufacturer_id": 0, + "pid": 512, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "sensor", "type": "uint8" } + ], + "get_response": [ + { "name": "sensor", "type": "uint8" }, + { + "name": "type", + "type": "uint8", + "labels": [ + { "name": "TEMPERATURE", "value": 0 }, + { "name": "VOLTAGE", "value": 1 }, + { "name": "CURRENT", "value": 2 }, + { "name": "FREQUENCY", "value": 3 }, + { "name": "RESISTANCE", "value": 4 }, + { "name": "POWER", "value": 5 }, + { "name": "MASS", "value": 6 }, + { "name": "LENGTH", "value": 7 }, + { "name": "AREA", "value": 8 }, + { "name": "VOLUME", "value": 9 }, + { "name": "DENSITY", "value": 10 }, + { "name": "VELOCITY", "value": 11 }, + { "name": "ACCELERATION", "value": 12 }, + { "name": "FORCE", "value": 13 }, + { "name": "ENERGY", "value": 14 }, + { "name": "PRESSURE", "value": 15 }, + { "name": "TIME", "value": 16 }, + { "name": "ANGLE", "value": 17 }, + { "name": "POSITION_X", "value": 18 }, + { "name": "POSITION_Y", "value": 19 }, + { "name": "POSITION_Z", "value": 20 }, + { "name": "ANGULAR_VELOCTY", "value": 21 }, + { "name": "LUMINOUS_INTENSITY", "value": 22 }, + { "name": "LUMINOUS_FLUX", "value": 23 }, + { "name": "ILLUMINANCE", "value": 24 }, + { "name": "CHROMINANCE_RED", "value": 25 }, + { "name": "CHROMINANCE_GREEN", "value": 26 }, + { "name": "CHROMINANCE_BLUE", "value": 27 }, + { "name": "CONTACTS", "value": 28 }, + { "name": "MEMORY", "value": 29 }, + { "name": "ITEMS", "value": 30 }, + { "name": "HUMIDITY", "value": 31 }, + { "name": "COUNTER_16BIT", "value": 32 }, + { "name": "RPM", "value": 33 }, + { "name": "CPU_LOAD", "value": 34 }, + { "name": "BANDWIDTH_TOTAL", "value": 35 }, + { "name": "BANDWIDTH_USED", "value": 36 }, + { "name": "GAS_CONCENTRATION", "value": 37 }, + { "name": "CO2_LEVEL", "value": 38 }, + { "name": "SOUND_PRESSURE_LEVEL", "value": 39 }, + { "name": "OTHER", "value": 127 } + ] + }, + { + "name": "unit", + "type": "uint8", + "labels": [ + { "name": "NONE", "value": 0 }, + { "name": "CENTIGRADE", "value": 1 }, + { "name": "VOLTS_DC", "value": 2 }, + { "name": "VOLTS_AC_PEAK", "value": 3 }, + { "name": "VOLTS_AC_RMS", "value": 4 }, + { "name": "AMPERE_DC", "value": 5 }, + { "name": "AMPERE_AC_PEAK", "value": 6 }, + { "name": "AMPERE_AC_RMS", "value": 7 }, + { "name": "HERTZ", "value": 8 }, + { "name": "OHM", "value": 9 }, + { "name": "WATT", "value": 10 }, + { "name": "KILOGRAM", "value": 11 }, + { "name": "METERS", "value": 12 }, + { "name": "METERS_SQUARED", "value": 13 }, + { "name": "METERS_CUBED", "value": 14 }, + { "name": "KILOGRAMS_PER_METERS_CUBED", "value": 15 }, + { "name": "METERS_PER_SECOND", "value": 16 }, + { "name": "METERS_PER_SECOND_SQUARED", "value": 17 }, + { "name": "NEWTON", "value": 18 }, + { "name": "JOULE", "value": 19 }, + { "name": "PASCAL", "value": 20 }, + { "name": "SECOND", "value": 21 }, + { "name": "DEGREE", "value": 22 }, + { "name": "STERADIAN", "value": 23 }, + { "name": "CANDELA", "value": 24 }, + { "name": "LUMEN", "value": 25 }, + { "name": "LUX", "value": 26 }, + { "name": "IRE", "value": 27 }, + { "name": "BYTE", "value": 28 }, + { "name": "DECIBEL", "value": 29 }, + { "name": "DECIBEL_VOLT", "value": 30 }, + { "name": "DECIBEL_WATT", "value": 31 }, + { "name": "DECIBEL_METER", "value": 32 }, + { "name": "PERCENT", "value": 33 } + ] + }, + { + "name": "unit_prefix", + "type": "uint8", + "labels": [ + { "name": "NONE", "value": 0 }, + { "name": "DECI", "value": 1 }, + { "name": "CENTI", "value": 2 }, + { "name": "MILLI", "value": 3 }, + { "name": "MICRO", "value": 4 }, + { "name": "NANO", "value": 5 }, + { "name": "PICO", "value": 6 }, + { "name": "FEMTO", "value": 7 }, + { "name": "ATTO", "value": 8 }, + { "name": "ZEPTO", "value": 9 }, + { "name": "YOCTO", "value": 10 }, + { "name": "DECA", "value": 17 }, + { "name": "HEPTO", "value": 18 }, + { "name": "KILO", "value": 19 }, + { "name": "MEGA", "value": 20 }, + { "name": "GIGA", "value": 21 }, + { "name": "TERA", "value": 22 }, + { "name": "PETA", "value": 23 }, + { "name": "EXA", "value": 24 }, + { "name": "ZETTA", "value": 25 }, + { "name": "YOTTA", "value": 26 } + ] + }, + { "name": "range_min_value", "type": "int16" }, + { "name": "range_max_value", "type": "int16" }, + { "name": "normal_min_value", "type": "int16" }, + { "name": "normal_max_value", "type": "int16" }, + { + "name": "recorded_value_support", + "type": "bitField", + "size": 8, + "bits": [ + { "name": "recorded_value_supported", "index": 0 }, + { "name": "low_high_detected_values_supported", "index": 1 } + ] + }, + { + "name": "description", + "type": "string", + "maxLength": 32 + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_VALUE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_VALUE.json new file mode 100644 index 0000000..6ad3ba6 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SENSOR_VALUE.json @@ -0,0 +1,20 @@ +{ + "name": "SENSOR_VALUE", + "manufacturer_id": 0, + "pid": 513, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "sensor", "type": "uint8" } + ], + "get_response": [ + { "name": "sensor", "type": "uint8" }, + { "name": "value", "type": "int16" }, + { "name": "lowest_detected", "type": "int16" }, + { "name": "highest_detected", "type": "int16" }, + { "name": "recorded_value", "type": "int16" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_request", + "set_response": "get_response" +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_DESCRIPTION.json new file mode 100644 index 0000000..7d3fbee --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_DESCRIPTION.json @@ -0,0 +1,19 @@ +{ + "name": "SLOT_DESCRIPTION", + "manufacturer_id": 0, + "pid": 289, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "slot", "type": "uint16" } + ], + "get_response": [ + { "name": "slot", "type": "uint16" }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_INFO.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_INFO.json new file mode 100644 index 0000000..a25aaba --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SLOT_INFO.json @@ -0,0 +1,22 @@ +{ + "name": "SLOT_INFO", + "manufacturer_id": 0, + "pid": 288, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "slots", + "type": "list", + "itemType": { + "type": "compound", + "subtypes": [ + { "name": "id", "type": "uint16" }, + { "name": "type", "type": "uint8" }, + { "name": "label_id", "type": "uint16" } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SOFTWARE_VERSION_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SOFTWARE_VERSION_LABEL.json new file mode 100644 index 0000000..0eb607d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SOFTWARE_VERSION_LABEL.json @@ -0,0 +1,16 @@ +{ + "name": "SOFTWARE_VERSION_LABEL", + "manufacturer_id": 0, + "pid": 192, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "software_version_label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_ID_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_ID_DESCRIPTION.json new file mode 100644 index 0000000..8428a76 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_ID_DESCRIPTION.json @@ -0,0 +1,18 @@ +{ + "name": "STATUS_ID_DESCRIPTION", + "manufacturer_id": 0, + "pid": 49, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { "name": "status_id", "type": "uint16" } + ], + "get_response": [ + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_MESSAGES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_MESSAGES.json new file mode 100644 index 0000000..3876d53 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/STATUS_MESSAGES.json @@ -0,0 +1,49 @@ +{ + "name": "STATUS_MESSAGES", + "manufacturer_id": 0, + "pid": 48, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "status_type", + "type": "uint8", + "notes": "The requested Status Type isn't restricted in the spec.", + "labels": [ + { "name": "STATUS_NONE", "value": 0 }, + { "name": "STATUS_GET_LAST_MESSAGE", "value": 1 }, + { "name": "STATUS_ADVISORY", "value": 2 }, + { "name": "STATUS_WARNING", "value": 3 }, + { "name": "STATUS_ERROR", "value": 4 } + ] + } + ], + "get_response": [ + { + "name": "slots", + "type": "list", + "itemType": { + "type": "compound", + "subtypes": [ + { "name": "subdevice_id", "type": "uint16" }, + { + "name": "status_type", + "type": "uint8", + "labels": [ + { "name": "STATUS_ADVISORY", "value": 2 }, + { "name": "STATUS_WARNING", "value": 3 }, + { "name": "STATUS_ERROR", "value": 4 }, + { "name": "STATUS_ADVISORY_CLEARED", "value": 18 }, + { "name": "STATUS_WARNING_CLEARED", "value": 19 }, + { "name": "STATUS_ERROR_CLEARED", "value": 20 } + ], + "restrictToLabeled": true + }, + { "name": "status_message_id", "type": "uint16" }, + { "name": "data_value_1", "type": "int16" }, + { "name": "data_value_2", "type": "int16" } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUB_DEVICE_STATUS_REPORT_THRESHOLD.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUB_DEVICE_STATUS_REPORT_THRESHOLD.json new file mode 100644 index 0000000..66f35fb --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUB_DEVICE_STATUS_REPORT_THRESHOLD.json @@ -0,0 +1,24 @@ +{ + "name": "SUB_DEVICE_STATUS_REPORT_THRESHOLD", + "manufacturer_id": 0, + "pid": 51, + "version": 1, + "get_request_subdevice_range": [ "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "status_type", + "type": "uint8", + "notes": "The Status Type value is not restricted in the spec.", + "labels": [ + { "name": "STATUS_NONE", "value": 0 }, + { "name": "STATUS_ADVISORY", "value": 2 }, + { "name": "STATUS_WARNING", "value": 3 }, + { "name": "STATUS_ERROR", "value": 4 } + ] + } + ], + "set_request_subdevice_range": [ "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUPPORTED_PARAMETERS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUPPORTED_PARAMETERS.json new file mode 100644 index 0000000..dd2143e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/SUPPORTED_PARAMETERS.json @@ -0,0 +1,18 @@ +{ + "name": "SUPPORTED_PARAMETERS", + "manufacturer_id": 0, + "pid": 80, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "pids", + "type": "list", + "itemType": { + "name": "pid", + "type": "uint16" + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/TILT_INVERT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/TILT_INVERT.json new file mode 100644 index 0000000..75eb34e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.20/TILT_INVERT.json @@ -0,0 +1,21 @@ +{ + "name": "TILT_INVERT", + "manufacturer_id": 0, + "pid": 1537, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "boolean", + "labels": [ + { "name": "Off", "value": false }, + { "name": "On", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/BURN_IN.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/BURN_IN.json new file mode 100644 index 0000000..f608075 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/BURN_IN.json @@ -0,0 +1,23 @@ +{ + "name": "BURN_IN", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 1088, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "hours_remaining", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "hours", + "type": "uint8", + "labels": [ + { "name": "Abort", "value": 0 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE.json new file mode 100644 index 0000000..fbec7d5 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE.json @@ -0,0 +1,18 @@ +{ + "name": "CURVE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 835, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "curve", "type": "uint8" }, + { "name": "curve_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { "name": "curve", "type": "uint8" } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE_DESCRIPTION.json new file mode 100644 index 0000000..abc6992 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/CURVE_DESCRIPTION.json @@ -0,0 +1,20 @@ +{ + "name": "CURVE_DESCRIPTION", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 836, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "curve", "type": "uint8" } + ], + "get_response": [ + { "name": "curve", "type": "uint8" }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DIMMER_INFO.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DIMMER_INFO.json new file mode 100644 index 0000000..896d4c8 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DIMMER_INFO.json @@ -0,0 +1,55 @@ +{ + "name": "DIMMER_INFO", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 832, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "min_level_lower_limit", + "type": "uint16", + "labels": [ + { "name": "Not Implemented", "value": 0 } + ] + }, + { + "name": "min_level_upper_limit", + "type": "uint16", + "labels": [ + { "name": "Not Implemented", "value": 0 } + ] + }, + { + "name": "max_level_lower_limit", + "type": "uint16", + "labels": [ + { "name": "Not Implemented", "value": 65535 } + ] + }, + { + "name": "max_level_upper_limit", + "type": "uint16", + "labels": [ + { "name": "Not Implemented", "value": 65535 } + ] + }, + { "name": "curve_count", "type": "uint8" }, + { + "name": "levels_resolution_bits", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 16 } + ] + }, + { + "name": "min_level_split_levels_supported", + "type": "boolean", + "labels": [ + { "name": "Not Supported", "value": false }, + { "name": "Supported", "value": true } + ] + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_BLOCK_ADDRESS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_BLOCK_ADDRESS.json new file mode 100644 index 0000000..34799d3 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_BLOCK_ADDRESS.json @@ -0,0 +1,40 @@ +{ + "name": "DMX_BLOCK_ADDRESS", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 320, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { + "name": "total_subdevice_footprint", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 512 } + ] + }, + { + "name": "base_dmx_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "No Footprint", "value": 65535 } + ] + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "base_dmx_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_FAIL_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_FAIL_MODE.json new file mode 100644 index 0000000..593c822 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_FAIL_MODE.json @@ -0,0 +1,47 @@ +{ + "name": "DMX_FAIL_MODE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 321, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "scene_num", + "type": "uint16", + "labels": [ + { "name": "PRESET_PLAYBACK_OFF", "value": 0 }, + { "name": "PRESET_PLAYBACK_ALL", "value": 65535 } + ] + }, + { + "name": "loss_of_signal_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Infinite", "value": 65535 } + ] + }, + { + "name": "hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Infinite", "value": 65535 } + ] + }, + { + "name": "level", + "type": "uint8", + "labels": [ + { "name": "Full", "value": 255 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_STARTUP_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_STARTUP_MODE.json new file mode 100644 index 0000000..f568ba9 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/DMX_STARTUP_MODE.json @@ -0,0 +1,44 @@ +{ + "name": "DMX_STARTUP_MODE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 322, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "scene_num", + "type": "uint16", + "labels": [ + { "name": "PRESET_PLAYBACK_OFF", "value": 0 }, + { "name": "PRESET_PLAYBACK_ALL", "value": 65535 } + ] + }, + { + "name": "startup_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Infinite", "value": 65535 } + ] + }, + { + "name": "level", + "type": "uint8", + "labels": [ + { "name": "Full", "value": 255 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/IDENTIFY_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/IDENTIFY_MODE.json new file mode 100644 index 0000000..7eaec5e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/IDENTIFY_MODE.json @@ -0,0 +1,22 @@ +{ + "name": "IDENTIFY_MODE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 4160, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "mode", + "type": "uint8", + "labels": [ + { "name": "Quiet Identify", "value": 0 }, + { "name": "Loud Identify", "value": 255 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_PIN.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_PIN.json new file mode 100644 index 0000000..4d934b1 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_PIN.json @@ -0,0 +1,36 @@ +{ + "name": "LOCK_PIN", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 1600, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "current_pin_code", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 9999 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "new_pin_code", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 9999 } + ] + }, + { + "name": "current_pin_code", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 9999 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE.json new file mode 100644 index 0000000..a82df8d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE.json @@ -0,0 +1,37 @@ +{ + "name": "LOCK_STATE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 1601, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "state", + "type": "uint8", + "labels": [ + { "name": "Unlocked", "value": 0 } + ] + }, + { "name": "state_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "pin_code", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 9999 } + ] + }, + { + "name": "state", + "type": "uint8", + "labels": [ + { "name": "Unlocked", "value": 0 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE_DESCRIPTION.json new file mode 100644 index 0000000..36cecf6 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/LOCK_STATE_DESCRIPTION.json @@ -0,0 +1,32 @@ +{ + "name": "LOCK_STATE_DESCRIPTION", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 1602, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "state", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { + "name": "state", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MAXIMUM_LEVEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MAXIMUM_LEVEL.json new file mode 100644 index 0000000..4227ddc --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MAXIMUM_LEVEL.json @@ -0,0 +1,15 @@ +{ + "name": "MAXIMUM_LEVEL", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 834, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "max_level", "type": "uint16" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MINIMUM_LEVEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MINIMUM_LEVEL.json new file mode 100644 index 0000000..fe4ea10 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MINIMUM_LEVEL.json @@ -0,0 +1,17 @@ +{ + "name": "MINIMUM_LEVEL", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 833, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "min_level_increasing", "type": "uint16" }, + { "name": "min_level_decreasing", "type": "uint16" }, + { "name": "on_below_min", "type": "boolean" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY.json new file mode 100644 index 0000000..aa66cd4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY.json @@ -0,0 +1,30 @@ +{ + "name": "MODULATION_FREQUENCY", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 839, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "setting_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY_DESCRIPTION.json new file mode 100644 index 0000000..2dcf584 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/MODULATION_FREQUENCY_DESCRIPTION.json @@ -0,0 +1,42 @@ +{ + "name": "MODULATION_FREQUENCY_DESCRIPTION", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 840, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "setting", + "type": "uint8", + "notes": "The value isn't restricted in the spec, but MODULATION_FREQUENCY restricts this.", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { + "name": "setting", + "type": "uint8", + "notes": "The value isn't restricted in the spec, but MODULATION_FREQUENCY restricts this.", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { + "name": "frequency", + "type": "uint32", + "units": 8, + "labels": [ + { "name": "Not Declared", "value": 4294967295 } + ] + }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME.json new file mode 100644 index 0000000..6910308 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME.json @@ -0,0 +1,30 @@ +{ + "name": "OUTPUT_RESPONSE_TIME", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 837, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "setting_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME_DESCRIPTION.json new file mode 100644 index 0000000..2c96662 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/OUTPUT_RESPONSE_TIME_DESCRIPTION.json @@ -0,0 +1,34 @@ +{ + "name": "OUTPUT_RESPONSE_TIME_DESCRIPTION", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 838, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "setting", + "type": "uint8", + "notes": "The value isn't restricted in the spec, but OUTPUT_RESPONSE_TIME restricts this.", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { + "name": "setting", + "type": "uint8", + "notes": "The value isn't restricted in the spec, but OUTPUT_RESPONSE_TIME restricts this.", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/POWER_ON_SELF_TEST.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/POWER_ON_SELF_TEST.json new file mode 100644 index 0000000..f3101d7 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/POWER_ON_SELF_TEST.json @@ -0,0 +1,22 @@ +{ + "name": "POWER_ON_SELF_TEST", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 4164, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "parameter", + "type": "uint8", + "labels": [ + { "name": "Disabled", "value": 0 }, + { "name": "Enabled", "value": 1 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_INFO.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_INFO.json new file mode 100644 index 0000000..80ea0de --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_INFO.json @@ -0,0 +1,114 @@ +{ + "name": "PRESET_INFO", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 4161, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "name": "level_field_supported", "type": "boolean" }, + { "name": "preset_sequence_supported", "type": "boolean" }, + { "name": "split_times_supported", "type": "boolean" }, + { "name": "dmx_fail_infinite_delay_time_supported", "type": "boolean" }, + { "name": "dmx_fail_infinite_hold_time_supported", "type": "boolean" }, + { "name": "startup_infinite_hold_time_supported", "type": "boolean" }, + { "name": "max_scene_number", "type": "uint16" }, + { + "name": "preset_min_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "preset_max_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "preset_min_wait_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "preset_max_wait_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "dmx_fail_min_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "dmx_fail_max_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "dmx_fail_min_hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "dmx_fail_max_hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "startup_min_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "startup_max_delay_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "startup_min_hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "startup_max_hold_time", + "type": "uint16", + "units": 21, + "prefixPower": -1, + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_MERGE_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_MERGE_MODE.json new file mode 100644 index 0000000..465f69a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_MERGE_MODE.json @@ -0,0 +1,26 @@ +{ + "name": "PRESET_MERGE_MODE", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 4163, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "mode", + "type": "uint8", + "labels": [ + { "name": "DEFAULT", "value": 0 }, + { "name": "HTP", "value": 1 }, + { "name": "LTP", "value": 2 }, + { "name": "DMX_ONLY", "value": 3 }, + { "name": "OTHER", "value": 255 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_STATUS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_STATUS.json new file mode 100644 index 0000000..f7df384 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-1/PRESET_STATUS.json @@ -0,0 +1,91 @@ +{ + "name": "PRESET_STATUS", + "notes": "E1.37-1", + "manufacturer_id": 0, + "pid": 4162, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "scene_num", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 65534 } + ] + } + ], + "get_response": [ + { + "name": "scene_num", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 65534 } + ] + }, + { + "name": "up_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "down_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "wait_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "programmed", + "type": "uint8", + "labels": [ + { "name": "NOT_PROGRAMMED", "value": 0 }, + { "name": "PROGRAMMED", "value": 1 }, + { "name": "PROGRAMMED_READ_ONLY", "value": 2 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "scene_num", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 65534 } + ] + }, + { + "name": "up_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "down_fade_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "wait_time", + "type": "uint16", + "units": 21, + "prefixPower": -1 + }, + { + "name": "clear_preset", + "type": "boolean", + "labels": [ + { "name": "Don't Clear", "value": false }, + { "name": "Clear", "value": true } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_DOMAIN_NAME.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_DOMAIN_NAME.json new file mode 100644 index 0000000..2fdb9c2 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_DOMAIN_NAME.json @@ -0,0 +1,28 @@ +{ + "name": "DNS_DOMAIN_NAME", + "notes": "E1.37-2. This the domain of an internet host; it is appended to the hostname using a dot ('.') to create a fully qualified domain name (FQDN).", + "manufacturer_id": 0, + "pid": 1805, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "domain_name", + "type": "string", + "resources": [ + "https://www.rfc-editor.org/rfc/rfc1123.html#section-2", + "https://www.rfc-editor.org/rfc/rfc1912.html#section-2.1", + "https://www.rfc-editor.org/rfc/rfc1035.html#section-2.3.1", + "https://www.rfc-editor.org/rfc/rfc3696.html#section-2", + "https://stackoverflow.com/a/14622263" + ], + "format": "hostname", + "maxLength": 231, + "restrictToASCII": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_HOSTNAME.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_HOSTNAME.json new file mode 100644 index 0000000..a96c6f7 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_HOSTNAME.json @@ -0,0 +1,29 @@ +{ + "name": "DNS_HOSTNAME", + "notes": "E1.37-2. This the host-specific part (or \"label\") of an internet host; it is prepended to the domain name using a dot ('.') to create a fully qualified domain name (FQDN).", + "manufacturer_id": 0, + "pid": 1804, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "hostname", + "type": "string", + "resources": [ + "https://www.rfc-editor.org/rfc/rfc1123.html#section-2", + "https://www.rfc-editor.org/rfc/rfc1912.html#section-2.1", + "https://www.rfc-editor.org/rfc/rfc3696.html#section-2", + "https://stackoverflow.com/a/14622263" + ], + "pattern": "^(?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]$", + "notes": "Some implementations don't support negative lookbehind in patterns. Alternative patterns without negative lookahead: \"^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$\", \"^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$\".", + "minLength": 1, + "maxLength": 63, + "restrictToASCII": true + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_IPV4_NAME_SERVER.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_IPV4_NAME_SERVER.json new file mode 100644 index 0000000..d4e0245 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/DNS_IPV4_NAME_SERVER.json @@ -0,0 +1,35 @@ +{ + "name": "DNS_IPV4_NAME_SERVER", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1803, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "index", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 2 } + ] + } + ], + "get_response": [ + { + "name": "index", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 2 } + ] + }, + { + "name": "address", + "type": "bytes", + "notes": "All zeros means IPV4_UNCONFIGURED.", + "format": "ipv4" + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_APPLY_CONFIGURATION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_APPLY_CONFIGURATION.json new file mode 100644 index 0000000..46df8c9 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_APPLY_CONFIGURATION.json @@ -0,0 +1,18 @@ +{ + "name": "INTERFACE_APPLY_CONFIGURATION", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1781, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_HARDWARE_ADDRESS_TYPE1.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_HARDWARE_ADDRESS_TYPE1.json new file mode 100644 index 0000000..5c2d03d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_HARDWARE_ADDRESS_TYPE1.json @@ -0,0 +1,32 @@ +{ + "name": "INTERFACE_HARDWARE_ADDRESS_TYPE1", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1794, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "address", + "type": "bytes", + "resources": [ "https://www.rfc-editor.org/rfc/rfc7042.html#section-2.1" ], + "format": "mac-address" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_LABEL.json new file mode 100644 index 0000000..460c72e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_LABEL.json @@ -0,0 +1,32 @@ +{ + "name": "INTERFACE_LABEL", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1793, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RELEASE_DHCP.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RELEASE_DHCP.json new file mode 100644 index 0000000..0cb4539 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RELEASE_DHCP.json @@ -0,0 +1,18 @@ +{ + "name": "INTERFACE_RELEASE_DHCP", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1780, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RENEW_DHCP.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RENEW_DHCP.json new file mode 100644 index 0000000..7251fa8 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/INTERFACE_RENEW_DHCP.json @@ -0,0 +1,18 @@ +{ + "name": "INTERFACE_RENEW_DHCP", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1799, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_CURRENT_ADDRESS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_CURRENT_ADDRESS.json new file mode 100644 index 0000000..a6148e0 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_CURRENT_ADDRESS.json @@ -0,0 +1,49 @@ +{ + "name": "IPV4_CURRENT_ADDRESS", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1797, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "address", + "type": "bytes", + "notes": "All zeros means IPV4_UNCONFIGURED.", + "format": "ipv4" + }, + { + "name": "netmask", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 32 } + ] + }, + { + "name": "dhcp_status", + "type": "uint8", + "labels": [ + { "name": "INACTIVE", "value": 0 }, + { "name": "ACTIVE", "value": 1 }, + { "name": "UNKNOWN", "value": 2 } + ], + "restrictToLabeled": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DEFAULT_ROUTE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DEFAULT_ROUTE.json new file mode 100644 index 0000000..586392e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DEFAULT_ROUTE.json @@ -0,0 +1,27 @@ +{ + "name": "IPV4_DEFAULT_ROUTE", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1802, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "default_route", + "type": "bytes", + "notes": "All zeros means NO_DEFAULT_ROUTE.", + "format": "ipv4" + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DHCP_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DHCP_MODE.json new file mode 100644 index 0000000..eb5685f --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_DHCP_MODE.json @@ -0,0 +1,37 @@ +{ + "name": "IPV4_DHCP_MODE", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1795, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "mode", + "type": "boolean", + "labels": [ + { "name": "Disabled", "value": false }, + { "name": "Enabled", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_STATIC_ADDRESS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_STATIC_ADDRESS.json new file mode 100644 index 0000000..c2f9be4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_STATIC_ADDRESS.json @@ -0,0 +1,41 @@ +{ + "name": "IPV4_STATIC_ADDRESS", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1798, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "address", + "type": "bytes", + "format": "ipv4" + }, + { + "name": "netmask", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 32 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_ZEROCONF_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_ZEROCONF_MODE.json new file mode 100644 index 0000000..e1ba671 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/IPV4_ZEROCONF_MODE.json @@ -0,0 +1,37 @@ +{ + "name": "IPV4_ZEROCONF_MODE", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1796, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + } + ], + "get_response": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "mode", + "type": "boolean", + "labels": [ + { "name": "Disabled", "value": false }, + { "name": "Enabled", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/LIST_INTERFACES.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/LIST_INTERFACES.json new file mode 100644 index 0000000..bb8ad38 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-2/LIST_INTERFACES.json @@ -0,0 +1,32 @@ +{ + "name": "LIST_INTERFACES", + "notes": "E1.37-2", + "manufacturer_id": 0, + "pid": 1792, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "interfaces", + "type": "list", + "itemType": { + "type": "compound", + "subtypes": [ + { + "name": "id", + "type": "uint32", + "ranges": [ + { "minimum": 1, "maximum": 4294967040 } + ] + }, + { + "name": "hardware_type", + "type": "uint16", + "resources": [ "https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml" ] + } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/ADD_TAG.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/ADD_TAG.json new file mode 100644 index 0000000..521f496 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/ADD_TAG.json @@ -0,0 +1,16 @@ +{ + "name": "ADD_TAG", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1618, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "tag", + "type": "string", + "maxLength": 32 + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CHECK_TAG.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CHECK_TAG.json new file mode 100644 index 0000000..cb1e97a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CHECK_TAG.json @@ -0,0 +1,25 @@ +{ + "name": "CHECK_TAG", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1620, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices" ], + "set_request": [ + { + "name": "tag", + "type": "string", + "maxLength": 32 + } + ], + "set_response": [ + { + "name": "status", + "type": "boolean", + "labels": [ + { "name": "Not Present", "value": false }, + { "name": "Present", "value": true } + ] + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CLEAR_TAGS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CLEAR_TAGS.json new file mode 100644 index 0000000..487f4f3 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/CLEAR_TAGS.json @@ -0,0 +1,10 @@ +{ + "name": "CLEAR_TAGS", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1621, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/COMMS_STATUS_NSC.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/COMMS_STATUS_NSC.json new file mode 100644 index 0000000..a0831f4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/COMMS_STATUS_NSC.json @@ -0,0 +1,63 @@ +{ + "name": "COMMS_STATUS_NSC", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 23, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { + "name": "supported", + "type": "bitField", + "size": 8, + "bits": [ + { "name": "additive_checksum", "index": 0 }, + { "name": "packet_count", "index": 1 }, + { "name": "most_recent_slot_count", "index": 2 }, + { "name": "min_slot_count", "index": 3 }, + { "name": "max_slot_count", "index": 4 }, + { "name": "error_count", "index": 5 } + ] + }, + { "name": "additive_checksum", "type": "uint32" }, + { + "name": "packet_count", + "type": "uint32", + "labels": [ + { "name": "Not Supported", "value": 4294967295 } + ] + }, + { + "name": "most_recent_slot_count", + "type": "uint16", + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "min_slot_count", + "type": "uint16", + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "max_slot_count", + "type": "uint16", + "labels": [ + { "name": "Not Supported", "value": 65535 } + ] + }, + { + "name": "error_count", + "type": "uint32", + "labels": [ + { "name": "Not Supported", "value": 4294967295 } + ] + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_INFO_OFFSTAGE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_INFO_OFFSTAGE.json new file mode 100644 index 0000000..be8442d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_INFO_OFFSTAGE.json @@ -0,0 +1,135 @@ +{ + "name": "DEVICE_INFO_OFFSTAGE", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 212, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "root_personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { + "name": "subdevice", + "type": "uint16", + "labels": [ + { "name": "root", "value": 0 } + ] + }, + { + "name": "subdevice_personality", + "type": "uint8", + "labels": [ + { "name": "root", "value": 0 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "$ref": "#/get_request/1" }, + { "$ref": "#/get_request/2" }, + { "name": "protocol_major", "type": "uint8" }, + { "name": "protocol_minor", "type": "uint8" }, + { "name": "device_model_id", "type": "uint16" }, + { + "name": "product_category", + "type": "uint16", + "labels": [ + { "name": "NOT_DECLARED", "value": 0 }, + { "name": "FIXTURE", "value": 256 }, + { "name": "FIXTURE_FIXED", "value": 257 }, + { "name": "FIXTURE_MOVING_YOKE", "value": 258 }, + { "name": "FIXTURE_MOVING_MIRROR", "value": 259 }, + { "name": "FIXTURE_OTHER", "value": 511 }, + { "name": "FIXTURE_ACCESSORY", "value": 512 }, + { "name": "FIXTURE_ACCESSORY_COLOR", "value": 513 }, + { "name": "FIXTURE_ACCESSORY_YOKE", "value": 514 }, + { "name": "FIXTURE_ACCESSORY_MIRROR", "value": 515 }, + { "name": "FIXTURE_ACCESSORY_EFFECT", "value": 516 }, + { "name": "FIXTURE_ACCESSORY_BEAM", "value": 517 }, + { "name": "FIXTURE_ACCESSORY_OTHER", "value": 767 }, + { "name": "PROJECTOR", "value": 768 }, + { "name": "PROJECTOR_FIXED", "value": 769 }, + { "name": "PROJECTOR_MOVING_YOKE", "value": 770 }, + { "name": "PROJECTOR_MOVING_MIRROR", "value": 771 }, + { "name": "PROJECTOR_OTHER", "value": 1023 }, + { "name": "ATMOSPHERIC", "value": 1024 }, + { "name": "ATMOSPHERIC_EFFECT", "value": 1025 }, + { "name": "ATMOSPHERIC_PYRO", "value": 1026 }, + { "name": "ATMOSPHERIC_OTHER", "value": 1279 }, + { "name": "DIMMER", "value": 1280 }, + { "name": "DIMMER_AC_INCANDESCENT", "value": 1281 }, + { "name": "DIMMER_AC_FLUORESCENT", "value": 1282 }, + { "name": "DIMMER_AC_COLD_CATHODE", "value": 1283 }, + { "name": "DIMMER_AC_NONDIM", "value": 1284 }, + { "name": "DIMMER_AC_ELV", "value": 1285 }, + { "name": "DIMMER_AC_OTHER", "value": 1286 }, + { "name": "DIMMER_DC_LEVEL", "value": 1287 }, + { "name": "DIMMER_DC_PWM", "value": 1288 }, + { "name": "DIMMER_CS_LED", "value": 1289 }, + { "name": "DIMMER_OTHER", "value": 1535 }, + { "name": "POWER", "value": 1536 }, + { "name": "POWER_CONTROL", "value": 1537 }, + { "name": "POWER_SOURCE", "value": 1538 }, + { "name": "POWER_OTHER", "value": 1791 }, + { "name": "SCENIC", "value": 1792 }, + { "name": "SCENIC_DRIVE", "value": 1793 }, + { "name": "SCENIC_OTHER", "value": 2047 }, + { "name": "DATA", "value": 2048 }, + { "name": "DATA_DISTRIBUTION", "value": 2049 }, + { "name": "DATA_CONVERSION", "value": 2050 }, + { "name": "DATA_OTHER", "value": 2303 }, + { "name": "AV", "value": 2304 }, + { "name": "AV_AUDIO", "value": 2305 }, + { "name": "AV_VIDEO", "value": 2306 }, + { "name": "AV_OTHER", "value": 2559 }, + { "name": "MONITOR", "value": 2560 }, + { "name": "MONITOR_AC_LINE_POWER", "value": 2561 }, + { "name": "MONITOR_DC_POWER", "value": 2562 }, + { "name": "MONITOR_ENVIRONMENTAL", "value": 2563 }, + { "name": "MONITOR_OTHER", "value": 2815 }, + { "name": "CONTROL", "value": 28672 }, + { "name": "CONTROL_CONTROLLER", "value": 28673 }, + { "name": "CONTROL_BACKUP_DEVICE", "value": 28674 }, + { "name": "CONTROL_OTHER", "value": 28927 }, + { "name": "TEST", "value": 28928 }, + { "name": "TEST_EQUIPMENT", "value": 28929 }, + { "name": "TEST_OTHER", "value": 29183 }, + { "name": "OTHER", "value": 32767 } + ] + }, + { "name": "software_version_id", "type": "uint32" }, + { + "name": "dmx_footprint", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 512 } + ] + }, + { + "name": "current_personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "personality_count", "type": "uint8" }, + { + "name": "dmx_start_address", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 512 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "No Footprint", "value": 65535 } + ] + }, + { "name": "sub_device_count", "type": "uint16" }, + { "name": "sensor_count", "type": "uint8" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_UNIT_NUMBER.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_UNIT_NUMBER.json new file mode 100644 index 0000000..342e046 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DEVICE_UNIT_NUMBER.json @@ -0,0 +1,21 @@ +{ + "name": "DEVICE_UNIT_NUMBER", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1622, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "unit_number", + "type": "uint32", + "labels": [ + { "name": "Unset", "value": 0 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DMX_PERSONALITY_ID.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DMX_PERSONALITY_ID.json new file mode 100644 index 0000000..d5d0dc6 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/DMX_PERSONALITY_ID.json @@ -0,0 +1,22 @@ +{ + "name": "DMX_PERSONALITY_ID", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 226, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "personality", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "name": "major_id", "type": "uint32" }, + { "name": "minor_id", "type": "uint32" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/FIRMWARE_URL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/FIRMWARE_URL.json new file mode 100644 index 0000000..0cb65e8 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/FIRMWARE_URL.json @@ -0,0 +1,17 @@ +{ + "name": "FIRMWARE_URL", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 210, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "url", + "type": "string", + "notes": "The spec says that the minimum length is 5, but we shouldn't restrict because that would imply we know what the URL scheme is.", + "format": "url" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/IDENTIFY_TIMEOUT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/IDENTIFY_TIMEOUT.json new file mode 100644 index 0000000..7462e6e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/IDENTIFY_TIMEOUT.json @@ -0,0 +1,23 @@ +{ + "name": "IDENTIFY_TIMEOUT", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 4176, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "timeout", + "type": "uint16", + "units": 21, + "prefixPower": 0, + "labels": [ + { "name": "Disabled", "value": 0 } + ] + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": "get_response", + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/LIST_TAGS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/LIST_TAGS.json new file mode 100644 index 0000000..9f718d2 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/LIST_TAGS.json @@ -0,0 +1,16 @@ +{ + "name": "LIST_TAGS", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1617, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "tags", + "type": "bytes", + "notes": "NUL-delimited." + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/MANUFACTURER_URL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/MANUFACTURER_URL.json new file mode 100644 index 0000000..05aae77 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/MANUFACTURER_URL.json @@ -0,0 +1,17 @@ +{ + "name": "MANUFACTURER_URL", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 208, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "url", + "type": "string", + "notes": "The spec says that the minimum length is 5, but we shouldn't restrict because that would imply we know what the URL scheme is.", + "format": "url" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON.json new file mode 100644 index 0000000..771db13 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON.json @@ -0,0 +1,19 @@ +{ + "name": "METADATA_JSON", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 83, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "pid", "type": "uint16" } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "json", + "type": "string", + "format": "json" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON_URL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON_URL.json new file mode 100644 index 0000000..4b49ace --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_JSON_URL.json @@ -0,0 +1,16 @@ +{ + "name": "METADATA_JSON_URL", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 84, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "url", + "type": "string", + "format": "url" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_PARAMETER_VERSION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_PARAMETER_VERSION.json new file mode 100644 index 0000000..923e84b --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/METADATA_PARAMETER_VERSION.json @@ -0,0 +1,18 @@ +{ + "name": "METADATA_PARAMETER_VERSION", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 82, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { "name": "pid", "type": "uint16" } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "version", + "type": "uint16" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/POWER_OFF_READY.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/POWER_OFF_READY.json new file mode 100644 index 0000000..ad3e34a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/POWER_OFF_READY.json @@ -0,0 +1,19 @@ +{ + "name": "POWER_OFF_READY", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 4177, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "state", + "type": "boolean", + "labels": [ + { "name": "Not Ready", "value": false }, + { "name": "Ready", "value": true } + ] + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/PRODUCT_URL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/PRODUCT_URL.json new file mode 100644 index 0000000..0415439 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/PRODUCT_URL.json @@ -0,0 +1,17 @@ +{ + "name": "PRODUCT_URL", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 209, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "url", + "type": "string", + "notes": "The spec says that the minimum length is 5, but we shouldn't restrict because that would imply we know what the URL scheme is.", + "format": "url" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/REMOVE_TAG.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/REMOVE_TAG.json new file mode 100644 index 0000000..bec5482 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/REMOVE_TAG.json @@ -0,0 +1,16 @@ +{ + "name": "REMOVE_TAG", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1619, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { + "name": "tag", + "type": "string", + "maxLength": 32 + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_TYPE_CUSTOM.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_TYPE_CUSTOM.json new file mode 100644 index 0000000..3f0fd0d --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_TYPE_CUSTOM.json @@ -0,0 +1,25 @@ +{ + "name": "SENSOR_TYPE_CUSTOM", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 528, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "sensor_type", + "type": "uint8", + "ranges": [ + { "minimum": 128, "maximum": 255 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "label", + "type": "string", + "maxLength": 32 + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_UNIT_CUSTOM.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_UNIT_CUSTOM.json new file mode 100644 index 0000000..1db4c71 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SENSOR_UNIT_CUSTOM.json @@ -0,0 +1,25 @@ +{ + "name": "SENSOR_UNIT_CUSTOM", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 529, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "sensor_unit", + "type": "uint8", + "ranges": [ + { "minimum": 128, "maximum": 255 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "label", + "type": "string", + "maxLength": 32 + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SERIAL_NUMBER.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SERIAL_NUMBER.json new file mode 100644 index 0000000..2873a47 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SERIAL_NUMBER.json @@ -0,0 +1,16 @@ +{ + "name": "SERIAL_NUMBER", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 211, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "serial_number", + "type": "string", + "maxLength": 231 + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SHIPPING_LOCK.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SHIPPING_LOCK.json new file mode 100644 index 0000000..79f7003 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/SHIPPING_LOCK.json @@ -0,0 +1,35 @@ +{ + "name": "SHIPPING_LOCK", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 1616, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { + "name": "lock_state", + "type": "uint8", + "labels": [ + { "name": "UNLOCKED", "value": 0 }, + { "name": "LOCKED", "value": 1 }, + { "name": "PARTIALLY_LOCKED", "value": 2 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "lock_state", + "type": "uint8", + "notes": "The list here is more restrictive than for getting the lock state. Do we want to add states and maybe descriptions?", + "labels": [ + { "name": "Unlocked", "value": 0 }, + { "name": "Locked", "value": 1 } + ], + "restrictToLabeled": true + } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/TEST_DATA.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/TEST_DATA.json new file mode 100644 index 0000000..71d2a4a --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-5/TEST_DATA.json @@ -0,0 +1,33 @@ +{ + "name": "TEST_DATA", + "notes": "E1.37-5", + "manufacturer_id": 0, + "pid": 22, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "pattern_length", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 4096 } + ] + } + ], + "get_response": [ + { + "name": "pattern_data", + "type": "bytes", + "maxLength": 4096 + } + ], + "set_request_subdevice_range": [ "root", "subdevices" ], + "set_request": [ + { + "name": "loopback_data", + "type": "bytes", + "maxLength": 231 + } + ], + "set_response": "set_request" +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_DISCOVERY.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_DISCOVERY.json new file mode 100644 index 0000000..c762a78 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_DISCOVERY.json @@ -0,0 +1,39 @@ +{ + "name": "BACKGROUND_DISCOVERY", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2312, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "name": "enabled", "type": "boolean" } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY.json new file mode 100644 index 0000000..4baa465 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY.json @@ -0,0 +1,32 @@ +{ + "name": "BACKGROUND_QUEUED_STATUS_POLICY", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2318, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { + "name": "policy_setting", + "type": "uint8", + "notes": "See \"Table 7-3: Control Field\" in ANSI E1.20-202x. The labeled values are just informative, but this contradicts with the spec (E1.37-7) saying \"must support this minimum set\".", + "labels": [ + { "name": "STATUS_NONE", "value": 0 }, + { "name": "STATUS_ADVISORY", "value": 1 }, + { "name": "STATUS_WARNING", "value": 2 }, + { "name": "STATUS_ERROR", "value": 3 } + ] + }, + { + "name": "policy_setting_count", + "type": "uint8", + "notes": "Breaking with other message definitions (and this is not mentioned in the spec), the policy setting value starts at 0, unlike others which start at 1. This means that the maximum value is 254 since the count can be at most 255." + } + ], + "set_request_subdevice_range": [ "root", "subdevices", "broadcast" ], + "set_request": [ + { "$ref": "#/get_response/0" } + ], + "set_response": [] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION.json new file mode 100644 index 0000000..92e17a9 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION.json @@ -0,0 +1,29 @@ +{ + "name": "BACKGROUND_QUEUED_STATUS_POLICY_DESCRIPTION", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2319, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "policy", + "type": "uint8", + "labels": [ + { "name": "Status Type None", "value": 0 }, + { "name": "Status Type Advisory and higher", "value": 1 }, + { "name": "Status Type Warning and higher", "value": 2 }, + { "name": "Status Type Error", "value": 3 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BINDING_CONTROL_FIELDS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BINDING_CONTROL_FIELDS.json new file mode 100644 index 0000000..d5634a4 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/BINDING_CONTROL_FIELDS.json @@ -0,0 +1,37 @@ +{ + "name": "BINDING_CONTROL_FIELDS", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2317, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + }, + { + "name": "uid", + "type": "bytes", + "format": "uid" + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "$ref": "#/get_request/1" }, + { + "name": "control", + "type": "uint16", + "notes": "See \"Table 7-3: Control Field\" in ANSI E1.20-202x." + }, + { + "name": "binding_uid", + "type": "bytes", + "notes": "All zeros means no Binding UID present in the DISC_MUTE response.", + "format": "uid" + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/DISCOVERY_STATE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/DISCOVERY_STATE.json new file mode 100644 index 0000000..b2037c1 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/DISCOVERY_STATE.json @@ -0,0 +1,74 @@ +{ + "name": "DISCOVERY_STATE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2311, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "device_count", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "DISCOVERY_COUNT_INCOMPLETE", "value": 0 }, + { "name": "DISCOVERY_COUNT_UNKNOWN", "value": 65535 } + ] + }, + { + "name": "state", + "type": "uint8", + "ranges": [ + { "minimum": 0, "maximum": 223 } + ], + "labels": [ + { "name": "INCOMPLETE", "value": 0 }, + { "name": "INCREMENTAL", "value": 1 }, + { "name": "FULL", "value": 2 }, + { "name": "NOT_ACTIVE", "value": 3 } + ] + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { + "name": "state", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 223 } + ], + "labels": [ + { "name": "INCREMENTAL", "value": 1 }, + { "name": "FULL", "value": 2 }, + { "name": "NOT_ACTIVE", "value": 3 } + ] + } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LABEL.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LABEL.json new file mode 100644 index 0000000..0f49f88 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LABEL.json @@ -0,0 +1,44 @@ +{ + "name": "ENDPOINT_LABEL", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2309, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST.json new file mode 100644 index 0000000..6c34502 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST.json @@ -0,0 +1,37 @@ +{ + "name": "ENDPOINT_LIST", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2304, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { "name": "list_change_number", "type": "uint32" }, + { + "name": "endpoints", + "type": "list", + "itemType": { + "type": "compound", + "subtypes": [ + { + "name": "id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + }, + { + "name": "type", + "type": "uint8", + "labels": [ + { "name": "VIRTUAL", "value": 0 }, + { "name": "PHYSICAL", "value": 1 } + ], + "restrictToLabeled": true + } + ] + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST_CHANGE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST_CHANGE.json new file mode 100644 index 0000000..8f6720e --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_LIST_CHANGE.json @@ -0,0 +1,12 @@ +{ + "name": "ENDPOINT_LIST_CHANGE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2305, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [], + "get_response": [ + { "name": "list_change_number", "type": "uint32" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_MODE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_MODE.json new file mode 100644 index 0000000..9c83db9 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_MODE.json @@ -0,0 +1,48 @@ +{ + "name": "ENDPOINT_MODE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2308, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "mode", + "type": "uint8", + "labels": [ + { "name": "Disabled", "value": 0 }, + { "name": "Input", "value": 1 }, + { "name": "Output", "value": 2 } + ], + "restrictToLabeled": true + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDERS.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDERS.json new file mode 100644 index 0000000..0437b36 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDERS.json @@ -0,0 +1,30 @@ +{ + "name": "ENDPOINT_RESPONDERS", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2315, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "name": "list_change_number", "type": "uint32" }, + { + "name": "uids", + "type": "list", + "itemType": { + "name": "uid", + "type": "bytes", + "format": "uid" + } + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDER_LIST_CHANGE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDER_LIST_CHANGE.json new file mode 100644 index 0000000..c7cee97 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_RESPONDER_LIST_CHANGE.json @@ -0,0 +1,21 @@ +{ + "name": "ENDPOINT_RESPONDER_LIST_CHANGE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2316, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "name": "list_change_number", "type": "uint32" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING.json new file mode 100644 index 0000000..2f8c9c0 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING.json @@ -0,0 +1,46 @@ +{ + "name": "ENDPOINT_TIMING", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2313, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + }, + { "name": "setting_count", "type": "uint8" } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING_DESCRIPTION.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING_DESCRIPTION.json new file mode 100644 index 0000000..e1cbb6b --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TIMING_DESCRIPTION.json @@ -0,0 +1,26 @@ +{ + "name": "ENDPOINT_TIMING_DESCRIPTION", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2314, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "setting", + "type": "uint8", + "ranges": [ + { "minimum": 1, "maximum": 255 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "description", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TO_UNIVERSE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TO_UNIVERSE.json new file mode 100644 index 0000000..e8db959 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/ENDPOINT_TO_UNIVERSE.json @@ -0,0 +1,59 @@ +{ + "name": "ENDPOINT_TO_UNIVERSE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2307, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "universe", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "Unpatched", "value": 0 }, + { "name": "Composite", "value": 65535 } + ] + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { + "name": "universe", + "type": "uint16", + "ranges": [ + { "minimum": 0, "maximum": 63999 } + ], + "labels": [ + { "name": "Unpatched", "value": 0 } + ] + } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/IDENTIFY_ENDPOINT.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/IDENTIFY_ENDPOINT.json new file mode 100644 index 0000000..16eed74 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/IDENTIFY_ENDPOINT.json @@ -0,0 +1,46 @@ +{ + "name": "IDENTIFY_ENDPOINT", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2306, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { + "name": "identify_state", + "type": "boolean", + "labels": [ + { "name": "Off", "value": false }, + { "name": "On", "value": true } + ] + } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/RDM_TRAFFIC_ENABLE.json b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/RDM_TRAFFIC_ENABLE.json new file mode 100644 index 0000000..6b091dd --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/Defines/e1.37-7/RDM_TRAFFIC_ENABLE.json @@ -0,0 +1,39 @@ +{ + "name": "RDM_TRAFFIC_ENABLE", + "notes": "E1.37-7", + "manufacturer_id": 0, + "pid": 2310, + "version": 1, + "get_request_subdevice_range": [ "root" ], + "get_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 } + ] + } + ], + "get_response": [ + { "$ref": "#/get_request/0" }, + { "name": "rdm_enabled", "type": "boolean" } + ], + "set_request_subdevice_range": [ "root" ], + "set_request": [ + { + "name": "endpoint_id", + "type": "uint16", + "ranges": [ + { "minimum": 1, "maximum": 63999 }, + { "minimum": 65535, "maximum": 65535 } + ], + "labels": [ + { "name": "BROADCAST", "value": 65535 } + ] + }, + { "$ref": "#/get_response/1" } + ], + "set_response": [ + { "$ref": "#/set_request/0" } + ] +} diff --git a/RDMSharp/Resources/JSON-Defines/1.0.0/schema.json b/RDMSharp/Resources/JSON-Defines/1.0.0/schema.json new file mode 100644 index 0000000..f8fa984 --- /dev/null +++ b/RDMSharp/Resources/JSON-Defines/1.0.0/schema.json @@ -0,0 +1,599 @@ +{ + "$id": "https://www.esta.org/e1.37-5/schemas/1.0.0/schema.json", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Parameter Message", + "description": "The schema for the Parameter Metadata Language from Section 5 of E1.37-5. This schema is subject to change.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "manufacturer_id": { + "$comment": "Manufacturer IDs are assigned by ESTA and are commonly expressed in hexadecimal. Users may expect to see these values in the UI as hexadecimal.", + "title": "Manufacturer ID", + "description": "The Manufacturer ID.", + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "device_model_id": { + "$comment": "The Device Model ID is a 16-bit value determined by the manufacturer. Users may expect to see these values in the UI as hexadecimal.", + "title": "Device Model ID", + "description": "The Device Model ID.", + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "software_version_id": { + "$comment": "The Software Version ID is a 32-bit value determined by the manufacturer.", + "title": "Software Version ID", + "description": "The Software Version ID.", + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + "pid": { + "title": "PID", + "description": "The parameter ID.", + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "version": { + "title": "Version", + "description": "The parameter descriptor version.", + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "get_request_subdevice_range": { + "$comment": "'subdevicesForRequests' already contains a title and description", + "description": "Absence implies a default value of [\"root\"].", + "$ref": "#/$defs/subdevicesForRequests", + "default": [ "root" ] + }, + "get_request": { + "$comment": "'command' already contains a description", + "title": "GET Command", + "$ref": "#/$defs/command" + }, + "get_response_subdevice_range": { + "$comment": "'subdevicesForResponses' already contains a title and description", + "description": "Absence implies a default value of [\"match\"].", + "$ref": "#/$defs/subdevicesForResponses", + "default": [ "match" ] + }, + "get_response": { + "$comment": "'command' already contains a description", + "title": "GET Command Response", + "$ref": "#/$defs/command" + }, + "set_request_subdevice_range": { + "$comment": "'subdevicesForRequests' already contains a title and description", + "description": "Absence implies a default value of [\"root\"].", + "$ref": "#/$defs/subdevicesForRequests", + "default": [ "root" ] + }, + "set_request": { + "$comment": "'command' already contains a description", + "title": "SET Command", + "$ref": "#/$defs/command" + }, + "set_response_subdevice_range": { + "$comment": "'subdevicesForResponses' already contains a title and description", + "description": "Absence implies a default value of [\"match\"].", + "$ref": "#/$defs/subdevicesForResponses", + "default": [ "match" ] + }, + "set_response": { + "$comment": "'command' already contains a description", + "title": "SET Command Response", + "$ref": "#/$defs/command" + } + }, + "unevaluatedProperties": false, + "required": [ "manufacturer_id", "pid", "version" ], + "dependentRequired": { + "get_request": [ "get_response" ], + "get_response": [ "get_request" ], + "set_request": [ "set_response" ], + "set_response": [ "set_request" ] + }, + "$defs": { + "bit": { + "title": "Bit", + "description": "One bit in a bit field.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "index": { + "title": "Index", + "description": "Zero-based index of this bit.", + "type": "integer", + "minimum": 0 + }, + "reserved": { + "title": "Reserved", + "description": "Indicates that this bit is unused or reserved. Note that this value does not need to be specified for absent bits; they are already assumed to be reserved.", + "type": "boolean" + }, + "valueIfReserved": { + "title": "Value If Reserved", + "description": "The assumed value when the bit is marked as reserved. Absence implies a default value of false.", + "type": "boolean", + "default": false + } + }, + "unevaluatedProperties": false, + "required": [ "index" ] + }, + "bitFieldType": { + "title": "Bit Field Type", + "description": "A bit field, a collection of 'bit' items. The \"size\" field is used to specify the number of bits in this bit field, a multiple of 8. It is an error if the size is less than the number of defined bits. Bits that are not specified are assumed to be reserved, having a value equal to the \"valueForUnspecified\" value.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "bitField" }, + "bits": { + "title": "Bits", + "description": "A list of the bits in the bit field.", + "type": "array", + "items": { "$ref": "#/$defs/bit" }, + "uniqueItems": true + }, + "size": { + "title": "Size", + "description": "The size, in multiples-of-8 bits, of this bit field. It is an error if the size is less than the number of defined bits.", + "type": "integer", + "minimum": 0, + "multipleOf": 8 + }, + "valueForUnspecified": { + "title": "Value for Unspecified", + "description": "The default value to use for any unspecified bits. Absence implies a default value of false.", + "type": "boolean", + "default": false + } + }, + "required": [ "type", "size", "bits" ] + }, + "booleanType": { + "title": "Boolean Type", + "description": "A Boolean value. This corresponds to the intent of DS_BOOLEAN in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification, a 1-byte zero-or-one value.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "boolean" }, + "labels": { + "title": "Labels", + "description": "A list of labels that name special values.", + "type": "array", + "items": { "$ref": "#/$defs/labeledBoolean" }, + "uniqueItems": true, + "maxItems": 2 + } + }, + "required": [ "type" ] + }, + "bytesType": { + "title": "Bytes Type", + "description": "An array of bytes. The minimum and maximum length properties are not required, but it is a good idea to specify their values for unknown bytes types. This corresponds to the intent of DS_UNSIGNED_BYTE in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "bytes" }, + "format": { + "title": "Interpretation Format", + "description": "This field describes how to interpret the value. It can be one of the bytes types defined in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification (or other add-on specifications), or it can be something manufacturer-specific. Be aware, however, that anything not defined here may not be understood by a controller or UI. The known bytes types include: ipv4 (4 bytes), ipv6 (16 bytes), mac-address (6 bytes), uid (6 bytes), and uuid (16 bytes).", + "type": "string" + }, + "minLength": { + "title": "Minimum Length", + "description": "The minimum bytes length. Care must be taken to make sure this doesn't contradict any \"maxLength\" value. It is an error if there is a contradiction.", + "type": "integer", + "minimum": 0 + }, + "maxLength": { + "title": "Maximum Length", + "description": "The maximum bytes length. Care must be taken to make sure this doesn't contradict any \"minLength\" value. It is an error if there is a contradiction. If a responder requires a controller to limit the number of bytes sent, then this value should be set.", + "type": "integer", + "minimum": 0 + } + }, + "required": [ "type" ] + }, + "command": { + "$comment": "The title is specific to where this used, and so no title is defined here", + "description": "The contents of an RDM command: 1. a collection of 'field' items, each a simple or compound type, 2. a single 'field' item, or 3. a duplicate command.", + "oneOf": [ + { + "title": "List of Fields", + "description": "The command consists of zero or more fields.", + "type": "array", + "items": { + "$ref": "#/$defs/oneOfTypes", + "unevaluatedProperties": false + }, + "uniqueItems": true + }, + { + "title": "Single Field", + "description": "The command consists of a single field.", + "$ref": "#/$defs/oneOfTypes", + "unevaluatedProperties": false + }, + { + "title": "Command Duplicate", + "description": "Indicates that a command is a duplicate of one of the other commands. Using this feature can potentially save space. It is an error if the command refers to itself.", + "enum": [ + "get_request", + "get_response", + "set_request", + "set_response", + "different_pid" + ] + } + ] + }, + "commonPropertiesForNamed": { + "$comment": "Defines a set of properties common to everything having a name", + "properties": { + "name": { + "title": "Name", + "description": "The object name. If this is not intended for UI display, then a displayable name can be added with \"displayName\". This property can, for example, be used as the key for lookup into a table of localized display names.", + "type": "string", + "minLength": 1 + }, + "displayName": { + "title": "Display Name", + "description": "An optional name for UI display. This might be used, for example, as the fallback or default display name if, say, a localized name isn't specified or found via the \"name\" property.", + "type": "string", + "minLength": 1 + }, + "notes": { + "title": "Notes", + "description": "Contains any notes about this object.", + "type": "string" + }, + "resources": { + "title": "List of Resources", + "description": "Informative URLs pointing to a specification or more information for this field type.", + "type": "array", + "items": { + "type": "string", + "format": "uri-reference" + } + } + } + }, + "compoundType": { + "title": "Compound Type", + "description": "Defines a compound type, a type used to combine other types. This is useful for including in lists. This corresponds to the intent of DS_GROUP in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "compound" }, + "subtypes": { + "title": "Subtypes", + "description": "A list of types composing this compound type.", + "type": "array", + "items": { + "$ref": "#/$defs/oneOfTypes", + "unevaluatedProperties": false + } + } + }, + "required": [ "type", "subtypes" ] + }, + "integerType": { + "title": "Integer Type", + "description": "A signed or unsigned integer, can have an optional prefix, unit, and range. This corresponds to the intent of any of the integer types in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { + "enum": [ + "int8", + "int16", + "int32", + "int64", + "int128", + "uint8", + "uint16", + "uint32", + "uint64", + "uint128" + ] + }, + "labels": { + "title": "Labels", + "description": "A list of labels that name special values.", + "type": "array", + "items": { "$ref": "#/$defs/labeledInteger" }, + "uniqueItems": true + }, + "restrictToLabeled": { + "title": "Restrict to Labeled", + "description": "Whether to restrict the allowed values to those that have labels. This is useful to not have to additionally specify a set of ranges. If this is set to \"true\" then \"ranges\" should not be specified.", + "type": "boolean" + }, + "ranges": { + "title": "Ranges", + "description": "A list of possible ranges for the value. The complete range is the union of all the ranges. This should not be specified if \"restrictToLabeled\" is set to 'true'.", + "type": "array", + "items": { "$ref": "#/$defs/range" }, + "uniqueItems": true + }, + "units": { + "title": "Units", + "description": "The units type, defined in Table A-13 of E1.20-2010.", + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "prefixPower": { + "title": "Prefix Power", + "description": "The power of 10 to be used as the prefix for the value. For example, -2 is used to represent 10^(-2) or the prefix centi-. Absence implies a default value of 0.", + "type": "integer", + "default": 0 + }, + "prefixBase": { + "title": "Prefix Base", + "description": "The base of the prefix. For example, to express \"kilo\", specify prefixBase=10 and prefixPower=3, and to express \"kibi\", specify prefixBase=2 and prefixPower=10 or prefixBase=1024 and prefixPower=1. Absence implies a default value of 10.", + "type": "integer", + "default": 10 + } + }, + "required": [ "type" ] + }, + "labeledBoolean": { + "title": "Labeled Boolean", + "description": "Associates a name to a Boolean value.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "value": { + "title": "Value", + "description": "The labeled value", + "type": "boolean" + } + }, + "unevaluatedProperties": false, + "required": [ "name", "value" ] + }, + "labeledInteger": { + "title": "Labeled Integer", + "description": "Associates a name to an integer value.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "value": { + "title": "Value", + "description": "The labeled value", + "type": "integer" + } + }, + "unevaluatedProperties": false, + "required": [ "name", "value" ] + }, + "listType": { + "title": "List Type", + "description": "A list of objects all having the same type.", + "$comment": "The names \"minItems\" and \"maxItems\" were chosen because those match the validation keywords for arrays in the JSON schema spec", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "list" }, + "itemType": { + "title": "Item Type", + "description": "The type of each item in the list.", + "$ref": "#/$defs/oneOfTypes", + "unevaluatedProperties": false + }, + "minItems": { + "title": "Minimum List Size", + "description": "The minimum list size.", + "type": "integer", + "minimum": 0 + }, + "maxItems": { + "title": "Maximum List Size", + "description": "The maximum list size.", + "type": "integer", + "minimum": 0 + } + }, + "required": [ "type", "itemType" ] + }, + "oneOfTypes": { + "$comment": "One of any of the types. This provides a single location to keep the list. None of the types here specify \"unevaluatedProperties\", so if extra properties are to be disallowed, then that must be specified by the referencer of this schema. This will make sorting through any errors easier", + "oneOf": [ + { "$ref": "#/$defs/bitFieldType" }, + { "$ref": "#/$defs/booleanType" }, + { "$ref": "#/$defs/bytesType" }, + { "$ref": "#/$defs/compoundType" }, + { "$ref": "#/$defs/integerType" }, + { "$ref": "#/$defs/listType" }, + { "$ref": "#/$defs/pdEnvelopeType" }, + { "$ref": "#/$defs/refType" }, + { "$ref": "#/$defs/stringType" } + ] + }, + "pdEnvelopeType": { + "title": "PD Envelope Type", + "description": "Contains a length/data pair for one Parameter Data item, where the length is an unsigned 8-bit value and the data has 'length' bytes. This exists to provide a schema definition for the 'envelope' of a PDL/PD pair.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "pdEnvelope" }, + "length": { + "title": "Data Length", + "description": "The data length can be optionally specified.", + "type": "integer", + "minimum": 0, + "maximum": 255 + } + }, + "required": [ "type" ] + }, + "range": { + "title": "Range", + "description": "Defines an inclusive range of numbers. If one of the bounds is undefined then it is assumed to be the bound appropriate for the type.", + "type": "object", + "properties": { + "minimum": { + "title": "Minimum", + "description": "The lower bound, inclusive.", + "type": "integer" + }, + "maximum": { + "title": "Maximum", + "description": "The upper bound, inclusive.", + "type": "integer" + } + }, + "additionalProperties": false + }, + "refType": { + "title": "Reference Type", + "description": "Specifies a reference to another value, a URI whose fragment part, if present, is a JSON Pointer. See [URI Syntax](https://www.rfc-editor.org/rfc/rfc3986.html) and [JSON Pointer](https://www.rfc-editor.org/rfc/rfc6901.html). It is an error if this does not point to an object having one of the types in \"#/$defs/oneOfTypes\", or if there is a circular reference. Any common properties defined in this field will override any defined by the referenced field.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "$ref": { + "title": "Reference", + "description": "Points to a resource, a URI.", + "type": "string", + "format": "uri-reference" + } + }, + "additionalProperties": false, + "required": [ "$ref" ] + }, + "stringType": { + "title": "String Type", + "description": "A UTF-8-encoded string having a possibly bounded size. Implementations may need to use either a NUL terminator or another \"length\" field for multi-field messages where a string is followed by another field, so that its boundary can be determined. This corresponds to the intent of DS_STRING in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification. Characters are defined by the [JSON specification](https://www.rfc-editor.org/rfc/rfc8259.html) (see [Section 7: Strings](https://www.rfc-editor.org/rfc/rfc8259.html#section-7) and [Section 8: String and Character Issues](https://www.rfc-editor.org/rfc/rfc8259.html#section-8)). Note that characters are either encoded directly in UTF-8 or escaped using the scheme described by the specification.", + "type": "object", + "$ref": "#/$defs/commonPropertiesForNamed", + "properties": { + "type": { "const": "string" }, + "format": { + "title": "Interpretation Format", + "description": "This field describes how to interpret the string value. It can be one of the string types defined in \"Table A-15: Data Type Defines\" of the E1.20-2010 specification (or other add-on specifications), one of the defined formats from the [JSON Schema Validation specification](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3), or it can be something manufacturer-specific. It is suggested that a URI or other unique naming convention be used to uniquely identify these. Be aware, however, that anything not defined here may not be understood by a controller or UI. The known string types from E1.20-2010 (and add-ons) include: \"hostname\" (https://www.rfc-editor.org/rfc/rfc1123.html#section-2, https://www.rfc-editor.org/rfc/rfc3696.html#section-2, https://www.rfc-editor.org/rfc/rfc5890.html), \"json\" (https://www.rfc-editor.org/rfc/rfc8259.html), \"string\", and \"url\" (the intent of DS_URL in \"Table A-15\") (https://www.rfc-editor.org/rfc/rfc3986.html, https://www.rfc-editor.org/rfc/rfc1738.html).", + "type": "string" + }, + "pattern": { + "title": "Pattern", + "description": "An [ECMA-262 regular expression](https://www.ecma-international.org/publications/standards/Ecma-262.htm) that can be used to validate the contents of this field. They're helpful for assisting a controller or UI do message validation. It's not necessary to provide a pattern for known \"format\" types. Note that care must be taken to make sure that patterns don't contradict any \"minLength\" and \"maxLength\" values. It is an error if there is a contradiction. As well, if there are maximum or minimum sizes, it is suggested that an instance makes use of the \"minLength\" and \"maxLength\" sizes in order to support those UIs that don't support regexes.", + "type": "string", + "format": "regex" + }, + "minLength": { + "title": "Minimum Length", + "description": "The minimum string length, in characters as defined by [JSON](https://www.rfc-editor.org/rfc/rfc8259.html). Care must be taken to make sure this doesn't contradict any \"pattern\" or \"maxLength\" values. It is an error if there is a contradiction. If there are maximum or minimum sizes, it is suggested that an instance makes use of the \"minLength\" and \"maxLength\" sizes in order to support those UIs that don't support regexes.", + "type": "integer", + "minimum": 0 + }, + "maxLength": { + "title": "Maximum Length", + "description": "The maximum string length, in characters as defined by [JSON](https://www.rfc-editor.org/rfc/rfc8259.html). Care must be taken to make sure this doesn't contradict any \"pattern\" or \"minLength\" values. It is an error if there is a contradiction. If there are maximum or minimum sizes, it is suggested that an instance makes use of the \"minLength\" and \"maxLength\" sizes in order to support those UIs that don't support regexes.", + "type": "integer", + "minimum": 0 + }, + "minBytes": { + "title": "Minimum Length in Bytes", + "description": "The minimum UTF-8-encoded length in bytes. In the case that the number of characters in the string is different from the number of bytes after UTF-8 encoding, we may need to specify a minimum encoded length.", + "type": "integer", + "minimum": 0 + }, + "maxBytes": { + "title": "Maximum Length in Bytes", + "description": "The maximum UTF-8-encoded length in bytes. In the case that the number of characters in the string is different from the number of bytes after UTF-8 encoding, we may need to specify a maximum encoded length. If a responder requires a controller to limit the number of bytes sent, then this value should be set.", + "type": "integer", + "minimum": 0 + }, + "restrictToASCII": { + "title": "Restrict to ASCII", + "description": "Indicates whether the string contents should be restricted to US-ASCII.", + "type": "boolean" + } + }, + "required": [ "type" ] + }, + "subdeviceType": { + "title": "Subdevice Type", + "description": "A subdevice value. It is a 16-bit integral type and its range includes the values specified by the E1.20-2010 specification (0x0001-0x0200). It does not include the root value (0) or special all-call value (65535).", + "type": "integer", + "minimum": 1, + "maximum": 512 + }, + "subdeviceRange": { + "title": "Subdevice Range", + "description": "Defines a range of subdevices, not including the root or the special all-call value. The complete range is the union of all the ranges in the subdevice array.", + "type": "object", + "properties": { + "minimum": { + "$comment": "'subdeviceType' already contains a title and description", + "title": "Minimum", + "description": "The lower bound, inclusive.", + "$ref": "#/$defs/subdeviceType" + }, + "maximum": { + "$comment": "'subdeviceType' already contains a title and description", + "title": "Maximum", + "description": "The upper bound, inclusive.", + "$ref": "#/$defs/subdeviceType" + } + }, + "required": [ "minimum", "maximum" ], + "additionalProperties": false + }, + "subdeviceValue": { + "title": "Subdevice Value", + "description": "Defines a single subdevice or range of subdevices. Note that a \"subdevice\" here means any valid subdevice that isn't \"root\" or \"broadcast\".", + "anyOf": [ + { "$ref": "#/$defs/subdeviceRange" }, + { "$ref": "#/$defs/subdeviceType" } + ] + }, + "subdevicesForRequests": { + "title": "Subdevices in a Request", + "description": "Acceptable values for the subdevice in a GET or SET command. An empty list means allow nothing.", + "type": "array", + "items": { + "anyOf": [ + { + "enum": [ + "root", + "subdevices", + "broadcast" + ] + }, + { + "$ref": "#/$defs/subdeviceValue" + } + ] + }, + "uniqueItems": true + }, + "subdevicesForResponses": { + "title": "Subdevices in a Response", + "description": "Acceptable values for the subdevice in a GET_RESPONSE or SET_RESPONSE. An empty list means allow nothing.", + "type": "array", + "items": { + "anyOf": [ + { + "enum": [ + "root", + "subdevices", + "broadcast", + "match" + ] + }, + { + "$ref": "#/$defs/subdeviceValue" + } + ] + }, + "uniqueItems": true + } + } +} diff --git a/RDMSharpTests/Devices/TestRDMSendReceive.cs b/RDMSharpTests/Devices/TestRDMSendReceive.cs index 0c44758..f44d381 100644 --- a/RDMSharpTests/Devices/TestRDMSendReceive.cs +++ b/RDMSharpTests/Devices/TestRDMSendReceive.cs @@ -1,6 +1,4 @@ using RDMSharpTests.Devices.Mock; -using System.Diagnostics; -using System.Reflection.Metadata; namespace RDMSharpTests.RDM.Devices { diff --git a/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTestSubject.cs b/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTestSubject.cs new file mode 100644 index 0000000..7cf019b --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTestSubject.cs @@ -0,0 +1,66 @@ +using RDMSharp.Metadata; +using System.Collections.Concurrent; +using System.Reflection; + +namespace RDMSharpTests.Metadata.JSON +{ + public class MetadataJSONObjectDefineTestSubject + { + public static readonly object[] TestSubjects = getTestSubjects(); + internal static string[] GetResources() + { + var assembly = Assembly.GetExecutingAssembly(); + return assembly.GetManifestResourceNames(); + } + private static object[] getTestSubjects() + { + List instances = new List(); + List metadataVersionList = new List(); + metadataVersionList.AddRange(MetadataFactory.GetResources().Select(r => new MetadataVersion(r))); + var schemaList = MetadataFactory.GetMetadataSchemaVersions(); + ConcurrentDictionary versionSchemas = new ConcurrentDictionary(); + + foreach (var mv in metadataVersionList.Where(_mv => !_mv.IsSchema)) + { + var _schema = schemaList.First(s => s.Version.Equals(mv.Version)); + if (!versionSchemas.TryGetValue(_schema.Version, out MetadataBag schema)) + { + schema = new MetadataBag(_schema); + versionSchemas.TryAdd(_schema.Version, schema); + } + instances.Add(new MetadataJSONObjectDefineTestSubject(schema, new MetadataBag(mv))); + } + foreach (var mv in GetResources().Select(r => new MetadataVersion(r))) + { + var _schema = schemaList.First(s => s.Version.Equals(mv.Version)); + if (!versionSchemas.TryGetValue(_schema.Version, out MetadataBag schema)) + { + schema = new MetadataBag(_schema); + versionSchemas.TryAdd(_schema.Version, schema); + } + instances.Add(new MetadataJSONObjectDefineTestSubject(schema, new MetadataBag(mv.Version, mv.Name, mv.IsSchema, getContent(mv.Path), mv.Path))); + } + return instances.ToArray(); + } + private static string getContent(string path) + { + if (string.IsNullOrWhiteSpace(path)) + return null; + var assembly = typeof(MetadataJSONObjectDefineTestSubject).Assembly; + using Stream stream = assembly.GetManifestResourceStream(path); + using StreamReader reader = new StreamReader(stream); + return reader.ReadToEnd(); + } + + public readonly MetadataBag Schema; + public readonly MetadataBag Define; + + public override string ToString() => Define.Name; + + public MetadataJSONObjectDefineTestSubject(MetadataBag schema, MetadataBag define) + { + Schema = schema; + Define = define; + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTests.cs b/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTests.cs new file mode 100644 index 0000000..26167bf --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/MetadataJSONObjectDefineTests.cs @@ -0,0 +1,250 @@ +using Json.Schema; +using Newtonsoft.Json.Linq; +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace RDMSharpTests.Metadata.JSON +{ + [TestFixtureSource(typeof(MetadataJSONObjectDefineTestSubject), nameof(MetadataJSONObjectDefineTestSubject.TestSubjects))] + public class MetadataJSONObjectDefineTests + { + private readonly MetadataJSONObjectDefineTestSubject testSubject; + + public MetadataJSONObjectDefineTests(MetadataJSONObjectDefineTestSubject _TestSubject) + { + testSubject = _TestSubject; + } + + + [Test] + public void TestValidateAgainstSchema() + { + JsonSchema jsonSchema = JsonSchema.FromText(testSubject.Schema.Content); + var result = jsonSchema.Evaluate(JsonNode.Parse(testSubject.Define.Content)); + Assert.That(result, Is.Not.Null); + if (!testSubject.Define.Name.ToLower().Contains("invalid")) + Assert.That(result.IsValid, Is.True); + else if (testSubject.Define.Name.ToLower().Contains("invalid_but_schema_is_valid")) + Assert.That(result.IsValid, Is.True); + else + Assert.That(result.IsValid, Is.False); + } + [Test] + public void TestDeseriaizeAndSerialize() + { + try + { + MetadataJSONObjectDefine deserialized = JsonSerializer.Deserialize(testSubject.Define.Content); + Assert.That(deserialized.Version, Is.AtLeast(1)); + Assert.That(deserialized.Name, Is.Not.WhiteSpace); + Assert.That(deserialized.Name, Is.Not.Empty); + string serialized = JsonSerializer.Serialize(deserialized); + + var original = JToken.Parse(PrittyJSON(testSubject.Define.Content)); + var smashed = JToken.Parse(PrittyJSON(serialized)); + + Assert.Multiple(() => + { + Assert.That(JToken.DeepEquals(smashed, original)); + + + Warn.Unless(PrittyJSON(serialized), Is.EqualTo(PrittyJSON(testSubject.Define.Content))); + }); + } + catch (JsonException ex) + { + if (testSubject.Define.Name.ToLower().Contains("invalid")) + return; + +#if !NET7_0_OR_GREATER + Warn.If(ex.Message, Is.EqualTo("Unexpected JSON format Type: int128 for FieldContainer.").Or.EqualTo("Unexpected JSON format Type: uint128 for FieldContainer."), "Due to .NET6 limitations"); + return; +#else + throw; +#endif + } + } + [Test] + public void TestDeseriaizedObject() + { + MetadataJSONObjectDefine deserialized = null; + testString(testSubject.Define.ToString()); + try + { + deserialized = JsonSerializer.Deserialize(testSubject.Define.Content); + } + catch (JsonException ex) + { + if (testSubject.Define.Name.ToLower().Contains("invalid")) + return; +#if !NET7_0_OR_GREATER + Warn.If(ex.Message, Is.EqualTo("Unexpected JSON format Type: int128 for FieldContainer.").Or.EqualTo("Unexpected JSON format Type: uint128 for FieldContainer."), "Due to .NET6 limitations"); + return; +#else + throw; +#endif + } + Assert.That(deserialized.Version, Is.AtLeast(1)); + Assert.That(deserialized.Name, Is.Not.WhiteSpace); + Assert.That(deserialized.Name, Is.Not.Empty); + + testString(deserialized.ToString()); + + if (deserialized.GetRequestSubdeviceRange != null) + { + testString(string.Join("; ", deserialized.GetRequestSubdeviceRange.Select(r => r.ToString()))!); + } + if (deserialized.GetResponseSubdeviceRange != null) + { + testString(string.Join("; ", deserialized.GetResponseSubdeviceRange.Select(r => r.ToString()))!); + } + if (deserialized.SetRequestsSubdeviceRange != null) + { + testString(string.Join("; ", deserialized.SetRequestsSubdeviceRange.Select(r => r.ToString()))!); + } + if (deserialized.SetResponseSubdeviceRange != null) + { + testString(string.Join("; ", deserialized.SetResponseSubdeviceRange.Select(r => r.ToString()))!); + } + + if (deserialized.GetRequest != null) + { + testCommand(deserialized.GetRequest.Value); + deserialized.GetCommand(Command.ECommandDublicte.GetRequest, out Command? command); + if (command != null) + testCommand(command.Value); + } + + if (deserialized.GetResponse != null) + { + testCommand(deserialized.GetResponse.Value); + deserialized.GetCommand(Command.ECommandDublicte.GetResponse, out Command? command); + if (command != null) + testCommand(command.Value); + } + + if (deserialized.SetRequest != null) + { + testCommand(deserialized.SetRequest.Value); + deserialized.GetCommand(Command.ECommandDublicte.SetRequest, out Command? command); + if (command != null) + testCommand(command.Value); + } + + if (deserialized.SetResponse != null) + { + testCommand(deserialized.SetResponse.Value); + deserialized.GetCommand(Command.ECommandDublicte.SetResponse, out Command? command); + if (command != null) + testCommand(command.Value); + } + + + static void testString(string str) + { + Assert.That(str, Is.Not.WhiteSpace); + Assert.That(str, Is.Not.Empty); + Assert.That(str, Does.Not.Contain("{")); + Assert.That(str, Does.Not.Contain("}")); + } + static void testCommand(Command command) + { + testString(command.ToString()!); + PDL? pdl = null; + if (command.EnumValue is Command.ECommandDublicte _enum) + { + Assert.That(command.GetIsEmpty(), Is.False); + testString(_enum.ToString()!); + return; + } + + Assert.DoesNotThrow(() => { pdl = command.GetDataLength(); }); + Assert.That(pdl.HasValue, Is.True); + + if (command.SingleField is OneOfTypes singleField) + { + Assert.That(command.GetIsEmpty(), Is.False); + testString(singleField.ToString()!); + if (singleField.ObjectType is CommonPropertiesForNamed common) + testCommon(common); + else if (singleField.ReferenceType is ReferenceType reference) + testReference(reference); + return; + } + else if (command.ListOfFields is OneOfTypes[] listOfFields) + { + if (listOfFields.Length != 0) + { + Assert.That(command.GetIsEmpty(), Is.False); + testString(string.Join("; ", listOfFields.Select(r => r.ToString()))!); + foreach (var field in listOfFields) + { + if (field.ObjectType is CommonPropertiesForNamed common) + testCommon(common); + else if (field.ReferenceType is ReferenceType reference) + testReference(reference); + } + return; + } + } + Assert.That(command.GetIsEmpty(), Is.True); + } + static void testCommon(CommonPropertiesForNamed common) + { + testString(common.ToString()!); + if (common is IntegerType integerByte) + testIntegerType(integerByte); + else if (common is IntegerType integerSByte) + testIntegerType(integerSByte); + else if (common is IntegerType integerShort) + testIntegerType(integerShort); + else if (common is IntegerType integerUShort) + testIntegerType(integerUShort); + else if (common is IntegerType integerInt) + testIntegerType(integerInt); + else if (common is IntegerType integerUInt) + testIntegerType(integerUInt); + else if (common is IntegerType integerLong) + testIntegerType(integerLong); + else if (common is IntegerType integerULong) + testIntegerType(integerULong); +#if NET7_0_OR_GREATER + else if (common is IntegerType integerInt128) + testIntegerType(integerInt128); + else if (common is IntegerType integerUInt128) + testIntegerType(integerUInt128); +#endif + } + static void testReference(ReferenceType reference) + { + testString(reference.ToString()); + Assert.That(reference.Command, Is.EqualTo(Command.ECommandDublicte.GetRequest).Or.EqualTo(Command.ECommandDublicte.GetResponse).Or.EqualTo(Command.ECommandDublicte.SetRequest).Or.EqualTo(Command.ECommandDublicte.SetResponse)); + Assert.That(reference.Pointer, Is.AtLeast(0)); + } + static void testIntegerType(IntegerType integerType) + { + testString(integerType.ToString()!); + if (integerType.Ranges != null) + foreach (Range range in integerType.Ranges) + testString(range.ToString()!); + } + } + + private static string PrittyJSON(string jsonString) + { + var jsonObject = JsonSerializer.Deserialize(jsonString); + + var options = new JsonSerializerOptions + { + WriteIndented = false, + }; + + string formattedJson = JsonSerializer.Serialize(jsonObject, options); + return formattedJson; + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs b/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs new file mode 100644 index 0000000..f95bf1b --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestBitFieldType.cs @@ -0,0 +1,90 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestBitFieldType + { + [Test] + public void TestMany() + { + var bitTypes=new BitType[2]; + bitTypes[0] = new BitType("NAME11", "DISPLAY_NAME11", "NOTES11", null, null, 2, false, false); + bitTypes[1] = new BitType("NAME22", "DISPLAY_NAME22", "NOTES22", null, null, 4, false, false); + var bitFieldType = new BitFieldType("NAME", "DISPLAY_NAME", "NOTES", null, "bitField",16, false, bitTypes); + Assert.That(bitFieldType.Size, Is.EqualTo(16)); + Assert.That(bitFieldType.Bits, Has.Length.EqualTo(2)); + + Assert.DoesNotThrow(() => + { + PDL pdl = bitFieldType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(2)); + }); + + Assert.Throws(typeof(ArgumentException), () => bitFieldType = new BitFieldType("NAME", "DISPLAY_NAME", "NOTES", null, "botField", 16, false, bitTypes)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => bitFieldType = new BitFieldType("NAME", "DISPLAY_NAME", "NOTES", null, "bitField", 7, false, bitTypes)); + + + bitTypes = new BitType[3]; + bitTypes[0] = new BitType("NAME11", 2); + bitTypes[1] = new BitType("NAME22", 4); + bitTypes[2] = new BitType("NAME33", 15); + bitFieldType = new BitFieldType("NAME_BIT_FIELD", 16, bitTypes); + var dataTree= new DataTree(bitFieldType.Name,0,new DataTree[] { new DataTree(bitTypes[0].Name, 0, true), new DataTree(bitTypes[1].Name, 1, true), new DataTree(bitTypes[2].Name, 2, true), }); + + DoParseDataTest(bitFieldType, dataTree, new byte[] { 0b00010100, 0b10000000 }); + + bitFieldType = new BitFieldType("NAME_BIT_FIELD", 16, bitTypes, true); + dataTree = new DataTree(bitFieldType.Name, 0, new DataTree[] { new DataTree(bitTypes[0].Name, 0, false), new DataTree(bitTypes[1].Name, 1, false), new DataTree(bitTypes[2].Name, 2, false), }); + Assert.That(bitFieldType.ValueForUnspecified, Is.True); + DoParseDataTest(bitFieldType, dataTree, new byte[] { 0b11101011, 0b01111111 }); + } + private void DoParseDataTest(BitFieldType bitFieldType, DataTree dataTree, byte[] expectedData, string message = null) + { + Assert.Multiple(() => + { + Assert.That(dataTree.Value, Is.Null); + Assert.That(dataTree.Children, Is.Not.Null); + var data = new byte[0]; + Assert.DoesNotThrow(() => data = bitFieldType.ParsePayloadToData(dataTree), message); + Assert.That(data, Is.EqualTo(expectedData), message); + + byte[] clonaData = new byte[data.Length]; + Array.Copy(data, clonaData, clonaData.Length); + var parsedDataTree = bitFieldType.ParseDataToPayload(ref clonaData); + Assert.That(clonaData, Has.Length.EqualTo(0), message); + + Assert.That(parsedDataTree, Is.EqualTo(dataTree), message); + Assert.That(parsedDataTree.Value, Is.Null); + + //Test for short Data & PDL Issue + clonaData = new byte[data.Length - 1]; + Array.Copy(data, clonaData, clonaData.Length); + Assert.DoesNotThrow(() => parsedDataTree = bitFieldType.ParseDataToPayload(ref clonaData)); + Assert.That(parsedDataTree.Issues, Is.Not.Null); + Assert.That(parsedDataTree.Value, Is.Null); + Assert.That(parsedDataTree.Children, Is.Not.Null); + + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree("Different Name", dataTree.Index, children: dataTree.Children)), message); + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, children: dataTree.Children?.Take(2).ToArray())), message); + + var children = dataTree.Children!.ToArray(); + children[1] = new DataTree("Other Name", children[1].Index, children[1].Value); + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, children: children)), message); + + children = dataTree.Children!.ToArray(); + children[1] = new DataTree(children[1].Name, 3, children[1].Value); + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, children: children)), message); + + children = dataTree.Children!.ToArray(); + children[1] = new DataTree(children[1].Name, 0, children[1].Value); + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, children: children)), message); + + children = dataTree.Children!.ToArray(); + children[1] = new DataTree(children[1].Name, children[1].Index, 3); + Assert.Throws(typeof(ArithmeticException), () => data = bitFieldType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, children: children)), message); + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestBitType.cs b/RDMSharpTests/Metadata/JSON/TestBitType.cs new file mode 100644 index 0000000..e0d2bd8 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestBitType.cs @@ -0,0 +1,19 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestBitType + { + [Test] + public void TestMany() + { + var bitType = new BitType("NAME", "DISPLAY_NAME", "NOTES", null, "bit", 1, true, false); + Assert.That(bitType.Index, Is.EqualTo(1)); + Assert.Throws(typeof(NotSupportedException), () => bitType.GetDataLength()); + byte[] bytes = new byte[0]; + Assert.Throws(typeof(NotSupportedException), () => bitType.ParseDataToPayload(ref bytes)); + Assert.Throws(typeof(NotSupportedException), () => bitType.ParsePayloadToData(new DataTree())); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestBooleanType.cs b/RDMSharpTests/Metadata/JSON/TestBooleanType.cs new file mode 100644 index 0000000..79fa755 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestBooleanType.cs @@ -0,0 +1,73 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestBooleanType + { + [Test] + public void TestMany() + { + var labeledBooleanType = new LabeledBooleanType[2]; + labeledBooleanType[0] = new LabeledBooleanType("NAME11", null, "NOTES11", null, false); + labeledBooleanType[1] = new LabeledBooleanType("NAME22", "DISPLAY_NAME22", "NOTES22", null, true); + var booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "boolean", labeledBooleanType); + Assert.That(booleanType.Labels, Has.Length.EqualTo(2)); + + Assert.DoesNotThrow(() => + { + PDL pdl = booleanType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(1)); + }); + + DoParseDataTest(booleanType, false, new byte[] { 0x00 }); + DoParseDataTest(booleanType, true, new byte[] { 0x01 }); + + booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "boolean", null); + DoParseDataTest(booleanType, false, new byte[] { 0x00 }); + DoParseDataTest(booleanType, true, new byte[] { 0x01 }); + + Assert.Throws(typeof(ArgumentException), () => booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "bolean", labeledBooleanType)); + + labeledBooleanType = new LabeledBooleanType[1]; + labeledBooleanType[0] = new LabeledBooleanType("NAME11", "DISPLAY_NAME11", "NOTES11", null, false); + Assert.Throws(typeof(ArgumentException), () => booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "boolean", labeledBooleanType)); + + labeledBooleanType = new LabeledBooleanType[3]; + labeledBooleanType[0] = new LabeledBooleanType("NAME11", false); + labeledBooleanType[1] = new LabeledBooleanType("NAME22", "DISPLAY_NAME22", "NOTES22", null, true); + labeledBooleanType[2] = new LabeledBooleanType("NAME33", "DISPLAY_NAME33", "NOTES33", null, false); + Assert.Throws(typeof(ArgumentException), () => booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "boolean", labeledBooleanType)); + + labeledBooleanType = new LabeledBooleanType[2]; + labeledBooleanType[0] = new LabeledBooleanType("NAME11", "DISPLAY_NAME11", "NOTES11", null, false); + labeledBooleanType[1] = new LabeledBooleanType("NAME22", "DISPLAY_NAME22", "NOTES22", null, false); + Assert.Throws(typeof(ArgumentException), () => booleanType = new BooleanType("NAME", "DISPLAY_NAME", "NOTES", null, "boolean", labeledBooleanType)); + } + private void DoParseDataTest(BooleanType booleanType, bool value, byte[] expectedData, string message = null) + { + var dataTree = new DataTree(booleanType.Name, 0, value); + var data = new byte[0]; + Assert.DoesNotThrow(() => data = booleanType.ParsePayloadToData(dataTree), message); + Assert.That(data, Is.EqualTo(expectedData), message); + + byte[] clonaData = new byte[data.Length]; + Array.Copy(data, clonaData, clonaData.Length); + var parsedDataTree = booleanType.ParseDataToPayload(ref clonaData); + Assert.That(clonaData, Has.Length.EqualTo(0), message); + + Assert.That(parsedDataTree, Is.EqualTo(dataTree), message); + + //Test for short Data & PDL Issue + clonaData = new byte[data.Length - 1]; + Array.Copy(data, clonaData, clonaData.Length); + Assert.DoesNotThrow(() => parsedDataTree = booleanType.ParseDataToPayload(ref clonaData)); + Assert.That(parsedDataTree.Issues, Is.Not.Null); + Assert.That(parsedDataTree.Value, Is.Not.Null); + + Assert.Throws(typeof(ArithmeticException), () => data = booleanType.ParsePayloadToData(new DataTree("Different Name", dataTree.Index, dataTree.Value)), message); + Assert.Throws(typeof(ArithmeticException), () => data = booleanType.ParsePayloadToData(new DataTree(dataTree.Name, dataTree.Index, 234)), message); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestBytesType.cs b/RDMSharpTests/Metadata/JSON/TestBytesType.cs new file mode 100644 index 0000000..2aad6f7 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestBytesType.cs @@ -0,0 +1,339 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestBytesType + { + [Test] + public void TestMany() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, null, null); + Assert.That(bytesType.MinLength, Is.Null); + Assert.That(bytesType.MaxLength, Is.Null); + + bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, 1, null); + Assert.That(bytesType.MinLength, Is.EqualTo(1)); + Assert.That(bytesType.MaxLength, Is.Null); + + Assert.DoesNotThrow(() => + { + PDL pdl = bytesType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(1)); + Assert.That(pdl.MaxLength, Is.EqualTo(PDL.MAX_LENGTH)); + }); + + bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, 1, 3); + Assert.That(bytesType.MinLength, Is.EqualTo(1)); + Assert.That(bytesType.MaxLength, Is.EqualTo(3)); + + Assert.DoesNotThrow(() => + { + PDL pdl = bytesType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(1)); + Assert.That(pdl.MaxLength, Is.EqualTo(3)); + }); + + Assert.Throws(typeof(ArgumentException), () => bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bites", null, 1, 5)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, 6, 5)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, 4294567890, null)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, 2, 4294567890)); + } + [Test] + public void TestParseUID() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "uid", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(6)); + var uid = new UID(0x4646, 0x12345678); + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, uid)); + Assert.That(data, Is.EqualTo(new byte[] { 0x46, 0x46, 0x12, 0x34, 0x56, 0x78 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(uid)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "uid", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseUIDArrayEmpty() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "uid[]", null, null); + Assert.That(bytesType.GetDataLength().MinLength, Is.EqualTo(0)); + var uidArray = new UID[0]; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, uidArray)); + Assert.That(data, Is.EqualTo(new byte[0])); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Null); + } + [Test] + public void TestParseUIDArray() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "uid[]", null, null); + Assert.That(bytesType.GetDataLength().MinLength, Is.EqualTo(0)); + var uidArray = new UID[] { new UID(0x4646, 0x12345678) , new UID(0x4646, 0x12345678) }; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, uidArray)); + Assert.That(data, Is.EqualTo(new byte[] { 0x46, 0x46, 0x12, 0x34, 0x56, 0x78, 0x46, 0x46, 0x12, 0x34, 0x56, 0x78 })); + var corrupData = new List(); + corrupData.AddRange(data); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.EqualTo(uidArray)); + + corrupData.Add(1); + corrupData.Add(2); + data= corrupData.ToArray(); + dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(2)); + Assert.That(data, Is.EqualTo(new byte[] { 1, 2 })); + Assert.That(dataTree.Value, Is.EqualTo(uidArray)); + Assert.That(dataTree.Issues, Has.Length.EqualTo(2)); + } + + [Test] + public void TestParseIPv4() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "ipv4", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(4)); + var ipv4 = new IPv4Address(192,168,178,254); + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, ipv4)); + Assert.That(data, Is.EqualTo(new byte[] { 192, 168, 178, 254 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(ipv4)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "ipv4", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseIPv6() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "ipv6", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(16)); + var ipv6 = IPv6Address.LocalHost; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, ipv6)); + Assert.That(data, Is.EqualTo(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(ipv6)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "ipv6", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseMAC() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "mac-address", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(6)); + var mac = new MACAddress(new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }); + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, mac)); + Assert.That(data, Is.EqualTo(new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(mac)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "mac-address", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseGUID() + { + string[] formates = new string[] { "uuid", "guid" }; + foreach (var formate in formates) + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", formate, null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(16)); + var guid = new Guid(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }); + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, guid)); + Assert.That(data, Is.EqualTo(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(guid)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", formate, null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + } + [Test] + public void TestParseDouble() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "double", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(8)); + var _double = 0.252536d; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, _double)); + Assert.That(data, Is.EqualTo(new byte[] { 142, 2, 68, 193, 140, 41, 208, 63 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(_double)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "double", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseFloat() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "float", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(4)); + var _float = 0.252536f; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, _float)); + Assert.That(data, Is.EqualTo(new byte[] { 102, 76, 129, 62 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(_float)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "float", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParsePID() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "pid", null, null); + Assert.That(bytesType.GetDataLength().Value, Is.EqualTo(2)); + var pid = ERDM_Parameter.CURVE; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, pid)); + Assert.That(data, Is.EqualTo(new byte[] { 0x03, 0x043 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(pid)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "pid", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseASCII() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "ascii", null, null); + var ascii = "This is ASCII"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, ascii)); + Assert.That(data, Is.EqualTo(new byte[] { 84, 104, 105, 115, 32, 105, 115, 32, 65, 83, 67, 73, 73 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(ascii)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "ascii", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseUTF8() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "utf8", null, null); + var utf8 = "äöü߀!"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, utf8)); + Assert.That(data, Is.EqualTo(new byte[] { 195, 164, 195, 182, 195, 188, 195, 159, 226, 130, 172, 33 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(utf8)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "utf8", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseUTF32() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "utf32", null, null); + var utf32 = "😊🚀🌍💡📚✈️"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, utf32)); + Assert.That(data, Is.EqualTo(new byte[] { 10, 246, 1, 0, 128, 246, 1, 0, 13, 243, 1, 0, 161, 244, 1, 0, 218, 244, 1, 0, 8, 39, 0, 0, 15, 254, 0, 0 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(utf32)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "utf32", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseUnicode() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "unicode", null, null); + var unicode = "ÄÖÜß😊"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, unicode)); + Assert.That(data, Is.EqualTo(new byte[] { 196, 0, 214, 0, 220, 0, 223, 0, 61, 216, 10, 222 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(unicode)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "unicode", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseBigEndianUnicode() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "big_edian_unicode", null, null); + var big_edian_unicode = "ÄÖÜß😊"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, big_edian_unicode)); + Assert.That(data, Is.EqualTo(new byte[] { 0, 196, 0, 214, 0, 220, 0, 223, 216, 61, 222, 10 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(big_edian_unicode)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "big_edian_unicode", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseLatin1() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "latin1", null, null); + var latin1 = "Café"; ; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, latin1)); + Assert.That(data, Is.EqualTo(new byte[] { 67, 97, 102, 233 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(latin1)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "latin1", null, null).ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseFallbackString() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, null, null); + var utf8 = "äöü߀!"; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, utf8)); + Assert.That(data, Is.EqualTo(new byte[] { 195, 164, 195, 182, 195, 188, 195, 159, 226, 130, 172, 33 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + } + [Test] + public void TestParseFallbackUTF8Array() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "utf8[]", null, null); + var utf8 = "äöü߀!"; + var array = new string[] { utf8, utf8 }; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, array)); + Assert.That(data, Is.EqualTo(new byte[] { 195, 164, 195, 182, 195, 188, 195, 159, 226, 130, 172, 33, 0, 195, 164, 195, 182, 195, 188, 195, 159, 226, 130, 172, 33, 0 })); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + } + [Test] + public void TestParseFallbackByteArray() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", null, null, null); + var bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; + var data = bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, bytes)); + Assert.That(data, Is.EqualTo(bytes)); + var dataTree = bytesType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(bytes)); + } + [Test] + public void TestParseFallbackUnknownType() + { + var bytesType = new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "UNKNOWN", null, null); + Assert.Throws(typeof(ArithmeticException), () => bytesType.ParsePayloadToData(new DataTree(bytesType.Name, 0, DateTime.Now))); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestCommand.cs b/RDMSharpTests/Metadata/JSON/TestCommand.cs new file mode 100644 index 0000000..09bfda6 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestCommand.cs @@ -0,0 +1,15 @@ +using RDMSharp.Metadata.JSON; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestCommand + { + [Test] + public void TestMany() + { + var command = new Command( Command.ECommandDublicte.GetResponse); + Assert.That(command.GetIsEmpty(), Is.False); + Assert.Throws(typeof(NotSupportedException), () => command.GetDataLength()); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestCompoundType.cs b/RDMSharpTests/Metadata/JSON/TestCompoundType.cs new file mode 100644 index 0000000..4b869d0 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestCompoundType.cs @@ -0,0 +1,100 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestCompoundType + { + [Test] + public void TestMany() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + Assert.That(compoundType.Subtypes, Has.Length.EqualTo(2)); + + Assert.DoesNotThrow(() => + { + PDL pdl = compoundType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(2)); + }); + + Assert.Throws(typeof(ArgumentException), () => compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "kompound", oneOf)); + Assert.Throws(typeof(ArgumentException), () => compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", null)); + Assert.Throws(typeof(ArgumentException), () => compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", new OneOfTypes[0])); + + Assert.Throws(typeof(ArithmeticException), () => compoundType.validateDataLength(1)); + Assert.Throws(typeof(ArithmeticException), () => compoundType.validateDataLength(3)); + Assert.DoesNotThrow(() => compoundType.validateDataLength(2)); + } + + [Test] + public void TestParseData1() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME1", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(new IntegerType("NAME2", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + + DataTree dataTree = new DataTree(compoundType.Name, 0, new DataTree[] { new DataTree(oneOf[0].ObjectType.Name, 0, (byte)33), new DataTree(oneOf[1].ObjectType.Name, 1, (sbyte)-22) }); + byte[] data = compoundType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 33, 234 })); + + DataTree dataTreeResult = compoundType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult, Is.EqualTo(dataTree)); + } + + [Test] + public void TestParseDataInvalidName() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME1", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(new IntegerType("NAME2", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + + DataTree dataTree = new DataTree(compoundType.Name+"INVALID", 0, new DataTree[] { new DataTree(oneOf[0].ObjectType.Name, 0, (byte)33), new DataTree(oneOf[1].ObjectType.Name, 1, (sbyte)-22) }); + Assert.Throws(typeof(ArithmeticException), () => compoundType.ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseDataInvalidNameOnChildren() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME1", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(new IntegerType("NAME2", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + + DataTree dataTree = new DataTree(compoundType.Name, 0, new DataTree[] { new DataTree(oneOf[0].ObjectType.Name+ "INVALID", 0, (byte)33), new DataTree(oneOf[1].ObjectType.Name, 1, (sbyte)-22) }); + Assert.Throws(typeof(ArithmeticException), () => compoundType.ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseDataMissingChildrenDataTree() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME1", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(new IntegerType("NAME2", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + + DataTree dataTree = new DataTree(compoundType.Name, 0, new DataTree[] { new DataTree(oneOf[0].ObjectType.Name, 0, (byte)33) }); + Assert.Throws(typeof(ArithmeticException), () => compoundType.ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseSubItemIsEmpty() + { + OneOfTypes[] oneOf = new OneOfTypes[2]; + oneOf[0] = new OneOfTypes(new IntegerType("NAME1", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + oneOf[1] = new OneOfTypes(); + + var compoundType = new CompoundType("NAME", "DISPLAY_NAME", "NOTES", null, "compound", oneOf); + + DataTree dataTree = new DataTree(compoundType.Name, 0, new DataTree[] { new DataTree(oneOf[0].ObjectType.Name, 0, (byte)33), new DataTree(null, 1, (sbyte)-22) }); + Assert.Throws(typeof(ArithmeticException), () => compoundType.ParsePayloadToData(dataTree)); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestDataTree.cs b/RDMSharpTests/Metadata/JSON/TestDataTree.cs new file mode 100644 index 0000000..66e7d4b --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestDataTree.cs @@ -0,0 +1,85 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestDataTree + { + [Test] + public void TestMany() + { + Assert.Multiple(() => + { + var dataTree = new DataTree(); + Assert.That(dataTree.ToString(), Is.Not.Null); + Assert.Throws(typeof(ArgumentException), () => new DataTree("name", 1, value: new DataTree[0].ToList())); + + Assert.That(new DataTree() == new DataTree(), Is.True); + Assert.That(new DataTree() != new DataTree(), Is.False); + Assert.That(new DataTree().Equals(new DataTree()), Is.True); + Assert.That(((object)new DataTree()).Equals(new DataTree()), Is.True); + Assert.That(((object)new DataTree()).Equals((object)new DataTree()), Is.True); + Assert.That(((object)new DataTree()).Equals(1), Is.False); + + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test", 3, true), Is.True); + Assert.That(new DataTree("Test", 3, true) != new DataTree("Test", 3, true), Is.False); + Assert.That(new DataTree("Test", 3, true).Equals(new DataTree("Test", 3, true)), Is.True); + + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test", 31, true), Is.False); + Assert.That(new DataTree("Test", 3, true) != new DataTree("Test", 31, true), Is.True); + Assert.That(new DataTree("Test", 3, true).Equals(new DataTree("Test", 31, true)), Is.False); + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test", 3, false), Is.False); + Assert.That(new DataTree("Test", 3, true) != new DataTree("Test", 3, false), Is.True); + Assert.That(new DataTree("Test", 3, true).Equals(new DataTree("Test", 3, false)), Is.False); + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test2", 3, true), Is.False); + Assert.That(new DataTree("Test", 3, true) != new DataTree("Test3", 3, true), Is.True); + Assert.That(new DataTree("Test", 3, true).Equals(new DataTree("Test4", 3, true)), Is.False); + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test", 3, null), Is.False); + Assert.That(new DataTree("Test", 3, true) != new DataTree("Test", 3, null), Is.True); + Assert.That(new DataTree("Test", 3, true).Equals(new DataTree("Test", 3, null)), Is.False); + }); + + HashSet dict1 = new HashSet(); + HashSet dict2 = new HashSet(); + HashSet dict3 = new HashSet(); + + dict1.Add(new DataTree()); + dict2.Add(new DataTree()); + dict3.Add(new DataTree()); + + dict1.Add(new DataTree("Test", 1, false)); + dict2.Add(new DataTree("Test", 1, false)); + dict3.Add(new DataTree("Test", 1, true)); + + dict1.Add(new DataTree("Test2", 2, 33)); + dict2.Add(new DataTree("Test2", 2, 33)); + dict3.Add(new DataTree("Test2", 2, 33)); + + Assert.Multiple(() => + { + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()) == new DataTree("Test", 3, children: dict2.ToArray()), Is.True); + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()) != new DataTree("Test", 3, children: dict2.ToArray()), Is.False); + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()).Equals(new DataTree("Test", 3, children: dict2.ToArray())), Is.True); + + Assert.That(new DataTree("Test", 3, children: null) == new DataTree("Test", 3, children: dict3.ToArray()), Is.False); + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()) == new DataTree("Test", 3, children: dict3.ToArray()), Is.False); + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()) != new DataTree("Test", 3, children: dict3.ToArray()), Is.True); + Assert.That(new DataTree("Test", 3, children: dict1.ToArray()).Equals(new DataTree("Test", 3, children: dict3.ToArray())), Is.False); + }); + + DataTreeIssue[] issues1 = new DataTreeIssue[] { new DataTreeIssue("Test Issue") }; + DataTreeIssue[] issues2 = new DataTreeIssue[] { new DataTreeIssue("Test Issue"), new DataTreeIssue("Test Issue2") }; + + Assert.Multiple(() => + { + Assert.That(new DataTree("Test", 3, true, issues1) == new DataTree("Test", 3, true, issues1.ToList().ToArray()), Is.True); + Assert.That(new DataTree("Test", 3, true, issues1) != new DataTree("Test", 3, true, issues1.ToList().ToArray()), Is.False); + Assert.That(new DataTree("Test", 3, true, issues1).Equals(new DataTree("Test", 3, true, issues1.ToList().ToArray())), Is.True); + + Assert.That(new DataTree("Test", 3, true) == new DataTree("Test", 3, true, issues2), Is.False); + Assert.That(new DataTree("Test", 3, true, issues1) == new DataTree("Test", 3, true, issues2), Is.False); + Assert.That(new DataTree("Test", 3, true, issues1) != new DataTree("Test", 3, true, issues2), Is.True); + Assert.That(new DataTree("Test", 3, true, issues1).Equals(new DataTree("Test", 3, true, issues2)), Is.False); + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestDataTreeIssue.cs b/RDMSharpTests/Metadata/JSON/TestDataTreeIssue.cs new file mode 100644 index 0000000..e536fdc --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestDataTreeIssue.cs @@ -0,0 +1,21 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestDataTreeIssue + { + [Test] + public void TestMany() + { + Assert.Multiple(() => + { + var issue = new DataTreeIssue(); + Assert.That(issue.ToString(), Is.Null); + issue = new DataTreeIssue("Test"); + Assert.That(issue.ToString(), Is.EqualTo("Test")); + Assert.Throws(typeof(ArgumentNullException), () => new DataTreeIssue("")); + Assert.Throws(typeof(ArgumentNullException), () => new DataTreeIssue(null)); + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestDefineNotFoundException.cs b/RDMSharpTests/Metadata/JSON/TestDefineNotFoundException.cs new file mode 100644 index 0000000..d2cf3a7 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestDefineNotFoundException.cs @@ -0,0 +1,19 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestDefineNotFoundException + { + [Test] + public void TestMany() + { + Assert.Multiple(() => + { + var exception = new DefineNotFoundException(); + Assert.That(exception.Message, Is.Not.Null); + exception = new DefineNotFoundException("Test"); + Assert.That(exception.Message, Is.EqualTo("Test")); + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestIntegerType.cs b/RDMSharpTests/Metadata/JSON/TestIntegerType.cs new file mode 100644 index 0000000..6b2751c --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestIntegerType.cs @@ -0,0 +1,420 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestIntegerType + { + [Test] + public void TestManyInt8() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.Int8)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(1)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, -71, new byte[] { 185 }); + DoParseDataTest(integerType, sbyte.MinValue, new byte[] { 128 }, nameof(sbyte.MinValue)); + DoParseDataTest(integerType, sbyte.MaxValue, new byte[] { 127 }, nameof(sbyte.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 1 }, "One"); + }); + } + [Test] + public void TestManyUInt8() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.UInt8)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(1)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, 71, new byte[] { 71 }); + DoParseDataTest(integerType, byte.MinValue, new byte[] { 0 }, nameof(byte.MinValue)); + DoParseDataTest(integerType, byte.MaxValue, new byte[] { 255 }, nameof(byte.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 1 }, "One"); + }); + } + [Test] + public void TestManyInt16() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int16, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.Int16)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(2)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt16, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, -13245, new byte[] { 204, 67 }); + DoParseDataTest(integerType, short.MinValue, new byte[] { 128, 0 }, nameof(short.MinValue)); + DoParseDataTest(integerType, short.MaxValue, new byte[] { 127,255 }, nameof(short.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 1 }, "One"); + }); + } + [Test] + public void TestManyUInt16() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt16, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.UInt16)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(2)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int16, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, 65432, new byte[] { 255, 152 }); + DoParseDataTest(integerType, ushort.MinValue, new byte[] { 0, 0 }, nameof(ushort.MinValue)); + DoParseDataTest(integerType, ushort.MaxValue, new byte[] { 255, 255 }, nameof(ushort.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 1 }, "One"); + }); + } + [Test] + public void TestManyInt32() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int32, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.Int32)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(4)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt32, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, -13243567, new byte[] { 255, 53, 235, 81 }); + DoParseDataTest(integerType, int.MinValue, new byte[] { 128, 0, 0, 0 }, nameof(int.MinValue)); + DoParseDataTest(integerType, int.MaxValue, new byte[] { 127, 255, 255, 255 }, nameof(int.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0, 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 0, 0, 1 }, "One"); + }); + } + [Test] + public void TestManyUInt32() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt32, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.UInt32)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(4)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int32, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, 75643244, new byte[] { 4, 130, 57, 108 }); + DoParseDataTest(integerType, uint.MinValue, new byte[] { 0, 0, 0, 0 }, nameof(uint.MinValue)); + DoParseDataTest(integerType, uint.MaxValue, new byte[] { 255, 255, 255, 255 }, nameof(uint.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0, 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 0, 0, 1 }, "One"); + }); + } + [Test] + public void TestManyInt64() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int64, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.Int64)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(8)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt64, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, -2136456776545, new byte[] { 255, 255, 254, 14, 145, 64, 180, 159 }); + DoParseDataTest(integerType, long.MinValue, new byte[] { 128, 0, 0, 0, 0, 0, 0, 0 }, nameof(long.MinValue)); + DoParseDataTest(integerType, long.MaxValue, new byte[] { 127, 255, 255, 255, 255, 255, 255, 255 }, nameof(long.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, "One"); + }); + } + [Test] + public void TestManyUInt64() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt64, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.UInt64)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(8)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int64, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, 345676543456543, new byte[] { 0, 1, 58, 100, 23, 148, 117, 31 }); + DoParseDataTest(integerType, ulong.MinValue, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, nameof(ulong.MinValue)); + DoParseDataTest(integerType, ulong.MaxValue, new byte[] { 255, 255, 255, 255, 255, 255, 255, 255 }, nameof(ulong.MaxValue)); + DoParseDataTest(integerType, 0, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, "Zero"); + DoParseDataTest(integerType, 1, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 }, "One"); + }); + } +#if NET7_0_OR_GREATER + [Test] + public void TestManyInt128() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int128, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.Int128)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(16)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt128, null, null, null, null, null, null)); + Assert.Multiple(() => + { + DoParseDataTest(integerType, new Int128(2725151552362626646, 5278987657876567), new byte[] { 37, 209, 174, 229, 253, 173, 190, 86, 0, 18, 193, 54, 24, 31, 20, 87 }); + DoParseDataTest(integerType, Int128.MinValue, new byte[] { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, nameof(Int128.MinValue)); + DoParseDataTest(integerType, Int128.MaxValue, new byte[] { 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, nameof(Int128.MaxValue)); + DoParseDataTest(integerType, Int128.Zero, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, nameof(Int128.Zero)); + DoParseDataTest(integerType, Int128.One, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, nameof(Int128.One)); + }); + } + [Test] + public void TestManyUInt128() + { + var integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt128, null, null, null, null, null, null); + Assert.That(integerType.Type, Is.EqualTo(EIntegerType.UInt128)); + + Assert.DoesNotThrow(() => + { + PDL pdl = integerType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(16)); + }); + + Assert.Throws(typeof(ArgumentException), () => integerType = new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int128, null, null, null, null, null, null)); + + Assert.Multiple(() => + { + DoParseDataTest(integerType, new UInt128(2725751552362626686, 5278987657876567), new byte[] { 37, 211, 208, 152, 96, 139, 62, 126, 0, 18, 193, 54, 24, 31, 20, 87 }); + DoParseDataTest(integerType, UInt128.MinValue, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, nameof(UInt128.MinValue)); + DoParseDataTest(integerType, UInt128.MaxValue, new byte[] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, nameof(UInt128.MaxValue)); + DoParseDataTest(integerType, UInt128.Zero, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, nameof(UInt128.Zero)); + DoParseDataTest(integerType, UInt128.One, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, nameof(UInt128.One)); + }); + } +#endif + + [Test] + public void TestPrefix1024() + { + LabeledIntegerType[] labeledIntegerType = new LabeledIntegerType[] { new LabeledIntegerType("Test 0", 0), new LabeledIntegerType("Test 1", 1), new LabeledIntegerType("Test 100", 100), }; + Range[] ranges = new Range[] { new Range(0, 100) }; + CommonPropertiesForNamed[] types = new CommonPropertiesForNamed[] + { + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int16, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt16, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int32, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt32, null, null, null, null, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int64, labeledIntegerType, null, ranges, ERDM_SensorUnit.BYTE, 10, 2), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt64, null, null, null, null, 10, 2), + }; + foreach (CommonPropertiesForNamed integerType in types) + { + Assert.That(((IIntegerType)integerType).PrefixBase, Is.EqualTo(2)); + Assert.That(((IIntegerType)integerType).PrefixPower, Is.EqualTo(10)); + Assert.That(((IIntegerType)integerType).PrefixMultiplyer, Is.EqualTo(1024)); + + uint pdl = integerType.GetDataLength().Value.Value; + Assert.Multiple(() => + { + var data = new byte[pdl]; + var dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(0)); + var parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + Assert.That(parsedData, Is.EqualTo(data)); + + data = new byte[pdl]; + data[data.Length - 1] = 1; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(1024)); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 1; + Assert.That(parsedData, Is.EqualTo(data)); + + data = new byte[pdl]; + data[data.Length - 1] = 100; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(102400)); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 100; + Assert.That(parsedData, Is.EqualTo(data)); + }); + } + } + [Test] + public void TestPrefix1024Negativ() + { + CommonPropertiesForNamed[] types = new CommonPropertiesForNamed[] + { + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int16, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt16, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int32, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt32, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int64, null, null, null, null, 1, -1024), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt64, null, null, null, null, 1, -1024), + }; + foreach (CommonPropertiesForNamed integerType in types) + { + Assert.That(((IIntegerType)integerType).PrefixBase, Is.EqualTo(-1024)); + Assert.That(((IIntegerType)integerType).PrefixPower, Is.EqualTo(1)); + Assert.That(((IIntegerType)integerType).PrefixMultiplyer, Is.EqualTo(-1024)); + + uint pdl = integerType.GetDataLength().Value.Value; + Assert.Multiple(() => + { + string message= ((IIntegerType)integerType).Type.ToString(); + var data = new byte[pdl]; + var dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(0), message); + var parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + Assert.That(parsedData, Is.EqualTo(data), message); + + data = new byte[pdl]; + data[data.Length - 1] = 1; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(-1024), message); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 1; + Assert.That(parsedData, Is.EqualTo(data), message); + + data = new byte[pdl]; + data[data.Length - 1] = 100; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(-102400), message); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 100; + Assert.That(parsedData, Is.EqualTo(data), message); + }); + } + } + [Test] + public void TestPrefix4Decimals() + { + CommonPropertiesForNamed[] types = new CommonPropertiesForNamed[] + { + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int8, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int16, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt16, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int32, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt32, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.Int64, null, null, null, null, -4, 10), + new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt64, null, null, null, null, -4, 10), + }; + foreach (CommonPropertiesForNamed integerType in types) + { + Assert.That(((IIntegerType)integerType).PrefixBase, Is.EqualTo(10)); + Assert.That(((IIntegerType)integerType).PrefixPower, Is.EqualTo(-4)); + Assert.That(((IIntegerType)integerType).PrefixMultiplyer, Is.EqualTo(0.0001)); + + uint pdl = integerType.GetDataLength().Value.Value; + Assert.Multiple(() => + { + var data = new byte[pdl]; + var dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(0)); + var parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + Assert.That(parsedData, Is.EqualTo(data)); + + data = new byte[pdl]; + data[data.Length - 1] = 1; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(0.0001)); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 1; + Assert.That(parsedData, Is.EqualTo(data)); + + data = new byte[pdl]; + data[data.Length - 1] = 100; + dataTree = integerType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(0.01)); + parsedData = integerType.ParsePayloadToData(dataTree); + data = new byte[pdl]; + data[data.Length - 1] = 100; + Assert.That(parsedData, Is.EqualTo(data)); + }); + } + } + + private void DoParseDataTest(IntegerType integerType, T value, byte[] expectedData, string message = null) + { + var dataTree = new DataTree(integerType.Name, 0, value); + var data = new byte[0]; + Assert.DoesNotThrow(() => data = integerType.ParsePayloadToData(dataTree), message); + Assert.That(data, Is.EqualTo(expectedData), message); + + byte[] clonaData = new byte[data.Length]; + Array.Copy(data, clonaData, clonaData.Length); + var parsedDataTree = integerType.ParseDataToPayload(ref clonaData); + Assert.That(clonaData, Has.Length.EqualTo(0), message); + + Assert.That(parsedDataTree, Is.EqualTo(dataTree), message); + + //Test for short Data & PDL Issue + clonaData = new byte[data.Length - 1]; + Array.Copy(data, clonaData, clonaData.Length); + Assert.DoesNotThrow(() => parsedDataTree = integerType.ParseDataToPayload(ref clonaData)); + Assert.That(parsedDataTree.Issues, Is.Not.Null); + Assert.That(parsedDataTree.Value, Is.Not.Null); + + Assert.Throws(typeof(ArithmeticException), () => data = integerType.ParsePayloadToData(new DataTree("Different Name", dataTree.Index, dataTree.Value)), message); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestLabeledBooleanType.cs b/RDMSharpTests/Metadata/JSON/TestLabeledBooleanType.cs new file mode 100644 index 0000000..f509997 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestLabeledBooleanType.cs @@ -0,0 +1,19 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestLabeledBooleanType + { + [Test] + public void TestMany() + { + var labeledBooleanType = new LabeledBooleanType("NAME", "DISPLAY_NAME", "NOTES", null, true); + Assert.That(labeledBooleanType.Value, Is.True); + Assert.Throws(typeof(NotSupportedException), () => labeledBooleanType.GetDataLength()); + byte[] bytes = new byte[0]; + Assert.Throws(typeof(NotSupportedException), () => labeledBooleanType.ParseDataToPayload(ref bytes)); + Assert.Throws(typeof(NotSupportedException), () => labeledBooleanType.ParsePayloadToData(new DataTree())); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestLabeledIntegerType.cs b/RDMSharpTests/Metadata/JSON/TestLabeledIntegerType.cs new file mode 100644 index 0000000..6545873 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestLabeledIntegerType.cs @@ -0,0 +1,19 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestLabeledIntegerType + { + [Test] + public void TestMany() + { + var labeledIntegerType = new LabeledIntegerType("NAME", "DISPLAY_NAME", "NOTES", null, 3); + Assert.That(labeledIntegerType.Value, Is.EqualTo(3)); + Assert.Throws(typeof(NotSupportedException), () => labeledIntegerType.GetDataLength()); + byte[] bytes = new byte[0]; + Assert.Throws(typeof(NotSupportedException), () => labeledIntegerType.ParseDataToPayload(ref bytes)); + Assert.Throws(typeof(NotSupportedException), () => labeledIntegerType.ParsePayloadToData(new DataTree())); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestListType.cs b/RDMSharpTests/Metadata/JSON/TestListType.cs new file mode 100644 index 0000000..1d5295d --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestListType.cs @@ -0,0 +1,126 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestListType + { + [Test] + public void TestMany() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), null, null); + Assert.That(listType.MinItems, Is.Null); + Assert.That(listType.MaxItems, Is.Null); + + Assert.DoesNotThrow(() => + { + PDL pdl = listType.GetDataLength(); + Assert.That(pdl.MaxLength, Is.EqualTo(PDL.MAX_LENGTH)); + }); + + Assert.Throws(typeof(ArgumentException), () => listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "lost", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), null, null)); + Assert.Throws(typeof(ArgumentException), () => listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(), null, null)); + + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, 3, 10, null); + listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(stringType), 1, 3); + Assert.DoesNotThrow(() => + { + PDL pdl = listType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(3)); + Assert.That(pdl.MaxLength, Is.EqualTo(30)); + }); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null,32, 32, null); + listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(stringType), 1, 3); + Assert.DoesNotThrow(() => + { + PDL pdl = listType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(32)); + Assert.That(pdl.MaxLength, Is.EqualTo(96)); + }); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, 32, 32, null); + listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(stringType), null, 3); + Assert.DoesNotThrow(() => + { + PDL pdl = listType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(0)); + Assert.That(pdl.MaxLength, Is.EqualTo(96)); + }); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, 32, 32, null); + listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(stringType), 1, null); + Assert.DoesNotThrow(() => + { + PDL pdl = listType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(32)); + Assert.That(pdl.MaxLength, Is.EqualTo(PDL.MAX_LENGTH)); + }); + + Assert.Throws(typeof(ArithmeticException), () => listType.validateDataLength(0)); + Assert.Throws(typeof(ArithmeticException), () => listType.validateDataLength(3)); + Assert.DoesNotThrow(() => listType.validateDataLength(32)); + Assert.DoesNotThrow(() => listType.validateDataLength(58905)); + } + + [Test] + public void TestParseData1() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 1, 5); + var dataTree = new DataTree(listType.Name, 0, children: new DataTree[] { new DataTree("NAME", 0, (byte)11), new DataTree("NAME", 1, (byte)22), new DataTree("NAME", 2, (byte)33) }); + var data = listType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 11, 22, 33 })); + + var dataTreeResult = listType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult, Is.EqualTo(dataTree)); + + listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 3, 3); + data = listType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 11, 22, 33 })); + + dataTreeResult = listType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult, Is.EqualTo(dataTree)); + } + [Test] + public void TestParseDataShortMin() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 4, 5); + var dataTree = new DataTree(listType.Name, 0, children: new DataTree[] { new DataTree("NAME", 0, (byte)11), new DataTree("NAME", 1, (byte)22), new DataTree("NAME", 2, (byte)33) }); + + var data = new byte[] { 11, 22, 33 }; + var dataTreeResult = listType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult.Issues, Has.Length.EqualTo(2)); + } + [Test] + public void TestParseDataExceedMax() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 1, 2); + var dataTree = new DataTree(listType.Name, 0, children: new DataTree[] { new DataTree("NAME", 0, (byte)11), new DataTree("NAME", 1, (byte)22), new DataTree("NAME", 2, (byte)33) }); + + var data = new byte[] { 11, 22, 33 }; + var dataTreeResult = listType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult.Issues, Has.Length.EqualTo(2)); + } + [Test] + public void TestParseDataNameInvalid() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 1, 2); + var dataTree = new DataTree(listType.Name+"INVALID", 0, children: new DataTree[] { new DataTree("NAME", 0, (byte)11), new DataTree("NAME", 1, (byte)22), new DataTree("NAME", 2, (byte)33) }); + + Assert.Throws(typeof(ArithmeticException), () => listType.ParsePayloadToData(dataTree)); + } + [Test] + public void TestParseDataChildNameInvalid() + { + var listType = new ListType("NAME", "DISPLAY_NAME", "NOTES", null, "list", new OneOfTypes(new IntegerType("NAME", "DISPLAY_NAME", "NOTES", null, EIntegerType.UInt8, null, null, null, null, null, null)), 1, 2); + var dataTree = new DataTree(listType.Name, 0, children: new DataTree[] { new DataTree("NAME" + "INVALID", 0, (byte)11), new DataTree("NAME", 1, (byte)22), new DataTree("NAME", 2, (byte)33) }); + + Assert.Throws(typeof(ArithmeticException), () => listType.ParsePayloadToData(dataTree)); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestOneOfTypes.cs b/RDMSharpTests/Metadata/JSON/TestOneOfTypes.cs new file mode 100644 index 0000000..119e648 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestOneOfTypes.cs @@ -0,0 +1,19 @@ +using RDMSharp.Metadata.JSON.OneOfTypes; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestOneOfTypes + { + [Test] + public void TestMany() + { + var oneOfTypes = new OneOfTypes(); + Assert.That(oneOfTypes.IsEmpty, Is.True); + Assert.That(oneOfTypes.ToString(), Is.Null); + Assert.DoesNotThrow(() => + { + Assert.That(oneOfTypes.GetDataLength().Value, Is.EqualTo(0)); + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestPD_EnvelopeType.cs b/RDMSharpTests/Metadata/JSON/TestPD_EnvelopeType.cs new file mode 100644 index 0000000..374cf87 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestPD_EnvelopeType.cs @@ -0,0 +1,37 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestPD_EnvelopeType + { + [Test] + public void TestMany() + { + var pdEnvelopeType = new PD_EnvelopeType("NAME", "DISPLAY_NAME", "NOTES", null, "pdEnvelope", 2); + Assert.That(pdEnvelopeType.Length, Is.EqualTo(2)); + + Assert.DoesNotThrow(() => + { + PDL pdl = pdEnvelopeType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(2)); + }); + + Assert.Throws(typeof(ArgumentException), () => pdEnvelopeType = new PD_EnvelopeType("NAME", "DISPLAY_NAME", "NOTES", null, "pdEnvelop", 2)); + + } + + [Test] + public void TestParseData1() + { + var pdEnvelopeType = new PD_EnvelopeType("NAME", "DISPLAY_NAME", "NOTES", null, "pdEnvelope", 2); + var dataTree = new DataTree(pdEnvelopeType.Name, 0, null); + var data = pdEnvelopeType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { })); + + var dataTreeResult = pdEnvelopeType.ParseDataToPayload(ref data); + Assert.That(dataTreeResult, Is.EqualTo(dataTree)); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestRange.cs b/RDMSharpTests/Metadata/JSON/TestRange.cs new file mode 100644 index 0000000..d9af436 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestRange.cs @@ -0,0 +1,100 @@ +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestRange + { + [Test] + public void TestByte() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 01 - 07")); + } + [Test] + public void TestSByte() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(-3), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 01 - 07")); + } + [Test] + public void TestShort() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 0001 - 0007")); + } + [Test] + public void TestUShort() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 0001 - 0007")); + } + [Test] + public void TestInt() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 00000001 - 00000007")); + } + [Test] + public void TestUInt() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 00000001 - 00000007")); + } + [Test] + public void TestLong() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 0000000000000001 - 0000000000000007")); + } + [Test] + public void TestULong() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 0000000000000001 - 0000000000000007")); + } +#if NET7_0_OR_GREATER + [Test] + public void TestInt128() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 00000000000000000000000000000001 - 00000000000000000000000000000007")); + } + [Test] + public void TestUInt128() + { + Range range = new Range(1, 7); + Assert.That(range.IsInRange(2), Is.True); + Assert.That(range.IsInRange(0), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 00000000000000000000000000000001 - 00000000000000000000000000000007")); + } +#endif + + [Test] + public void TestStringInvalid() + { + Range range = new Range("1", "7"); + Assert.That(range.IsInRange("2"), Is.False); + Assert.That(range.IsInRange("0"), Is.False); + Assert.That(range.ToString(), Is.EqualTo("Range: 1 - 7")); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestReferenceType.cs b/RDMSharpTests/Metadata/JSON/TestReferenceType.cs new file mode 100644 index 0000000..1fe16b6 --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestReferenceType.cs @@ -0,0 +1,44 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestReferenceType + { + [Test] + public void TestMany() + { + var referenceType = new ReferenceType("#/get_request/0"); + Assert.That(referenceType.Command, Is.EqualTo(Command.ECommandDublicte.GetRequest)); + Assert.That(referenceType.Pointer, Is.EqualTo(0)); + + Assert.DoesNotThrow(() => + { + PDL pdl = referenceType.GetDataLength(); + Assert.That(pdl.Value, Is.EqualTo(0)); + Assert.That(pdl.MinLength, Is.Null); + Assert.That(pdl.MaxLength, Is.Null); + }); + + Assert.Throws(typeof(ArgumentException), () => referenceType = new ReferenceType("%/get_request/0")); + } + [Test] + public void TestParse() + { + var referenceType = new ReferenceType("#/get_request/0", new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "uid", null, null)); + Assert.That(referenceType.GetDataLength().Value, Is.EqualTo(6)); + var uid = new UID(0x4646, 0x12345678); + var data = referenceType.ParsePayloadToData(new DataTree(referenceType.ReferencedObject.Name, 0, uid)); + Assert.That(data, Is.EqualTo(new byte[] { 0x46, 0x46, 0x12, 0x34, 0x56, 0x78 })); + var dataTree = referenceType.ParseDataToPayload(ref data); + Assert.That(data, Has.Length.EqualTo(0)); + Assert.That(dataTree.Value, Is.Not.Null); + Assert.That(dataTree.Value, Is.EqualTo(uid)); + + Assert.Throws(typeof(ArithmeticException), () => new BytesType("Other Name", "DISPLAY_NAME", "NOTES", null, "bytes", "uid", null, null).ParsePayloadToData(dataTree)); + Assert.Throws(typeof(ArithmeticException), () => new BytesType("NAME", "DISPLAY_NAME", "NOTES", null, "bytes", "xyz", null, null).ParsePayloadToData(dataTree)); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/JSON/TestStringType.cs b/RDMSharpTests/Metadata/JSON/TestStringType.cs new file mode 100644 index 0000000..bc4aa2b --- /dev/null +++ b/RDMSharpTests/Metadata/JSON/TestStringType.cs @@ -0,0 +1,216 @@ +using RDMSharp.Metadata; +using RDMSharp.Metadata.JSON.OneOfTypes; +using RDMSharp.RDM; +using System.Text; + +namespace RDMSharpTests.Metadata.JSON +{ + public class TestStringType + { + [TearDown] + public void Teardown() + { + Console.OutputEncoding = Encoding.Default; + } + [Test] + public void TestUTF8_Works() + { + Console.OutputEncoding = Encoding.UTF8; + string originalString = "Ä"; + byte[] originalBytes = new byte[] { 195, 132 }; + byte[] byteArray = Encoding.UTF8.GetBytes(originalString); + string resultString = Encoding.UTF8.GetString(byteArray); + byte[] resultByteArray = Encoding.UTF8.GetBytes(originalString); + + + Assert.That(resultString, Is.EqualTo(originalString)); + Assert.That(byteArray, Is.EqualTo(originalBytes)); + Assert.That(resultByteArray, Is.EqualTo(originalBytes)); + } + [Test] + public void TestMany() + { + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, null, null, null); + Assert.That(stringType.MinLength, Is.Null); + Assert.That(stringType.MaxLength, Is.Null); + + + Assert.DoesNotThrow(() => + { + PDL pdl = stringType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(0)); + Assert.That(pdl.MaxLength, Is.EqualTo(PDL.MAX_LENGTH)); + }); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 1, 32, null, null, null); + Assert.DoesNotThrow(() => + { + PDL pdl = stringType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(1)); + Assert.That(pdl.MaxLength, Is.EqualTo(32)); + }); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 1, 32, 0, 34, null); + Assert.DoesNotThrow(() => + { + PDL pdl = stringType.GetDataLength(); + Assert.That(pdl.Value, Is.Null); + Assert.That(pdl.MinLength, Is.EqualTo(0)); + Assert.That(pdl.MaxLength, Is.EqualTo(34)); + }); + + Assert.Throws(typeof(ArgumentException), () => stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "sting", null, null, null, null, null, null, null)); + } + [Test] + public void TestParseFixedLengthASCII() + { + Console.OutputEncoding = Encoding.ASCII; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, null, 5, true); + string str = "qwert"; + DataTree dataTree = new DataTree("NAME", 0, str); + byte[] data = stringType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 113, 119, 101, 114, 116 })); + DataTree reverseDataTree = stringType.ParseDataToPayload(ref data); + Assert.Multiple(() => + { + Assert.That(data, Has.Length.Zero); + Assert.That(reverseDataTree, Is.EqualTo(dataTree)); + }); + } + [Test] + public void TestParseFixedLengthInBytesUTF8() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, minBytes: 8, maxBytes: 8, null); + string str = "ÄÜÖß"; + DataTree dataTree = new DataTree("NAME", 0, str); + byte[] data = stringType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 195, 132, 195, 156, 195, 150, 195, 159 })); + DataTree reverseDataTree = stringType.ParseDataToPayload(ref data); + Assert.Multiple(() => + { + Assert.That(data, Has.Length.Zero); + Assert.That(reverseDataTree, Is.EqualTo(dataTree)); + }); + } + [Test] + public void TestParseRangedLengthUTF8() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 4, 6, null, null, null); + string str = "ÄÜÖß"; + DataTree dataTree = new DataTree("NAME", 0, str); + byte[] data = stringType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 195, 132, 195, 156, 195, 150, 195, 159 })); + DataTree reverseDataTree = stringType.ParseDataToPayload(ref data); + Assert.Multiple(() => + { + Assert.That(data, Has.Length.Zero); + Assert.That(reverseDataTree, Is.EqualTo(dataTree)); + }); + } + [Test] + public void TestParseRangedLengthUTF8Mixed() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 4, 6, 4, 8, null); + string str = "ÄUÖS"; + DataTree dataTree = new DataTree("NAME", 0, str); + byte[] data = stringType.ParsePayloadToData(dataTree); + Assert.That(data, Is.EqualTo(new byte[] { 195, 132, 85, 195, 150, 83 })); + DataTree reverseDataTree = stringType.ParseDataToPayload(ref data); + Assert.Multiple(() => + { + Assert.That(data, Has.Length.Zero); + Assert.That(reverseDataTree, Is.EqualTo(dataTree)); + }); + } + + [Test] + public void TestParseExceptions() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 3, 6, 5, 8, null); + string str = "12"; + DataTree dataTree = new DataTree("NAME FAIL", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + str = "1234"; + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + str = "1234567"; + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + + stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, 5, 8, null); + + str = "ÄÖÜ4567"; + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + str = "ÄÖÜÜÖÄ"; + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + str = null; + dataTree = new DataTree("NAME", 0, str); + Assert.Throws(typeof(ArithmeticException), () => stringType.ParsePayloadToData(dataTree)); + } + + [Test] + public void TestParseBadFormatedData1() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, null, null, 2, 8, null); + byte[] data = new byte[] { 195, 132, 0, 0, 0, 0 }; + var dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("Ä")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + + data = new byte[] { 195, 132, 0, 0, 119, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("Ä")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(2)); + + data = new byte[] { 0, 0, 0, 0, 0, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(string.Empty)); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + + data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(string.Empty)); + Assert.That(dataTree.Issues, Has.Length.EqualTo(2)); + + data = new byte[] { }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo(string.Empty)); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + + data = new byte[] { 195, 132, 195, 132, 195, 132, 195, 132, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("ÄÄÄÄ")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + data = new byte[] { 195, 132, 195, 132, 195, 132, 195, 132, 119, 119, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("ÄÄÄÄ")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + } + [Test] + public void TestParseBadFormatedData2() + { + Console.OutputEncoding = Encoding.UTF8; + var stringType = new StringType("NAME", "DISPLAY_NAME", "NOTES", null, "string", null, null, 2, 4, null, null, null); + byte[] data = new byte[] { 195, 132, 0, 0, 0, 0 }; + var dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("Ä")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(2)); + + data = new byte[] { 195, 132, 119, 119, 119, 119, 0 }; + dataTree = stringType.ParseDataToPayload(ref data); + Assert.That(dataTree.Value, Is.EqualTo("Äwwww")); + Assert.That(dataTree.Issues, Has.Length.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/Parser/TestDefinedDataTreeObjects.cs b/RDMSharpTests/Metadata/Parser/TestDefinedDataTreeObjects.cs new file mode 100644 index 0000000..702ffcb --- /dev/null +++ b/RDMSharpTests/Metadata/Parser/TestDefinedDataTreeObjects.cs @@ -0,0 +1,223 @@ +using RDMSharp.Metadata; +using System.Data; +using System.Reflection; +using System.Text; + +namespace RDMSharpTests.Metadata.Parser; + +public class TestDefinedDataTreeObjects +{ + [Test] + public void Test_AllDefinedDataTreeObjectsForValidility() + { + StringBuilder stringBuilder = new StringBuilder(); + foreach (var type in MetadataFactory.DefinedDataTreeObjects) + { + if (type.IsEnum) + continue; + + StringBuilder stringBuilder2 = new StringBuilder(); + + var constructors = type.GetConstructors().Where(c => c.GetCustomAttributes().Count() != 0); + if (constructors.Count() == 0) + stringBuilder2.AppendLine($"{type} not defines a {nameof(DataTreeObjectConstructorAttribute)}"); + + foreach (var constructor in constructors) + { + StringBuilder stringBuilder3 = new StringBuilder(); + var parameters = constructor.GetParameters(); + foreach (var para in parameters.Where(p => !p.GetCustomAttributes().Any(a=>a is DataTreeObjectParameterAttribute))) + stringBuilder3.AppendLine($"\t{para.Name}"); + if (stringBuilder3.Length > 0) + { + stringBuilder2.AppendLine($"{type} Constructor not defines {nameof(DataTreeObjectParameterAttribute)} for the Parameters:"); + stringBuilder2.AppendLine(stringBuilder3.ToString().TrimEnd()); + } + } + if (stringBuilder2.Length > 0) + stringBuilder.AppendLine(stringBuilder2.ToString().Trim()); + } + if (stringBuilder.Length > 0) + Assert.Fail(stringBuilder.ToString().Trim()); + } + + [Test] + public async Task Test_DeviceInfo() + { + byte[] data = { + 0x01, 0x00, 0x00, 0x05, 0x06, 0x01, 0x02, 0x00, + 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, + 0x00, 0x04, 0x00 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.DEVICE_INFO); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.GetResponse, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(RDMDeviceInfo))); + + var obj = dataTreeBranch.ParsedObject as RDMDeviceInfo; + Assert.That(obj.RdmProtocolVersionMajor, Is.EqualTo(1)); + Assert.That(obj.RdmProtocolVersionMinor, Is.EqualTo(0)); + Assert.That(obj.DeviceModelId, Is.EqualTo(0x0005)); + Assert.That(obj.ProductCategoryCoarse, Is.EqualTo(ERDM_ProductCategoryCoarse.POWER)); + Assert.That(obj.ProductCategoryFine, Is.EqualTo(ERDM_ProductCategoryFine.POWER_CONTROL)); + Assert.That(obj.SoftwareVersionId, Is.EqualTo(0x02000101)); + Assert.That(obj.Dmx512Footprint, Is.EqualTo(1)); + Assert.That(obj.Dmx512CurrentPersonality, Is.EqualTo(1)); + Assert.That(obj.Dmx512NumberOfPersonalities, Is.EqualTo(3)); + Assert.That(obj.Dmx512StartAddress, Is.EqualTo(1)); + Assert.That(obj.SubDeviceCount, Is.EqualTo(4)); + Assert.That(obj.SensorCount, Is.EqualTo(0)); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.GET_COMMAND_RESPONSE, ERDM_Parameter.DEVICE_INFO); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } + + [Test] + public async Task Test_Personality() + { + byte[] data = { + 0x01, 0x03 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.DMX_PERSONALITY); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.GetResponse, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(RDMDMXPersonality))); + + var obj = dataTreeBranch.ParsedObject as RDMDMXPersonality; + Assert.That(obj.CurrentPersonality, Is.EqualTo(1)); + Assert.That(obj.OfPersonalities, Is.EqualTo(3)); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.GET_COMMAND_RESPONSE, ERDM_Parameter.DMX_PERSONALITY); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } + + [Test] + public async Task Test_Personality_Description() + { + byte[] data = { + 0x01, 0x00, 0x01, 0x53, 0x45, 0x51, 0x55, 0x45, + 0x4e, 0x43, 0x45 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.DMX_PERSONALITY_DESCRIPTION); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.GetResponse, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(RDMDMXPersonalityDescription))); + + var obj = dataTreeBranch.ParsedObject as RDMDMXPersonalityDescription; + Assert.That(obj.PersonalityId, Is.EqualTo(1)); + Assert.That(obj.Slots, Is.EqualTo(1)); + Assert.That(obj.Description, Is.EqualTo("SEQUENCE")); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.GET_COMMAND_RESPONSE, ERDM_Parameter.DMX_PERSONALITY_DESCRIPTION); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } + + [Test] + public async Task Test_Slot_Description() + { + byte[] data = { + 0x00, 0x00, 0x53, 0x41, 0x46, 0x45, 0x54, 0x59 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.SLOT_DESCRIPTION); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.GetResponse, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(RDMSlotDescription))); + + var obj = dataTreeBranch.ParsedObject as RDMSlotDescription; + Assert.That(obj.SlotId, Is.EqualTo(0)); + Assert.That(obj.Description, Is.EqualTo("SAFETY")); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.GET_COMMAND_RESPONSE, ERDM_Parameter.SLOT_DESCRIPTION); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } + + [Test] + public async Task Test_Display_Invert() + { + byte[] data = { + 0x01 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.DISPLAY_INVERT); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.SetRequest, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(ERDM_DisplayInvert))); + + var obj = (ERDM_DisplayInvert)dataTreeBranch.ParsedObject; + Assert.That(obj, Is.EqualTo(ERDM_DisplayInvert.ON)); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.SET_COMMAND, ERDM_Parameter.DISPLAY_INVERT); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } + + [Test] + public async Task Test_Status_Messages() + { + byte[] data = { + 0x02 + }; + + var parameterBag = new ParameterBag(ERDM_Parameter.STATUS_MESSAGES); + var define = MetadataFactory.GetDefine(parameterBag); + + var dataTreeBranch = MetadataFactory.ParseDataToPayload(define, RDMSharp.Metadata.JSON.Command.ECommandDublicte.GetRequest, data); + + Assert.Multiple(() => + { + Assert.That(dataTreeBranch.IsUnset, Is.False); + Assert.That(dataTreeBranch.IsEmpty, Is.False); + Assert.That(dataTreeBranch.ParsedObject, Is.Not.Null); + Assert.That(dataTreeBranch.ParsedObject, Is.TypeOf(typeof(ERDM_Status))); + + var obj = (ERDM_Status)dataTreeBranch.ParsedObject; + Assert.That(obj, Is.EqualTo(ERDM_Status.ADVISORY)); + }); + + var reversed = DataTreeBranch.FromObject(dataTreeBranch.ParsedObject, ERDM_Command.GET_COMMAND, ERDM_Parameter.STATUS_MESSAGES); + Assert.That(reversed, Is.EqualTo(dataTreeBranch)); + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/TestMetadataFactoryStuff.cs b/RDMSharpTests/Metadata/TestMetadataFactoryStuff.cs new file mode 100644 index 0000000..c318669 --- /dev/null +++ b/RDMSharpTests/Metadata/TestMetadataFactoryStuff.cs @@ -0,0 +1,63 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata +{ + public class TestMetadataFactoryStuff + { + [SetUp] + public void Setup() + { + Console.OutputEncoding = System.Text.Encoding.Unicode; + } + [TearDown] + public void Teardown() + { + Console.OutputEncoding = System.Text.Encoding.Default; + } + + //[Test] + //public void TestMetadataFactory() + //{ + // var schemas = MetadataFactory.GetMetadataSchemaVersions(); + // Assert.That(schemas, Has.Count.EqualTo(1)); + // var defines = MetadataFactory.GetMetadataDefineVersions(); + // Assert.That(defines, Has.Count.EqualTo(122)); + // foreach (var define in defines) + // testString(define.ToString()); + //} + + [Test] + public void TestMetadataVersion() + { + var mv = new MetadataVersion("RDMSharp.Resources.JSON_Defines._1._0._0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.json"); + testString(mv.ToString()); + Assert.Multiple(() => + { + Assert.Throws(typeof(ArgumentNullException), () => MetadataVersion.getVersion(null)); + Assert.Throws(typeof(ArgumentNullException), () => MetadataVersion.getName(null)); + Assert.Throws(typeof(ArgumentNullException), () => MetadataVersion.getIsSchema(null)); + + Assert.Throws(typeof(FormatException), () => MetadataVersion.getVersion("RDMSharp.Resources.JSON_Defines.1.0.0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.json")); + Assert.Throws(typeof(FormatException), () => MetadataVersion.getVersion("RDMSharp.Resources.JSON_Defines._1._X._0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.json")); + Assert.Throws(typeof(ArgumentException), () => MetadataVersion.getVersion("RDMSharp.Resources.JSON_Defines._1._0._0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.jsan")); + Assert.Throws(typeof(FormatException), () => MetadataVersion.getName("RDMSharp.Resources.JSON_Defines._1._0._0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.jsan")); + Assert.Throws(typeof(ArgumentException), () => MetadataVersion.getIsSchema("RDMSharp.Resources.JSON_Defines._1._0._0.Defines.e1._20.BOOT_SOFTWARE_VERSION_ID.jsan")); + }); + } + + [Test] + public void TestMetadataBag() + { + var bag = new MetadataBag("1.0.2", "NAME.json", false, "content", "Path"); + testString(bag.ToString()); + Assert.Throws(typeof(ArgumentNullException), () => MetadataBag.getContent(null)); + } + static void testString(string str) + { + Assert.That(str, Is.Not.WhiteSpace); + Assert.That(str, Is.Not.Empty); + Assert.That(str, Does.Not.Contain("{")); + Assert.That(str, Does.Not.Contain("}")); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/TestParameterBag.cs b/RDMSharpTests/Metadata/TestParameterBag.cs new file mode 100644 index 0000000..bb49cc0 --- /dev/null +++ b/RDMSharpTests/Metadata/TestParameterBag.cs @@ -0,0 +1,99 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata +{ + public class TestParameterBag + { + + [Test] + public void TestMany() + { + Assert.Throws(typeof(NotSupportedException), () => new ParameterBag()); + HashSet parameterBags = new HashSet(); + Assert.DoesNotThrow(() => parameterBags.Add(new ParameterBag(ERDM_Parameter.CURVE))); + + + ERDM_Parameter pid = ERDM_Parameter.ADD_TAG; + ParameterBag bag = new ParameterBag(pid); + parameterBags.Add(bag); + Assert.Multiple(() => + { + Assert.That(bag, Is.Not.Default); + Assert.That(bag.PID, Is.EqualTo(pid)); + Assert.That(bag.ManufacturerID, Is.EqualTo(0)); + Assert.That(bag.DeviceModelID, Is.EqualTo(null)); + Assert.That(bag.SoftwareVersionID, Is.EqualTo(null)); + Assert.That(bag.ToString(), Is.EqualTo(pid.ToString())); + }); + + pid = (ERDM_Parameter)0x8943; + bag = new ParameterBag(pid, 432, 678, 42); + parameterBags.Add(bag); + Assert.Multiple(() => + { + Assert.That(bag, Is.Not.Default); + Assert.That(bag.PID, Is.EqualTo(pid)); + Assert.That(bag.ManufacturerID, Is.EqualTo(432)); + Assert.That(bag.DeviceModelID, Is.EqualTo(678)); + Assert.That(bag.SoftwareVersionID, Is.EqualTo(42)); + Assert.That(bag.ToString(), Is.EqualTo($"{pid} ManufacturerID: {432}, DeviceModelID: {678}, SoftwareVersionID: {42}")); + }); + + bag = new ParameterBag(pid, 432, 678); + parameterBags.Add(bag); + Assert.Multiple(() => + { + Assert.That(bag, Is.Not.Default); + Assert.That(bag.PID, Is.EqualTo(pid)); + Assert.That(bag.ManufacturerID, Is.EqualTo(432)); + Assert.That(bag.DeviceModelID, Is.EqualTo(678)); + Assert.That(bag.SoftwareVersionID, Is.EqualTo(null)); + Assert.That(bag.ToString(), Is.EqualTo($"{pid} ManufacturerID: {432}, DeviceModelID: {678}")); + }); + + bag = new ParameterBag(pid, 432); + parameterBags.Add(bag); + Assert.Multiple(() => + { + Assert.That(bag, Is.Not.Default); + Assert.That(bag.PID, Is.EqualTo(pid)); + Assert.That(bag.ManufacturerID, Is.EqualTo(432)); + Assert.That(bag.DeviceModelID, Is.EqualTo(null)); + Assert.That(bag.SoftwareVersionID, Is.EqualTo(null)); + Assert.That(bag.ToString(), Is.EqualTo($"{pid} ManufacturerID: {432}")); + }); + + Assert.Throws(typeof(ArgumentNullException), () => new ParameterBag(pid)); + } + + + [Test] + public void TestEqualMethodes() + { + Assert.Multiple(() => + { + Assert.That(new ParameterBag(ERDM_Parameter.CURVE) == new ParameterBag(ERDM_Parameter.CURVE), Is.True); + Assert.That(new ParameterBag(ERDM_Parameter.CURVE) == new ParameterBag(ERDM_Parameter.DIMMER_INFO), Is.False); + + Assert.That(new ParameterBag(ERDM_Parameter.CURVE) != new ParameterBag(ERDM_Parameter.CURVE), Is.False); + Assert.That(new ParameterBag(ERDM_Parameter.CURVE) != new ParameterBag(ERDM_Parameter.DIMMER_INFO), Is.True); + + Assert.That(new ParameterBag(ERDM_Parameter.CURVE).Equals(new ParameterBag(ERDM_Parameter.CURVE)), Is.True); + Assert.That(new ParameterBag(ERDM_Parameter.CURVE).Equals(new ParameterBag(ERDM_Parameter.DIMMER_INFO)), Is.False); + + Assert.That(new ParameterBag(ERDM_Parameter.CURVE).Equals((object)new ParameterBag(ERDM_Parameter.CURVE)), Is.True); + Assert.That(new ParameterBag(ERDM_Parameter.CURVE).Equals((object)new ParameterBag(ERDM_Parameter.DIMMER_INFO)), Is.False); + + Assert.That(new ParameterBag(ERDM_Parameter.CURVE).Equals(null), Is.False); + + ERDM_Parameter pid = (ERDM_Parameter)0x8555; + Assert.That(new ParameterBag(pid, 1), Is.Not.EqualTo(new ParameterBag(pid, 2))); + Assert.That(new ParameterBag(pid, 1), Is.Not.EqualTo(new ParameterBag(pid, 1, 444))); + Assert.That(new ParameterBag(pid, 1, 444), Is.Not.EqualTo(new ParameterBag(pid, 1, 444, 5))); +#pragma warning disable NUnit2009 + Assert.That(new ParameterBag(pid, 1, 444, 5), Is.EqualTo(new ParameterBag(pid, 1, 444, 5))); +#pragma warning restore NUnit2009 + }); + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/Metadata/TestPeerToPeerProcess.cs b/RDMSharpTests/Metadata/TestPeerToPeerProcess.cs new file mode 100644 index 0000000..93c2489 --- /dev/null +++ b/RDMSharpTests/Metadata/TestPeerToPeerProcess.cs @@ -0,0 +1,181 @@ +using RDMSharp.Metadata; + +namespace RDMSharpTests.Metadata +{ + public class TestPeerToPeerProcess + { + + [Test] + public async Task Test_Get_DMX_START_ADDRESS() + { + var command = ERDM_Command.GET_COMMAND; + var uid = new UID(1234, 123456); + var subdevice = SubDevice.Root; + var parameterBag = new ParameterBag(ERDM_Parameter.DMX_START_ADDRESS); + const ushort DMX_ADDRESS = 33; + PeerToPeerProcess peerToPeerProcess = new PeerToPeerProcess(command, uid, subdevice, parameterBag); + + Assert.That(peerToPeerProcess.Define, Is.Not.Null); + Assert.That(peerToPeerProcess.State, Is.EqualTo(PeerToPeerProcess.EPeerToPeerProcessState.Waiting)); + Assert.That(peerToPeerProcess.RequestPayloadObject.IsUnset, Is.True); + Assert.That(peerToPeerProcess.ResponsePayloadObject.IsUnset, Is.True); + + AsyncRDMRequestHelper helper = null; + helper = new AsyncRDMRequestHelper(sendMessage); + + await Task.WhenAny( + peerToPeerProcess.Run(helper), + Task.Run(async () => + { + while (peerToPeerProcess.State == PeerToPeerProcess.EPeerToPeerProcessState.Running) + await Task.Delay(100); + })); + + Assert.That(peerToPeerProcess.ResponsePayloadObject, Is.TypeOf(typeof(DataTreeBranch))); + Assert.That(peerToPeerProcess.ResponsePayloadObject.Children[0].Value, Is.EqualTo(DMX_ADDRESS)); + Assert.That(peerToPeerProcess.ResponsePayloadObject.ParsedObject, Is.EqualTo(DMX_ADDRESS)); + + async Task sendMessage(RDMMessage message) + { + Assert.That(message.Command, Is.EqualTo(command)); + Assert.That(message.DestUID, Is.EqualTo(uid)); + Assert.That(message.SubDevice, Is.EqualTo(subdevice)); + Assert.That(message.Parameter, Is.EqualTo(parameterBag.PID)); + + RDMMessage response = new RDMMessage() + { + Command = message.Command | ERDM_Command.RESPONSE, + DestUID = message.SourceUID, + SourceUID = message.DestUID, + Parameter = message.Parameter, + SubDevice = message.SubDevice, + ParameterData = MetadataFactory.GetResponseMessageData(parameterBag, new DataTreeBranch(new DataTree[] { new DataTree("dmx_address", 0, DMX_ADDRESS) })) + }; + + await Task.Delay(10); + helper.ReceiveMessage(response); + } + } + + + [Test] + public async Task Test_Get_PROXIED_DEVICES() + { + var command = ERDM_Command.GET_COMMAND; + var uid = new UID(1234, 123456); + var subdevice = SubDevice.Root; + var parameterBag = new ParameterBag(ERDM_Parameter.PROXIED_DEVICES); + DataTree[] children = new DataTree[500]; + Random rnd = new Random(); + for (int i = 0; i < children.Length; i++) + children[i] = new DataTree("device_uid", (uint)i, new UID(0x1234, (uint)rnd.Next(1, int.MaxValue))); + + PeerToPeerProcess peerToPeerProcess = new PeerToPeerProcess(command, uid, subdevice, parameterBag); + + Assert.That(peerToPeerProcess.Define, Is.Not.Null); + Assert.That(peerToPeerProcess.State, Is.EqualTo(PeerToPeerProcess.EPeerToPeerProcessState.Waiting)); + Assert.That(peerToPeerProcess.RequestPayloadObject.IsUnset, Is.True); + Assert.That(peerToPeerProcess.ResponsePayloadObject.IsUnset, Is.True); + + AsyncRDMRequestHelper helper = null; + byte[] parameterData = MetadataFactory.GetResponseMessageData(parameterBag, new DataTreeBranch(new DataTree[] { new DataTree("device_uids", 0, children: children) })); + helper = new AsyncRDMRequestHelper(sendMessage); + + await Task.WhenAny( + peerToPeerProcess.Run(helper), + Task.Run(async () => + { + while (peerToPeerProcess.State == PeerToPeerProcess.EPeerToPeerProcessState.Running) + await Task.Delay(100); + })); + + Assert.That(peerToPeerProcess.ResponsePayloadObject, Is.TypeOf(typeof(DataTreeBranch))); + Assert.That(peerToPeerProcess.ResponsePayloadObject.Children[0].Children, Is.EqualTo(children)); + Assert.That(peerToPeerProcess.ResponsePayloadObject.ParsedObject, Is.EqualTo(children.Select(dt => dt.Value).ToList())); + + + async Task sendMessage(RDMMessage message) + { + Assert.That(message.Command, Is.EqualTo(command)); + Assert.That(message.DestUID, Is.EqualTo(uid)); + Assert.That(message.SubDevice, Is.EqualTo(subdevice)); + Assert.That(message.Parameter, Is.EqualTo(parameterBag.PID)); + + var count = Math.Min(parameterData.Length, 0xE4); + var _parameterData = parameterData.Take(count).ToArray(); + parameterData= parameterData.Skip(count).ToArray(); + RDMMessage response = new RDMMessage() + { + Command = message.Command | ERDM_Command.RESPONSE, + DestUID = message.SourceUID, + SourceUID = message.DestUID, + Parameter = message.Parameter, + SubDevice = message.SubDevice, + ParameterData = _parameterData, + PortID_or_Responsetype = parameterData.Length == 0 ? (byte)ERDM_ResponseType.ACK : (byte)ERDM_ResponseType.ACK_OVERFLOW + }; + + await Task.Delay(10); + helper.ReceiveMessage(response); + } + } + [Test] + public async Task Test_Get_LAMP_STRIKES() + { + var command = ERDM_Command.GET_COMMAND; + var uid = new UID(1234, 123456); + var subdevice = SubDevice.Root; + var parameterBag = new ParameterBag(ERDM_Parameter.LAMP_STRIKES); + const uint LAMP_STRIKES = 33; + PeerToPeerProcess peerToPeerProcess = new PeerToPeerProcess(command, uid, subdevice, parameterBag); + + Assert.That(peerToPeerProcess.Define, Is.Not.Null); + Assert.That(peerToPeerProcess.State, Is.EqualTo(PeerToPeerProcess.EPeerToPeerProcessState.Waiting)); + Assert.That(peerToPeerProcess.RequestPayloadObject.IsUnset, Is.True); + Assert.That(peerToPeerProcess.ResponsePayloadObject.IsUnset, Is.True); + + AsyncRDMRequestHelper helper = null; + byte count = 0; + helper = new AsyncRDMRequestHelper(sendMessage); + + await Task.WhenAny( + peerToPeerProcess.Run(helper), + Task.Run(async () => + { + while (peerToPeerProcess.State == PeerToPeerProcess.EPeerToPeerProcessState.Running) + await Task.Delay(100); + })); + + Assert.That(peerToPeerProcess.ResponsePayloadObject, Is.TypeOf(typeof(DataTreeBranch))); + Assert.That(peerToPeerProcess.ResponsePayloadObject.Children[0].Value, Is.EqualTo(LAMP_STRIKES)); + Assert.That(peerToPeerProcess.ResponsePayloadObject.ParsedObject, Is.EqualTo(LAMP_STRIKES)); + + async Task sendMessage(RDMMessage message) + { + Assert.That(count, Is.LessThan(2)); + if(count==0) + Assert.That(message.Parameter, Is.EqualTo(parameterBag.PID)); + else if(count==1) + Assert.That(message.Parameter, Is.EqualTo(ERDM_Parameter.QUEUED_MESSAGE)); + Assert.That(message.Command, Is.EqualTo(command)); + Assert.That(message.DestUID, Is.EqualTo(uid)); + Assert.That(message.SubDevice, Is.EqualTo(subdevice)); + + RDMMessage response = new RDMMessage() + { + Command = message.Command | ERDM_Command.RESPONSE, + DestUID = message.SourceUID, + SourceUID = message.DestUID, + Parameter = parameterBag.PID, + SubDevice = message.SubDevice, + ParameterData = count == 0 ? new AcknowledgeTimer(TimeSpan.FromSeconds(3)).ToPayloadData() : MetadataFactory.GetResponseMessageData(parameterBag, new DataTreeBranch(new DataTree[] { new DataTree("strikes", 0, LAMP_STRIKES) })), + PortID_or_Responsetype = count == 0 ? (byte)ERDM_ResponseType.ACK_TIMER : (byte)ERDM_ResponseType.ACK + }; + + await Task.Delay(10); + count++; + helper.ReceiveMessage(response); + } + } + } +} \ No newline at end of file diff --git a/RDMSharpTests/RDM/PayloadObject/AcknowledgeTimerTest.cs b/RDMSharpTests/RDM/PayloadObject/AcknowledgeTimerTest.cs index 2be1428..49b5ede 100644 --- a/RDMSharpTests/RDM/PayloadObject/AcknowledgeTimerTest.cs +++ b/RDMSharpTests/RDM/PayloadObject/AcknowledgeTimerTest.cs @@ -10,7 +10,7 @@ public void Setup() [Test] public void ToPayloadAndFromMessageTest() { - var time = TimeSpan.FromSeconds(360000); + var time = TimeSpan.FromSeconds(3); AcknowledgeTimer acknowledgeTimer = new AcknowledgeTimer(time); byte[] data = acknowledgeTimer.ToPayloadData(); diff --git a/RDMSharpTests/RDMSharpTests.csproj b/RDMSharpTests/RDMSharpTests.csproj index bcd1ef9..660c5ca 100644 --- a/RDMSharpTests/RDMSharpTests.csproj +++ b/RDMSharpTests/RDMSharpTests.csproj @@ -9,11 +9,10 @@ latest False - - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -23,7 +22,30 @@ - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_128BIT_INTEGER_TEST.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_128BIT_INTEGER_TEST.json new file mode 100644 index 0000000..f82be9e --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_128BIT_INTEGER_TEST.json @@ -0,0 +1,18 @@ +{ + "name": "MOCK_128BIT_INTEGER_TEST", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "timeout", + "type": "int128" + }, + { + "name": "timeout", + "type": "uint128" + } + ], + "get_response": "get_request" +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_ALL_INTEGER_TEST_EXCEPT_128BIT.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_ALL_INTEGER_TEST_EXCEPT_128BIT.json new file mode 100644 index 0000000..53d5d10 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_ALL_INTEGER_TEST_EXCEPT_128BIT.json @@ -0,0 +1,42 @@ +{ + "name": "MOCK_ALL_INTEGER_TEST_EXCEPT_128BIT", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "timeout", + "type": "int8" + }, + { + "name": "timeout", + "type": "uint8" + }, + { + "name": "timeout", + "type": "int16" + }, + { + "name": "timeout", + "type": "uint16" + }, + { + "name": "timeout", + "type": "int32" + }, + { + "name": "timeout", + "type": "uint32" + }, + { + "name": "timeout", + "type": "int64" + }, + { + "name": "timeout", + "type": "uint64" + } + ], + "get_response": "get_request" +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_DISPLAY_NAME.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_DISPLAY_NAME.json new file mode 100644 index 0000000..e0f8138 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_DISPLAY_NAME.json @@ -0,0 +1,62 @@ +{ + "name": "MOCK_DISPLAY_NAME", + "displayName": "Mock Display Name", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "timeout", + "displayName": "Timeout", + "type": "uint16", + "units": 21, + "prefixPower": 0, + "labels": [ + { + "name": "Disabled", + "displayName": "Disabled Label", + "value": 0 + } + ] + }, + { + "name": "label", + "displayName": "Label", + "type": "string", + "maxLength": 32, + "restrictToASCII": true + }, + { + "name": "status", + "displayName": "Status", + "type": "boolean" + }, + { + "name": "slots", + "displayName": "Slots", + "type": "list", + "itemType": { + "displayName": "Compound", + "type": "compound", + "subtypes": [ + { + "name": "id", + "type": "uint16" + }, + { + "name": "type", + "type": "uint8" + }, + { + "name": "label_id", + "type": "uint16" + } + ] + }, + "minItems": 2, + "maxItems": 6 + } + ], + "get_response": "get_request" +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_1.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_1.json new file mode 100644 index 0000000..5862d9b --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_1.json @@ -0,0 +1,11 @@ +{ + "name": "MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_1", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "$ref": "#/set_response/0" } + ] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_2.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_2.json new file mode 100644 index 0000000..6230687 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_2.json @@ -0,0 +1,11 @@ +{ + "name": "MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_2", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response": [ + { "$ref": "#/set_request/0" } + ] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_3.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_3.json new file mode 100644 index 0000000..a591e55 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_3.json @@ -0,0 +1,11 @@ +{ + "name": "MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_3", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices" ], + "set_request": [], + "set_response": [ + { "$ref": "#/get_response/0" } + ] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_4.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_4.json new file mode 100644 index 0000000..1cf0087 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_4.json @@ -0,0 +1,11 @@ +{ + "name": "MOCK_INVALID_BUT_SCHEMA_IS_VALID_REFERENCE_TYPE_NOT_DEFINED_3", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "set_request_subdevice_range": [ "root", "subdevices" ], + "set_request": [], + "set_response": [ + { "$ref": "#/get_request/0" } + ] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_COMMAND_NUMBER.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_COMMAND_NUMBER.json new file mode 100644 index 0000000..16c77bf --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_COMMAND_NUMBER.json @@ -0,0 +1,9 @@ +{ + "name": "MOCK_INVALID_COMMAND_NUMBER", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": 22, + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ENUM.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ENUM.json new file mode 100644 index 0000000..21e6a67 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ENUM.json @@ -0,0 +1,9 @@ +{ + "name": "MOCK_INVALID_ENUM", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "INVALID" ], + "get_request": [], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_GET_PAIR.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_GET_PAIR.json new file mode 100644 index 0000000..694408a --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_GET_PAIR.json @@ -0,0 +1,8 @@ +{ + "name": "MOCK_INVALID_NO_GET_PAIR", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", 1 ], + "get_request": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_SET_PAIR.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_SET_PAIR.json new file mode 100644 index 0000000..389a86f --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_NO_SET_PAIR.json @@ -0,0 +1,8 @@ +{ + "name": "MOCK_INVALID_NO_SET_PAIR", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "set_request_subdevice_range": [ "root", 1 ], + "set_request": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ONEOF_TYPE.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ONEOF_TYPE.json new file mode 100644 index 0000000..12822f6 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_ONEOF_TYPE.json @@ -0,0 +1,14 @@ +{ + "name": "MOCK_INVALID_ONEOF_TYPE", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "Invalid Type", + "invalid": "invalid" + } + ], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_REQUEST.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_REQUEST.json new file mode 100644 index 0000000..67b8e77 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_REQUEST.json @@ -0,0 +1,9 @@ +{ + "name": "MOCK_INVALID_SUBDEVICE_TYPE_REQUEST", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", null, [ 2, 3, 4 ] ], + "get_request": [], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_RESPONSE.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_RESPONSE.json new file mode 100644 index 0000000..5b5ca98 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_SUBDEVICE_TYPE_RESPONSE.json @@ -0,0 +1,10 @@ +{ + "name": "MOCK_INVALID_SUBDEVICE_TYPE_RESPONSE", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [], + "get_response_subdevice_range": [ "root", [ 2, 5 ], null ], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_TYPE.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_TYPE.json new file mode 100644 index 0000000..05ac1ef --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_INVALID_TYPE.json @@ -0,0 +1,14 @@ +{ + "name": "MOCK_INVALID_TYPE", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "Invalid Type", + "type": "invalid" + } + ], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_PD_ENVELOPED.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_PD_ENVELOPED.json new file mode 100644 index 0000000..82da703 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_PD_ENVELOPED.json @@ -0,0 +1,25 @@ +{ + "name": "MOCK_PD_ENVELOPED", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "timeout", + "displayName": "Timeout", + "type": "pdEnvelope", + "length": 21 + }, + { + "name": "subdevice_entry", + "type": "pdEnvelope" + }, + { + "name": "entries", + "type": "list", + "itemType": { "type": "pdEnvelope" } + } + ], + "get_response": "get_request" +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_REFERENCE_TYPE.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_REFERENCE_TYPE.json new file mode 100644 index 0000000..9204deb --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_REFERENCE_TYPE.json @@ -0,0 +1,65 @@ +{ + "name": "MOCK_REFERENCE_TYPE", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "root_personality", + "type": "uint8", + "ranges": [ + { + "minimum": 1, + "maximum": 255 + } + ] + }, + { + "name": "subdevice", + "type": "uint16", + "labels": [ + { + "name": "root", + "value": 0 + } + ] + }, + { + "name": "subdevice_personality", + "type": "uint8", + "labels": [ + { + "name": "root", + "value": 0 + } + ] + } + ], + "get_response": [ + { "$ref": "#/set_response/0" } + ], + "set_request": [], + "set_response": [ + { + "name": "root_personality", + "type": "uint8", + "ranges": [ + { + "minimum": 1, + "maximum": 255 + } + ] + }, + { + "name": "subdevice", + "type": "uint16", + "labels": [ + { + "name": "root", + "value": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD.json new file mode 100644 index 0000000..8db8e8f --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD.json @@ -0,0 +1,20 @@ +{ + "name": "MOCK_SINGLE_FIELD", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": { + "name": "timeout", + "type": "uint16", + "units": 21, + "prefixPower": 0, + "labels": [ + { + "name": "Disabled", + "value": 0 + } + ] + }, + "get_response": "get_request" +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD_REFERENCE.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD_REFERENCE.json new file mode 100644 index 0000000..26c7c82 --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SINGLE_FIELD_REFERENCE.json @@ -0,0 +1,40 @@ +{ + "name": "MOCK_SINGLE_FIELD_REFERENCE", + "manufacturer_id": 4365, + "pid": 4874, + "version": 1, + "get_request_subdevice_range": [ "root", "subdevices" ], + "get_request": [ + { + "name": "root_personality", + "type": "uint8", + "ranges": [ + { + "minimum": 1, + "maximum": 255 + } + ] + }, + { + "name": "subdevice", + "type": "uint16", + "labels": [ + { + "name": "root", + "value": 0 + } + ] + }, + { + "name": "subdevice_personality", + "type": "uint8", + "labels": [ + { + "name": "root", + "value": 0 + } + ] + } + ], + "get_response": { "$ref": "#/get_request/0" } +} \ No newline at end of file diff --git a/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SUBDEVICE_TYPES.json b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SUBDEVICE_TYPES.json new file mode 100644 index 0000000..61fc0ab --- /dev/null +++ b/RDMSharpTests/Resources/JSON-Defines/1.0.0/Defines/Mocks/MOCK_SUBDEVICE_TYPES.json @@ -0,0 +1,35 @@ +{ + "name": "MOCK_SUBDEVICE_TYPES", + "manufacturer_id": 3456, + "pid": 5678, + "version": 1, + "get_request_subdevice_range": [ + "root", + "subdevices", + 1, + 2, + 3, + 4, + 5, + { + "minimum": 70, + "maximum": 200 + } + ], + "get_request": [], + "get_response_subdevice_range": [ + "root", + "subdevices", + 45, + 75, + 86, + 99, + 23, + { + "minimum": 56, + "maximum": 79 + }, + 256 + ], + "get_response": [] +} \ No newline at end of file diff --git a/RDMSharpTests/TestManyObjects.cs b/RDMSharpTests/TestManyObjects.cs index 8c1b9b9..2af1335 100644 --- a/RDMSharpTests/TestManyObjects.cs +++ b/RDMSharpTests/TestManyObjects.cs @@ -1,3 +1,4 @@ +using RDMSharp.RDM; using System.Collections.Concurrent; using System.Reflection; @@ -245,7 +246,7 @@ public void TestSlot() }); } } - [Test] + [Test] public void TestGeneratedPersonality() { Assert.Throws(typeof(ArgumentOutOfRangeException), () => new GeneratedPersonality(0, "5CH RGB", @@ -284,5 +285,64 @@ public void TestGeneratedPersonality() Assert.That(pers.ID, Is.EqualTo(1)); }); } + [Test] + public void TestPDL() + { + Assert.Multiple(() => + { + PDL pdl = new PDL(); + Assert.That(pdl.Value.HasValue, Is.True); + Assert.That(pdl.MinLength.HasValue, Is.False); + Assert.That(pdl.MaxLength.HasValue, Is.False); + Assert.That(pdl.Value.Value, Is.EqualTo(0)); + + pdl = new PDL(13); + Assert.That(pdl.Value.HasValue, Is.True); + Assert.That(pdl.MinLength.HasValue, Is.False); + Assert.That(pdl.MaxLength.HasValue, Is.False); + Assert.That(pdl.Value.Value, Is.EqualTo(13)); + + + pdl = new PDL(3, 5); + Assert.That(pdl.Value.HasValue, Is.False); + Assert.That(pdl.MinLength.HasValue, Is.True); + Assert.That(pdl.MaxLength.HasValue, Is.True); + Assert.That(pdl.MinLength.Value, Is.EqualTo(3)); + Assert.That(pdl.MaxLength.Value, Is.EqualTo(5)); + + pdl = new PDL(5, 5); + Assert.That(pdl.Value.HasValue, Is.True); + Assert.That(pdl.MinLength.HasValue, Is.False); + Assert.That(pdl.MaxLength.HasValue, Is.False); + Assert.That(pdl.Value.Value, Is.EqualTo(5)); + + + List list = new List(); + list.Add(new PDL(1)); + list.Add(new PDL(2)); + list.Add(new PDL(3)); + pdl = new PDL(list.ToArray()); + Assert.That(pdl.Value.HasValue, Is.True); + Assert.That(pdl.MinLength.HasValue, Is.False); + Assert.That(pdl.MaxLength.HasValue, Is.False); + Assert.That(pdl.Value.Value, Is.EqualTo(6)); + + list.Clear(); + list.Add(new PDL(1, 2)); + list.Add(new PDL(1, 2)); + list.Add(new PDL(3, 4)); + pdl = new PDL(list.ToArray()); + Assert.That(pdl.Value.HasValue, Is.False); + Assert.That(pdl.MinLength.HasValue, Is.True); + Assert.That(pdl.MaxLength.HasValue, Is.True); + Assert.That(pdl.MinLength.Value, Is.EqualTo(5)); + Assert.That(pdl.MaxLength.Value, Is.EqualTo(8)); + + + Assert.Throws(typeof(ArgumentOutOfRangeException), () => new PDL(uint.MaxValue)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => new PDL(uint.MaxValue, 9)); + Assert.Throws(typeof(ArgumentOutOfRangeException), () => new PDL(1, uint.MaxValue)); + }); + } } } \ No newline at end of file