本文已收錄至:開源 DotNetty 實現的 Modbus TCP/IP 協議
Modbus TCP/IP 報文
- 報文最大長度為 260 byte (ADU = 7 byte MBAP Header + 253 byte PDU)
- Length = Unit Identifier 長度 + PDU 長度
MBAP Header
PDU
PDU 由兩部分構成:Function Code(功能碼) 和 Data 組成
Function Code
部分功能碼:
報文類
ModbusHeader
public class ModbusHeader
{
public ushort TransactionIdentifier { get; set; }
public ushort ProtocolIdentifier { get; set; }
public ushort Length { get; set; }
public short UnitIdentifier { get; set; }
public ModbusHeader(IByteBuffer buffer)
{
TransactionIdentifier = buffer.ReadUnsignedShort();
ProtocolIdentifier = buffer.ReadUnsignedShort();
Length = buffer.ReadUnsignedShort();
UnitIdentifier = buffer.ReadByte();
}
public ModbusHeader(ushort transactionIdentifier, short unitIdentifier)
: this(transactionIdentifier, 0x0000, unitIdentifier) // for modbus protocol: Protocol Identifier = 0x00
{
}
private ModbusHeader(ushort transactionIdentifier, ushort protocolIdentifier, short unitIdentifier)
{
TransactionIdentifier = transactionIdentifier;
ProtocolIdentifier = protocolIdentifier;
UnitIdentifier = unitIdentifier;
}
public IByteBuffer Encode()
{
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteUnsignedShort(TransactionIdentifier);
buffer.WriteUnsignedShort(ProtocolIdentifier);
buffer.WriteUnsignedShort(Length);
buffer.WriteByte(UnitIdentifier);
return buffer;
}
}
ModbusHeader 對應 MBAP Header,包含兩個構造函數:第一個構造函數用於從緩沖區解析消息頭,第二個構造函數用來請求/響應時手動構造消息頭。Encode 方法用於在傳輸前對消息頭進行編碼。
ModbusFunction
public abstract class ModbusFunction
{
protected short FunctionCode { get; }
protected ModbusFunction(short functionCode)
{
FunctionCode = functionCode;
}
/// <summary>
/// PDU length -1 (not include function code length)
/// </summary>
/// <returns></returns>
public abstract int CalculateLength();
public abstract void Decode(IByteBuffer buffer);
public abstract IByteBuffer Encode();
}
ModbusFunction 對應 PDU,該類為抽象類,所有的請求/相應的 PDU 均繼承自該類。實際使用中根據 FunctionCode 實例化具體的子類對象。其中 CalculateLength 方法用來計算 Data 部分的長度,Decode 方法用於從緩沖區解析 Data,Encode 方法用於在傳輸前對 Data 編碼。
ModbusFrame
public class ModbusFrame
{
public ModbusHeader Header { get; set; }
public ModbusFunction Function { get; set; }
public ModbusFrame(ModbusHeader header, ModbusFunction function)
{
Header = header;
Function = function;
}
public IByteBuffer Encode()
{
Header.Length = (ushort)(1 + 1 + Function.CalculateLength());// Unit Identifier + Function Code + data length
IByteBuffer buffer = Unpooled.Buffer();
buffer.WriteBytes(Header.Encode());
buffer.WriteBytes(Function.Encode());
return buffer;
}
}
ModbusFrame 對應 ADU。Encode 方法用於在傳輸前對 ADU 編碼。
開源地址:modbus-tcp