mudbus读写plc测试更改

master
lch 7 months ago
parent 821b8aac53
commit 5410bbe20b

@ -1,6 +1,8 @@
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.IO.Pipes;
using HslCommunication.Core;
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkCore.Utils;
using HybirdFrameworkDriver.ModbusTcpMaster;
@ -12,6 +14,8 @@ internal class Program
ModbusTcpMaster master = new ModbusTcpMaster()
{
Ip = "192.168.1.5",
//默认DataFormat.ABCD
//DataFormat = DataFormat.ABCD,
ReadAction = ReadFunc
};
@ -30,19 +34,27 @@ internal class Program
bool writeResult1 = master.WriteValue(coolData.Status);
Debug.Assert(writeResult1, "写入失败");
//写入bit
coolData.DraughtFan2.Value = true;
bool writeResult3 = master.WriteValue(coolData.DraughtFan2);
coolData.DraughtFan1.Value = true;
bool writeResult3 = master.WriteValue(coolData.DraughtFan1);
Debug.Assert(writeResult3, "写入失败");
coolData.Temperature1.Value = 12.7f;
bool writeResult5 = master.WriteValue(coolData.Temperature1);
Debug.Assert(writeResult5, "写入失败");
#endregion 测试写
}
private static WaterCoolData coolData = new WaterCoolData();
private static void ReadFunc(ModbusTcpMaster master)
{
byte[]? bytes = master.BatchRead(0, 46);
byte[]? bytes = master.BatchRead(1, 46);
if (bytes != null)
{
WaterCoolData coolData = ModbusDecoder.Decode<WaterCoolData>(bytes);
float temperature1Value = coolData.Temperature1.Value;
ModbusDecoder.Decode<WaterCoolData>(bytes, coolData);
Debug.WriteLine("12.7f" + coolData.Temperature1.Value);
Debug.WriteLine("12" + coolData.Status.Value);
Debug.WriteLine("fasle" + coolData.CompressorState1.Value);
Debug.WriteLine("18" + coolData.ushortType.Value);
}
}

@ -196,9 +196,20 @@ public static class BitUtls
#endregion
#region Decode Value
public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length, double scale, int round,
double offset)
/// <summary>
///
/// </summary>
/// <param name="bytes">原始字节数组</param>
/// <param name="propertyType">字段类型bool byte等</param>
/// <param name="start">当前字段第一个bit所处开始位置</param>
/// <param name="length">bit的数量</param>
/// <param name="scale">精度</param>
/// <param name="round">保留几位小数</param>
/// <param name="offset">位偏移</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static object Bytes2Value(byte[] bytes, Type propertyType, int start, int length,
double scale, int round,double offset)
{
if (propertyType == BOOLEAN)
{

@ -1,4 +1,6 @@
using HybirdFrameworkCore.Utils;
using HslCommunication.Core;
using HslCommunication.Secs.Types;
using HybirdFrameworkCore.Utils;
using log4net;
namespace HybirdFrameworkDriver.ModbusTcpMaster;
@ -7,13 +9,12 @@ public static class ModbusDecoder
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusDecoder));
public static T Decode<T>(byte[] bytes) where T : class, new()
public static T Decode<T>(byte[] bytes, T t) 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();
//startRegisterNo 获得整个对象的起始寄存器数值
int startRegisterNo = Int32.MaxValue;
foreach (object? field in fields)
{
@ -26,29 +27,95 @@ public static class ModbusDecoder
}
}
}
byte[] decodeUseBytes = new byte[bytes.Length];
switch (ModbusTcpMaster.DataFormat)
{
case DataFormat.ABCD:
for (int 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 (object? field in fields)
{
switch (field)
{
case ModbusProperty<byte> property:
{
SetPropertyValue(startRegisterNo, property, bytes);
break;
}
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, bytes);
break;
}
{
SetPropertyValue(startRegisterNo, floatProperty, decodeUseBytes);
// 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)
{
int registerNo = field.RegisterNo;
int start = field.Start;
int length = field.Length;
@ -59,15 +126,17 @@ public static class ModbusDecoder
start = (registerNo - startRegisterNo) * 16 + start;
length = type switch
{
ModbusDataType.Byte => length * 8,
ModbusDataType.Register => length * 16,
_ => length
};
Type valueType = typeof(T);
if (typeof(T) == typeof(byte))
length = length * 8;
else
{
length = type switch
{
ModbusDataType.Register => length * 16,
_ => length
};
}
object value = BitUtls.Bytes2Value(bytes, valueType, start, length, scale, round, offset);
field.Value = (T)value;
}

@ -26,10 +26,18 @@ public class ModbusProperty<T> : IModbusProperty
public int Round { get; set; }
public double Offset { get; set; }
public T Value { get; set; }
/// <summary>
///
/// </summary>
/// <param name="registerNo">寄存器编号</param>
/// <param name="start">根据类型Register为第几个寄存器</param>
/// <param name="length">根据类型Register 为 几个寄存器</param>
/// <param name="type">Register/Bit</param>
/// <param name="scale">精度</param>
/// <param name="round">保留几位小数</param>
/// <param name="offset">偏移量</param>
public ModbusProperty(int registerNo, int start = 0, int length = 1, ModbusDataType type = ModbusDataType.Register,
double scale = 1,
int round = 0, double offset = 0)
double scale = 1,int round = 0, double offset = 0)
{
this.RegisterNo = registerNo;
this.Start = start;
@ -50,6 +58,5 @@ public class ModbusProperty<T> : IModbusProperty
public enum ModbusDataType
{
Bit,
Byte,
Register
}

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using HslCommunication;
using HslCommunication.Core;
using HslCommunication.ModBus;
@ -15,7 +16,7 @@ public class ModbusTcpMaster
public string Ip { get; set; } = "192.168.1.5";
public int Port { get; set; } = 502;
public DataFormat DataFormat { get; set; } = DataFormat.ABCD;
public static DataFormat DataFormat { get; set; } = DataFormat.ABCD;
public int Duration { get; set; } = 1000;
public bool Connected { get; set; } = false;
@ -91,7 +92,7 @@ public class ModbusTcpMaster
{
try
{
ReadAction(this);
ReadAction(this);
Thread.Sleep(Duration);
}
catch (Exception e)
@ -137,7 +138,6 @@ public class ModbusTcpMaster
GetLog().Warn($"write property{property.RegisterNo} null value");
return false;
}
bool result = false;
ModbusDataType dataType = property.Type;
int start = property.Start;
@ -148,42 +148,119 @@ public class ModbusTcpMaster
switch (dataType)
{
case ModbusDataType.Byte:
start = start % 2 == 0 ? start / 2 : start / 2 + 1;
operateResult = ModbusTcpNet.Write("x=6;" + (registerNo + start), setValue);
result = operateResult.IsSuccess;
break;
case ModbusDataType.Register:
operateResult = ModbusTcpNet.Write("x=16;" + (registerNo + start), setValue);
result = operateResult.IsSuccess;
break;
case ModbusDataType.Bit:
start = start % 16 == 0 ? start / 16 : start / 16 + 1;
length = length % 8 == 0 ? length / 8 : length / 8 + 1;
OperateResult<byte[]> readResult =
ModbusTcpNet.Read("x=3;" + (registerNo + start), (ushort)length);
if (readResult.IsSuccess)
if (setValue.Length < length * 2)
{
byte[] bytes = readResult.Content;
BitArray bitArray = new BitArray(bytes);
int index = 0;
for (int i = property.Start % 16; i < property.Length; i++)
//byte 需要读取寄存器中的内容
if (typeof(T) == typeof(byte))
{
OperateResult<byte[]> readResultRegister = ModbusTcpNet.Read("x=3;" + (registerNo), 1);
if (readResultRegister.IsSuccess)
{
switch (DataFormat)
{
case DataFormat.ABCD:
readResultRegister.Content[1] = setValue[0];
break;
case DataFormat.BADC:
readResultRegister.Content[0] = setValue[0];
break;
}
operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), readResultRegister.Content);
result = operateResult.IsSuccess;
}
}
//其他类型 String 占用几个寄存器 直接补0
else
{
bitArray[i] = (setValue[index / 8] & (1 << (index % 8))) > 0;
index++;
byte[] preWriteCont = new byte[length * 2];
switch (DataFormat)
{
case DataFormat.ABCD:
for (int i = 0; i < setValue.Length; i++)
{
if (i % 2 == 0)
preWriteCont[i + 1] = setValue[i];
else
preWriteCont[i - 1] = setValue[i];
}
break;
case DataFormat.BADC:
Array.Copy(setValue, preWriteCont, setValue.Length);
break;
}
operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont);
result = operateResult.IsSuccess;
}
bitArray.CopyTo(bytes, 0);
}
else if (setValue.Length == length * 2)
{
byte[] preWriteCont = new byte[setValue.Length];
operateResult = ModbusTcpNet.Write("x=6;" + (registerNo + start), bytes);
switch (DataFormat)
{
case DataFormat.ABCD:
for (int i = 0; i < setValue.Length; i++)
{
if (i % 2 == 0)
preWriteCont[i + 1] = setValue[i];
else
preWriteCont[i - 1] = setValue[i];
}
break;
case DataFormat.BADC:
//Array.Copy(setValue, preWriteCont, setValue.Length);
break;
}
operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont);
result = operateResult.IsSuccess;
}
break;
case ModbusDataType.Bit:
result = WriteRegisterOneBit(registerNo, start, Convert.ToBoolean(value));
break;
}
return result;
}
/// <summary>
/// 写寄存器中的一个bit
/// </summary>
/// <param name="addr"></param>
/// <param name="location"></param>
/// <param name="boolResult"></param>
/// <returns></returns>
public bool WriteRegisterOneBit(int addr, int location, bool boolResult)
{
if (!Connected) return false;
bool result = false;
ushort registerValue1 = 0x1234;
ushort mask = 0x1234;
OperateResult<byte[]> readResult = ModbusTcpNet.Read("x=3;" + addr.ToString(), 1);
if (readResult.IsSuccess)
{
if (location >= 0 && location <= 15)
{
registerValue1 = ModbusTcpNet.ByteTransform.TransUInt16(readResult.Content, 0);
if (boolResult)
{
mask = (ushort)(1 << location);
registerValue1 |= mask;
}
else
{
mask = (ushort)(~(1 << location));
registerValue1 &= mask;
}
OperateResult writeResult = ModbusTcpNet.Write("x=6;" + addr, registerValue1);
if (writeResult.IsSuccess)
{
result = true;
}
}
}
return result;
}
}

@ -17,17 +17,17 @@ public class WaterCoolData
public ModbusProperty<bool> CompressorState4 { get; set; } = new(40003, 10, type: ModbusDataType.Bit);
public ModbusProperty<bool> ChargePump { get; set; } = new(40003, 11, type: ModbusDataType.Bit);
public ModbusProperty<float> Temperature1 { get; set; } = new(40004, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature2 { get; set; } = new(40005, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature3 { get; set; } = new(40006, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature4 { get; set; } = new(40007, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature5 { get; set; } = new(40008, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature6 { get; set; } = new(40009, scale: 0.1, round: 1);
public ModbusProperty<float> WaterDischarge { get; set; } = new(40010, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature1 { get; set; } = new(40011, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature2 { get; set; } = new(40012, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature3 { get; set; } = new(40013, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature4 { get; set; } = new(40014, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature1 { get; set; } = new(40004, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature2 { get; set; } = new(40005, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature3 { get; set; } = new(40006, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature4 { get; set; } = new(40007, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature5 { get; set; } = new(40008, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature6 { get; set; } = new(40009, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> WaterDischarge { get; set; } = new(40010, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature1 { get; set; } = new(40011, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature2 { get; set; } = new(40012, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature3 { get; set; } = new(40013, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> CompressorTemperature4 { get; set; } = new(40014, length: 2, scale: 0.1, round: 1);
public ModbusProperty<ushort> ushortType { get; set; } = new(40015);

Loading…
Cancel
Save