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.

140 lines
5.4 KiB

using HslCommunication.Core;
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();
return Decode<T>(bytes, t);
}
public static T Decode<T>(byte[] bytes, T t) where T : class, new()
{
var fields = t.GetType().GetProperties()
.Where(it => it.PropertyType.GetGenericTypeDefinition() == typeof(ModbusProperty<>))
.Select(p => p.GetValue(t)).ToList();
//startRegisterNo 获得整个对象的起始寄存器数值
var startRegisterNo = int.MaxValue;
foreach (var field in fields)
if (field != null)
{
var p = (IModbusProperty)field;
if (startRegisterNo > p.GetRegisterNo()) startRegisterNo = p.GetRegisterNo();
}
var decodeUseBytes = new byte[bytes.Length];
switch (ModbusTcpMaster.DataFormat)
{
case DataFormat.ABCD:
for (var i = 0; i < bytes.Length; i++)
if (i % 2 == 0)
decodeUseBytes[i + 1] = bytes[i];
else
decodeUseBytes[i - 1] = bytes[i];
break;
case DataFormat.BADC:
decodeUseBytes = bytes;
break;
}
foreach (var field in fields)
switch (field)
{
case ModbusProperty<bool> boolProperty:
{
SetPropertyValue(startRegisterNo, boolProperty, decodeUseBytes);
//SetPropertyValue(boolProperty.RegisterNo, boolProperty, decodeUseBytes);
break;
}
case ModbusProperty<byte> byteProperty:
{
SetPropertyValue(startRegisterNo, byteProperty, decodeUseBytes);
//SetPropertyValue(byteProperty.RegisterNo, byteProperty, decodeUseBytes);
break;
}
case ModbusProperty<sbyte> sbyteProperty:
{
//SetPropertyValue(sbyteProperty.RegisterNo, sbyteProperty, decodeUseBytes);
SetPropertyValue(startRegisterNo, sbyteProperty, decodeUseBytes);
break;
}
case ModbusProperty<short> shortProperty:
{
SetPropertyValue(startRegisterNo, shortProperty, decodeUseBytes);
//SetPropertyValue(shortProperty.RegisterNo, shortProperty, decodeUseBytes);
break;
}
case ModbusProperty<ushort> ushortProperty:
{
SetPropertyValue(startRegisterNo, ushortProperty, decodeUseBytes);
// SetPropertyValue(ushortProperty.RegisterNo, ushortProperty, decodeUseBytes);
break;
}
case ModbusProperty<int> intProperty:
{
SetPropertyValue(startRegisterNo, intProperty, decodeUseBytes);
// SetPropertyValue(intProperty.RegisterNo, intProperty, decodeUseBytes);
break;
}
case ModbusProperty<uint> uintProperty:
{
SetPropertyValue(startRegisterNo, uintProperty, decodeUseBytes);
// SetPropertyValue(uintProperty.RegisterNo, uintProperty, decodeUseBytes);
break;
}
case ModbusProperty<float> floatProperty:
{
SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes, true);
// SetPropertyValue(floatProperty.RegisterNo, floatProperty, decodeUseBytes);
break;
}
case ModbusProperty<double> doubleProperty:
{
SetPropertyValue(startRegisterNo, doubleProperty, decodeUseBytes);
// SetPropertyValue(doubleProperty.RegisterNo, doubleProperty, decodeUseBytes);
break;
}
case ModbusProperty<string> stringProperty:
{
SetPropertyValue(startRegisterNo, stringProperty, decodeUseBytes);
// SetPropertyValue(stringProperty.RegisterNo, stringProperty, decodeUseBytes);
break;
}
}
return t;
}
private static void SetPropertyValue<T>(int startRegisterNo, ModbusProperty<T> field, byte[] bytes, bool unSign = true)
{
var registerNo = field.RegisterNo;
var start = field.Start;
var length = field.Length;
var type = field.Type;
var scale = field.Scale;
var round = field.Round;
var offset = field.Offset;
start = (registerNo - startRegisterNo) * 16 + start;
var valueType = typeof(T);
if (typeof(T) == typeof(byte))
length = length * 8;
else
length = type switch
{
ModbusDataType.Register => length * 16,
_ => length
};
var value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset, unSign);
field.Value = (T)value;
}
}