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(byte[] bytes) where T : class, new() { T t = new T(); List 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) { if (field != null) { IModbusProperty p = (IModbusProperty)field; if (startRegisterNo > p.GetRegisterNo()) { startRegisterNo = p.GetRegisterNo(); } } } foreach (object field in fields) { switch (field) { case ModbusProperty property: { SetPropertyValue(startRegisterNo, property, bytes); break; } case ModbusProperty floatProperty: { SetPropertyValue(startRegisterNo, floatProperty, bytes); break; } } } return t; } private static void SetPropertyValue(int startRegisterNo, ModbusProperty 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; } }