Simplify registers

- add array conversion
- fixed dt area merging
This commit is contained in:
Felix Weiß
2023-07-17 00:41:27 +02:00
parent 4666d3071b
commit d6c00097bc
68 changed files with 1479 additions and 1210 deletions

View File

@@ -3,7 +3,6 @@ using MewtocolNet.Registers;
using MewtocolNet.TypeConversion;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace MewtocolNet {
@@ -12,71 +11,173 @@ namespace MewtocolNet {
private static List<IPlcTypeConverter> conversions => Conversions.items;
internal static T Parse<T> (IRegister register, byte[] bytes) {
internal static T Parse<T>(Register register, byte[] bytes) {
IPlcTypeConverter converter;
Type underlyingType;
//special case for enums
if(typeof(T).IsEnum) {
if (typeof(T).IsEnum) {
var underlyingNumberType = typeof(T).GetEnumUnderlyingType();
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == underlyingNumberType);
underlyingType = typeof(T).GetEnumUnderlyingType();
} else {
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == typeof(T));
underlyingType = typeof(T);
}
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == underlyingType);
if (converter == null)
throw new MewtocolException($"A converter for the dotnet type {typeof(T)} doesn't exist");
throw new MewtocolException($"A converter for the dotnet type {underlyingType} doesn't exist");
return (T)converter.FromRawData(register, bytes);
}
internal static byte[] Encode<T> (IRegister register, T value) {
internal static T ParseArray <T>(Register register, int[] indices, byte[] bytes) {
IPlcTypeConverter converter;
Type underlyingElementType;
//special case for enums
if (typeof(T).IsEnum) {
var underlyingNumberType = typeof(T).GetEnumUnderlyingType();
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == underlyingNumberType);
underlyingElementType = typeof(T).GetElementType().GetEnumUnderlyingType();
} else {
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == typeof(T));
underlyingElementType = typeof(T).GetElementType();
}
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == underlyingElementType);
if (converter == null)
throw new MewtocolException($"A converter for the dotnet type {typeof(T)} doesn't exist");
throw new MewtocolException($"A converter for the dotnet type {underlyingElementType} doesn't exist");
//parse the array from one to n dimensions
var outArray = Array.CreateInstance(underlyingElementType, indices);
if(outArray.GetType() == typeof(byte[])) {
Console.WriteLine();
}
int sizePerItem = underlyingElementType.DetermineTypeByteSize();
var iterateItems = indices.Aggregate((a, x) => a * x);
var indexer = new int[indices.Length];
for (int i = 0; i < iterateItems; i++) {
int j = i * sizePerItem;
var currentItem = bytes.Skip(j).Take(sizePerItem).ToArray();
var value = converter.FromRawData(register, currentItem);
for (int remainder = i, k = indices.Length - 1; k >= 0; k--) {
int currentDimension = indices[k];
indexer[k] = remainder % currentDimension;
remainder = remainder / currentDimension;
}
outArray.SetValue(value, indexer);
}
return (T)(object)outArray;
}
static void ConvertFlatArrayToDim (
IPlcTypeConverter converter,
Register register,
byte[] source,
Array target,
int sizePerVal,
int[] dims,
int currentIndex,
int currentArrayIndex
) {
if (currentIndex == dims.Length - 1) {
for (int i = 0; i < dims[currentIndex]; i++) {
byte[] rawDataItem = source.Skip(currentArrayIndex).Take(sizePerVal).ToArray();
var value = converter.FromRawData(register, rawDataItem);
target.SetValue(value, i);
currentArrayIndex += sizePerVal;
}
} else {
for (int i = 0; i < dims[currentIndex]; i++) {
Array innerArray = (Array)target.GetValue(i);
ConvertFlatArrayToDim(converter, register, source, innerArray, sizePerVal, dims, currentIndex + 1, currentArrayIndex);
currentArrayIndex += innerArray.Length * sizePerVal;
}
}
}
internal static byte[] Encode<T>(Register register, T value) {
IPlcTypeConverter converter;
Type underlyingType;
//special case for enums
if (typeof(T).IsEnum) {
underlyingType = typeof(T).GetEnumUnderlyingType();
} else {
underlyingType = typeof(T);
}
converter = conversions.FirstOrDefault(x => x.GetDotnetType() == underlyingType);
if (converter == null)
throw new MewtocolException($"A converter for the type {underlyingType} doesn't exist");
return converter.ToRawData(register, value);
}
public static List<Type> GetAllowDotnetTypes () => conversions.Select(x => x.GetDotnetType()).ToList();
//internal static byte[] EncodeArray (IRegister register, T value) {
public static List<Type> GetAllowRegisterTypes () => conversions.Select(x => x.GetHoldingRegisterType()).ToList();
public static RegisterType? GetDefaultRegisterType (Type type) =>
//}
public static List<Type> GetAllowDotnetTypes() => conversions.Select(x => x.GetDotnetType()).ToList();
public static List<Type> GetAllowRegisterTypes() => conversions.Select(x => x.GetHoldingRegisterType()).ToList();
public static RegisterType? GetDefaultRegisterType(Type type) =>
conversions.FirstOrDefault(x => x.GetDotnetType() == type)?.GetPlcRegisterType();
public static Type GetDefaultRegisterHoldingType (this PlcVarType type) =>
public static Type GetDefaultRegisterHoldingType(this PlcVarType type) =>
conversions.FirstOrDefault(x => x.GetPlcVarType() == type)?.GetHoldingRegisterType();
public static Type GetDefaultRegisterHoldingType (this Type type) =>
public static Type GetDefaultRegisterHoldingType(this Type type) =>
conversions.FirstOrDefault(x => x.GetDotnetType() == type)?.GetHoldingRegisterType();
public static Type GetDefaultDotnetType (this PlcVarType type) =>
public static Type GetDefaultDotnetType(this PlcVarType type) =>
conversions.FirstOrDefault(x => x.GetPlcVarType() == type)?.GetDotnetType();
public static PlcVarType? GetDefaultPlcVarType (this Type type) =>
public static PlcVarType? GetDefaultPlcVarType(this Type type) =>
conversions.FirstOrDefault(x => x.GetDotnetType() == type)?.GetPlcVarType();
}