Add a sample self defined modbus function library (not complete)
This commit is contained in:
@@ -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"}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user