Add a sample self defined modbus function library (not complete)

This commit is contained in:
luosheng
2023-03-28 16:07:24 +08:00
parent 7da1b7ea2a
commit c20809c3fb
13 changed files with 638 additions and 484 deletions

View File

@@ -4,42 +4,10 @@ using System.Threading.Tasks;
namespace Modbus.Net.Modbus
{
/// <summary>
/// 变量功能码
/// </summary>
internal enum ModbusProtocolVariableFunctionCode : byte
{
/// <summary>
/// 读变量
/// </summary>
ReadVariable = 20,
/// <summary>
/// 写变量
/// </summary>
WriteVariable = 21
}
/// <summary>
/// 跟时间有关的功能码
/// </summary>
public enum ModbusProtocolTimeFunctionCode : byte
{
/// <summary>
/// 读时间
/// </summary>
GetSystemTime = 3,
/// <summary>
/// 写时间
/// </summary>
SetSystemTime = 16
}
/// <summary>
/// 跟读数据有关的功能码
/// </summary>
public enum ModbusProtocolReadDataFunctionCode : byte
public enum ModbusProtocolFunctionCode : byte
{
/// <summary>
/// 读线圈
@@ -59,14 +27,8 @@ namespace Modbus.Net.Modbus
/// <summary>
/// 读输入寄存器
/// </summary>
ReadInputRegister = 4
}
/// <summary>
/// 跟写数据有关的功能码
/// </summary>
public enum ModbusProtocolWriteDataFunctionCode : byte
{
ReadInputRegister = 4,
/// <summary>
/// 写单个线圈
/// </summary>
@@ -85,7 +47,80 @@ namespace Modbus.Net.Modbus
/// <summary>
/// 写多个寄存器
/// </summary>
WriteMultiRegister = 16
WriteMultiRegister = 16,
/// <summary>
/// 读文件记录
/// </summary>
ReadFileRecord = 20,
/// <summary>
/// 写文件记录
/// </summary>
WriteFileRecord = 21,
/// <summary>
/// 写寄存器掩码
/// </summary>
MaskWriteRegister = 22,
/// <summary>
/// 读写多个寄存器
/// </summary>
ReadWriteMultipleRegister = 23,
/// <summary>
/// 读队列
/// </summary>
ReadFIFOQueue = 24,
}
/// <summary>
/// Modbus MEI方式
/// </summary>
public enum ModbusMEIProtocolFunctionCode : ushort
{
/// <summary>
///
/// </summary>
CANopenGeneralReferenceRequestandResponsePDU = 0x2B0D,
/// <summary>
/// 读设备信息
/// </summary>
ReadDeviceIdentification = 0x2B0E
}
/// <summary>
/// 只能在串口通信中使用的Modbus方法
/// 不能在TCP和UDP通信中使用
/// </summary>
public enum ModbusSerialPortOnlyFunctionCode : byte
{
/// <summary>
/// 读错误状态
/// </summary>
ReadExceptionStatus = 7,
/// <summary>
/// 诊断
/// </summary>
Diagnostics = 8,
/// <summary>
/// 读通讯事件计数器
/// </summary>
GetCommEventCounter = 11,
/// <summary>
/// 读日志
/// </summary>
GetCommEventLog = 12,
/// <summary>
/// 读从站ID
/// </summary>
ReportSlaveID = 17
}
/// <summary>
@@ -378,7 +413,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// 写数据输入
/// </summary>
public class WriteSingleDataModbusInputStruct : IInputStruct
public class WriteSingleCoilModbusInputStruct : IInputStruct
{
/// <summary>
/// 构造函数
@@ -388,7 +423,7 @@ namespace Modbus.Net.Modbus
/// <param name="writeValue">写入的数据</param>
/// <param name="addressTranslator">地址翻译器</param>
/// <param name="endian">端格式</param>
public WriteSingleDataModbusInputStruct(byte slaveAddress, string startAddress, object writeValue,
public WriteSingleCoilModbusInputStruct(byte slaveAddress, string startAddress, object writeValue,
ModbusTranslatorBase addressTranslator, Endian endian)
{
SlaveAddress = slaveAddress;
@@ -396,7 +431,7 @@ namespace Modbus.Net.Modbus
FunctionCode = (byte)translateAddress.Area;
StartAddress = (ushort)translateAddress.Address;
var writeByteValue =
FunctionCode == (byte)ModbusProtocolWriteDataFunctionCode.WriteSingleCoil
FunctionCode == (byte)ModbusProtocolFunctionCode.WriteSingleCoil
? ((bool)writeValue
? new byte[] { 0xFF, 0x00 }
: new byte[] { 0x00, 0x00 })
@@ -429,7 +464,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// 写数据输出
/// </summary>
public class WriteSingleDataModbusOutputStruct : IOutputStruct
public class WriteSingleCoilModbusOutputStruct : IOutputStruct
{
/// <summary>
/// 构造函数
@@ -438,7 +473,7 @@ namespace Modbus.Net.Modbus
/// <param name="functionCode">功能码</param>
/// <param name="startAddress">开始地址</param>
/// <param name="writeValue">写入的数据</param>
public WriteSingleDataModbusOutputStruct(byte slaveAddress, byte functionCode,
public WriteSingleCoilModbusOutputStruct(byte slaveAddress, byte functionCode,
ushort startAddress, object writeValue)
{
SlaveAddress = slaveAddress;
@@ -471,7 +506,7 @@ namespace Modbus.Net.Modbus
/// <summary>
/// 写多个寄存器协议
/// </summary>
public class WriteSingleDataModbusProtocol : ProtocolUnit
public class WriteSingleCoilModbusProtocol : ProtocolUnit
{
/// <summary>
/// 格式化
@@ -480,7 +515,7 @@ namespace Modbus.Net.Modbus
/// <returns>写寄存器协议核心</returns>
public override byte[] Format(IInputStruct message)
{
var r_message = (WriteSingleDataModbusInputStruct)message;
var r_message = (WriteSingleCoilModbusInputStruct)message;
var dataValue = Format(r_message.WriteValue);
var formattingBytes = Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, dataValue);
@@ -499,314 +534,15 @@ namespace Modbus.Net.Modbus
var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var startAddress = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var writeValue = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var returnValue = functionCode == (byte)ModbusProtocolWriteDataFunctionCode.WriteSingleCoil
var returnValue = functionCode == (byte)ModbusProtocolFunctionCode.WriteSingleCoil
? (object)(writeValue == 0xFF00) : writeValue;
return new WriteSingleDataModbusOutputStruct(slaveAddress, functionCode, startAddress,
return new WriteSingleCoilModbusOutputStruct(slaveAddress, functionCode, startAddress,
returnValue);
}
}
#endregion
#region PLC时间
/// <summary>
/// 读时间输入
/// </summary>
public class GetSystemTimeModbusInputStruct : IInputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
public GetSystemTimeModbusInputStruct(byte slaveAddress)
{
SlaveAddress = slaveAddress;
FunctionCode = (byte)ModbusProtocolTimeFunctionCode.GetSystemTime;
StartAddress = 30000;
GetCount = 5;
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; }
/// <summary>
/// 获取个数
/// </summary>
public ushort GetCount { get; }
}
/// <summary>
/// 读时间输出
/// </summary>
public class GetSystemTimeModbusOutputStruct : IOutputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="writeByteCount">写入个数</param>
/// <param name="year">年</param>
/// <param name="day">日</param>
/// <param name="month">月</param>
/// <param name="hour">时</param>
/// <param name="second">秒</param>
/// <param name="minute">分</param>
/// <param name="millisecond">毫秒</param>
public GetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
byte writeByteCount, ushort year, byte day, byte month, ushort hour, byte second, byte minute,
ushort millisecond)
{
SlaveAddress = slaveAddress;
FunctionCode = functionCode;
WriteByteCount = writeByteCount;
Time = new DateTime(year, month, day, hour, minute, second, millisecond);
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; }
/// <summary>
/// 写入个数
/// </summary>
public byte WriteByteCount { get; private set; }
/// <summary>
/// 时间
/// </summary>
public DateTime Time { get; private set; }
}
/// <summary>
/// 读系统时间协议
/// </summary>
public class GetSystemTimeModbusProtocol : ProtocolUnit
{
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写系统时间参数</param>
/// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message)
{
var r_message = (GetSystemTimeModbusInputStruct)message;
return Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.GetCount);
}
/// <summary>
/// 反格式化
/// </summary>
/// <param name="messageBytes">获取的信息</param>
/// <param name="flag">当前反格式化的位置</param>
/// <returns>反格式化的信息</returns>
public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var writeByteCount = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var year = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var day = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var month = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var hour = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var second = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var minute = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var millisecond = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
return new GetSystemTimeModbusOutputStruct(slaveAddress, functionCode, writeByteCount, year, day,
month, hour, second, minute, millisecond);
}
}
#endregion
#region PLC时间
/// <summary>
/// 写时间输入
/// </summary>
public class SetSystemTimeModbusInputStruct : IInputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="time">时间</param>
public SetSystemTimeModbusInputStruct(byte slaveAddress, DateTime time)
{
SlaveAddress = slaveAddress;
FunctionCode = (byte)ModbusProtocolTimeFunctionCode.SetSystemTime;
StartAddress = 30000;
WriteCount = 5;
WriteByteCount = 10;
Year = (ushort)time.Year;
Day = (byte)time.Day;
Month = (byte)time.Month;
Hour = (ushort)time.Hour;
Second = (byte)time.Second;
Minute = (byte)time.Minute;
Millisecond = (ushort)time.Millisecond;
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; }
/// <summary>
/// 写入字节个数
/// </summary>
public byte WriteByteCount { get; }
/// <summary>
/// 年
/// </summary>
public ushort Year { get; }
/// <summary>
/// 日
/// </summary>
public byte Day { get; }
/// <summary>
/// 月
/// </summary>
public byte Month { get; }
/// <summary>
/// 时
/// </summary>
public ushort Hour { get; }
/// <summary>
/// 秒
/// </summary>
public byte Second { get; }
/// <summary>
/// 分
/// </summary>
public byte Minute { get; }
/// <summary>
/// 毫秒
/// </summary>
public ushort Millisecond { get; }
}
/// <summary>
/// 写时间输出
/// </summary>
public class SetSystemTimeModbusOutputStruct : IOutputStruct
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="slaveAddress">从站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="startAddress">开始地址</param>
/// <param name="writeCount">写入个数</param>
public SetSystemTimeModbusOutputStruct(byte slaveAddress, byte functionCode,
ushort startAddress, ushort writeCount)
{
SlaveAddress = slaveAddress;
FunctionCode = functionCode;
StartAddress = startAddress;
WriteCount = writeCount;
}
/// <summary>
/// 从站号
/// </summary>
public byte SlaveAddress { get; private set; }
/// <summary>
/// 功能码
/// </summary>
public byte FunctionCode { get; private set; }
/// <summary>
/// 开始地址
/// </summary>
public ushort StartAddress { get; private set; }
/// <summary>
/// 写入个数
/// </summary>
public ushort WriteCount { get; private set; }
}
/// <summary>
/// 写系统时间协议
/// </summary>
public class SetSystemTimeModbusProtocol : ProtocolUnit
{
/// <summary>
/// 格式化
/// </summary>
/// <param name="message">写系统时间的参数</param>
/// <returns>写系统时间的核心</returns>
public override byte[] Format(IInputStruct message)
{
var r_message = (SetSystemTimeModbusInputStruct)message;
return Format(r_message.SlaveAddress, r_message.FunctionCode,
r_message.StartAddress, r_message.WriteCount, r_message.WriteByteCount, r_message.Year,
r_message.Day,
r_message.Month, r_message.Hour, r_message.Second, r_message.Minute, r_message.Millisecond);
}
/// <summary>
/// 反格式化
/// </summary>
/// <param name="messageBytes">获取的信息</param>
/// <param name="flag">当前反格式化的位置</param>
/// <returns>反格式化的信息</returns>
public override IOutputStruct Unformat(byte[] messageBytes, ref int flag)
{
var slaveAddress = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var functionCode = ValueHelper.GetInstance(Endian).GetByte(messageBytes, ref flag);
var startAddress = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
var writeCount = ValueHelper.GetInstance(Endian).GetUShort(messageBytes, ref flag);
return new SetSystemTimeModbusOutputStruct(slaveAddress, functionCode, startAddress, writeCount);
}
}
#endregion
/// <summary>
/// Modbus协议错误表
/// </summary>
@@ -820,6 +556,9 @@ namespace Modbus.Net.Modbus
{4, "SLAVE_DEVICE_FAILURE"},
{5, "ACKNOWLWDGE"},
{6, "SLAVE_DEVICE_BUSY"},
{8, "MEMORY_PARITY_ERROR" },
{10, "GATEWAY_PATH_UNAVAILABLE"},
{11, "GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND"},
{500, "TCP_ILLEGAL_LENGTH"},
{501, "RTU_ILLEGAL_CRC"}
};