本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议

Modbus TCP/IP 报文

DotNetty 实现 Modbus TCP 系列 (一) 报文类-LMLPHP

  • 报文最大长度为 260 byte (ADU = 7 byte MBAP Header + 253 byte PDU)
  • Length = Unit Identifier 长度 + PDU 长度

MBAP Header

DotNetty 实现 Modbus TCP 系列 (一) 报文类-LMLPHP

PDU

PDU 由两部分构成:Function Code(功能码) 和 Data 组成

Function Code

部分功能码:

DotNetty 实现 Modbus TCP 系列 (一) 报文类-LMLPHP

报文类

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

02-13 21:22