You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.2 KiB

6 months ago
using HybirdFrameworkCore.Utils;
using log4net;
namespace HybirdFrameworkDriver.ModbusTcpMaster;
public static class ModbusDecoder
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusDecoder));
public static T Decode<T>(byte[] bytes) where T : class, new()
{
T t = new T();
List<object?> fields = t.GetType().GetProperties()
.Where(it => it.PropertyType.GetGenericTypeDefinition() == typeof(ModbusProperty<>))
.Select(p => p.GetValue(t)).ToList();
int startRegisterNo = Int32.MaxValue;
foreach (object? field in fields)
6 months ago
{
if (field != null)
{
IModbusProperty p = (IModbusProperty)field;
if (startRegisterNo > p.GetRegisterNo())
{
startRegisterNo = p.GetRegisterNo();
}
}
}
foreach (object? field in fields)
6 months ago
{
switch (field)
{
case ModbusProperty<byte> property:
{
SetPropertyValue(startRegisterNo, property, bytes);
break;
}
case ModbusProperty<float> floatProperty:
{
SetPropertyValue(startRegisterNo, floatProperty, bytes);
break;
}
}
}
return t;
}
private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes)
{
int registerNo = field.RegisterNo;
int start = field.Start;
int length = field.Length;
ModbusDataType type = field.Type;
double scale = field.Scale;
int round = field.Round;
double offset = field.Offset;
start = (registerNo - startRegisterNo) * 16 + start;
length = type switch
{
ModbusDataType.Byte => length * 8,
ModbusDataType.Register => length * 16,
_ => length
};
Type valueType = typeof(T);
object value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset);
field.Value = (T)value;
}
}