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

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

@ -26,10 +26,18 @@ public class ModbusProperty<T> : IModbusProperty
public int Round { get; set; } public int Round { get; set; }
public double Offset { get; set; } public double Offset { get; set; }
public T Value { 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, public ModbusProperty(int registerNo, int start = 0, int length = 1, ModbusDataType type = ModbusDataType.Register,
double scale = 1, double scale = 1,int round = 0, double offset = 0)
int round = 0, double offset = 0)
{ {
this.RegisterNo = registerNo; this.RegisterNo = registerNo;
this.Start = start; this.Start = start;
@ -50,6 +58,5 @@ public class ModbusProperty<T> : IModbusProperty
public enum ModbusDataType public enum ModbusDataType
{ {
Bit, Bit,
Byte,
Register Register
} }

@ -1,4 +1,5 @@
using System.Collections; using System;
using System.Collections;
using HslCommunication; using HslCommunication;
using HslCommunication.Core; using HslCommunication.Core;
using HslCommunication.ModBus; using HslCommunication.ModBus;
@ -15,7 +16,7 @@ public class ModbusTcpMaster
public string Ip { get; set; } = "192.168.1.5"; public string Ip { get; set; } = "192.168.1.5";
public int Port { get; set; } = 502; 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 int Duration { get; set; } = 1000;
public bool Connected { get; set; } = false; public bool Connected { get; set; } = false;
@ -137,7 +138,6 @@ public class ModbusTcpMaster
GetLog().Warn($"write property{property.RegisterNo} null value"); GetLog().Warn($"write property{property.RegisterNo} null value");
return false; return false;
} }
bool result = false; bool result = false;
ModbusDataType dataType = property.Type; ModbusDataType dataType = property.Type;
int start = property.Start; int start = property.Start;
@ -148,42 +148,119 @@ public class ModbusTcpMaster
switch (dataType) 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: case ModbusDataType.Register:
operateResult = ModbusTcpNet.Write("x=16;" + (registerNo + start), setValue); if (setValue.Length < length * 2)
result = operateResult.IsSuccess; {
//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; break;
case ModbusDataType.Bit: case DataFormat.BADC:
start = start % 16 == 0 ? start / 16 : start / 16 + 1; readResultRegister.Content[0] = setValue[0];
length = length % 8 == 0 ? length / 8 : length / 8 + 1; break;
OperateResult<byte[]> readResult = }
ModbusTcpNet.Read("x=3;" + (registerNo + start), (ushort)length); operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), readResultRegister.Content);
result = operateResult.IsSuccess;
}
}
//其他类型 String 占用几个寄存器 直接补0
else
{
byte[] preWriteCont = new byte[length * 2];
if (readResult.IsSuccess) switch (DataFormat)
{ {
byte[] bytes = readResult.Content; case DataFormat.ABCD:
BitArray bitArray = new BitArray(bytes); for (int i = 0; i < setValue.Length; i++)
int index = 0;
for (int i = property.Start % 16; i < property.Length; i++)
{ {
bitArray[i] = (setValue[index / 8] & (1 << (index % 8))) > 0; if (i % 2 == 0)
index++; 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; result = operateResult.IsSuccess;
} }
break;
case ModbusDataType.Bit:
result = WriteRegisterOneBit(registerNo, start, Convert.ToBoolean(value));
break; break;
} }
return result; 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> CompressorState4 { get; set; } = new(40003, 10, type: ModbusDataType.Bit);
public ModbusProperty<bool> ChargePump { get; set; } = new(40003, 11, 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> Temperature1 { get; set; } = new(40004, length: 2, scale: 0.1, round: 1);
public ModbusProperty<float> Temperature2 { get; set; } = new(40005, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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); public ModbusProperty<ushort> ushortType { get; set; } = new(40015);

Loading…
Cancel
Save