DotNetty 實現 Modbus TCP 系列 (二) ModbusFunction 類圖及繼承舉例
阿新 • • 發佈:2019-02-13
說明 multiple var input ole ons orb .com 根據
本文已收錄至:開源 DotNetty 實現的 Modbus TCP/IP 協議
ModbusFunction 類圖如下:
如前文所述,所有請求/相應的 PDU 均繼承自 ModbusFunction,其子類傳入對應的 Function Code 並實現三個方法:
- CalculateLength:Data 部分的長度(該方法也可以為屬性,但屬性沒有強制性,怕漏掉故改為抽象方法)
- Decode:從緩沖區解析 Data
- Encode:在傳輸前對 Data 編碼
實現舉例
每個 Function Code 均對應 ModbusFunction 的兩個子類:請求類和響應類,以 0x03(讀取保持寄存器值)為例:
請求類
請求報文 Data 說明:
public class ReadHoldingRegistersRequest : ModbusFunction { public ushort StartingAddress { get; private set; } public ushort Quantity { get; private set; } public ReadHoldingRegistersRequest() : base((short)ModbusCommand.ReadHoldingRegisters) { } public ReadHoldingRegistersRequest(ushort startingAddress, ushort quantity) : base((short)ModbusCommand.ReadHoldingRegisters) { StartingAddress = startingAddress; Quantity = quantity; } public override int CalculateLength() { return 2 + 2; // StartingAddress Length + Quantity Length } public override void Decode(IByteBuffer buffer) { StartingAddress = buffer.ReadUnsignedShort(); Quantity = buffer.ReadUnsignedShort(); } public override IByteBuffer Encode() { IByteBuffer buffer = Unpooled.Buffer(); buffer.WriteByte(FunctionCode); buffer.WriteUnsignedShort(StartingAddress); buffer.WriteUnsignedShort(Quantity); return buffer; } }
響應類
響應報文 Data 說明:
public class ReadHoldingRegistersResponse : ModbusFunction { private ushort byteCount; public ushort[] Registers { get; private set; } public ReadHoldingRegistersResponse() : base((short)ModbusCommand.ReadHoldingRegisters) { } public ReadHoldingRegistersResponse(ushort[] registers) : base((short)ModbusCommand.ReadHoldingRegisters) { Registers = registers; byteCount = (ushort)(registers.Length * 2); } public override int CalculateLength() { return 1 + byteCount; } public override void Decode(IByteBuffer buffer) { byteCount = buffer.ReadByte(); Registers = new ushort[byteCount / 2]; for (int i = 0; i < Registers.Length; i++) { Registers[i] = buffer.ReadUnsignedShort(); } } public override IByteBuffer Encode() { IByteBuffer buffer = Unpooled.Buffer(); buffer.WriteByte(FunctionCode); buffer.WriteByte(byteCount); foreach (var register in Registers) { buffer.WriteUnsignedShort(register); } return buffer; } }
其中 ModbusCommand 為 Function Code 的枚舉:
enum ModbusCommand : short
{
ReadCoils = 0x01,
ReadDiscreteInputs = 0x02,
ReadHoldingRegisters = 0x03,
ReadInputRegisters = 0x04,
WriteSingleCoil = 0x05,
WriteSingleRegister = 0x06,
WriteMultipleCoils = 0x0F,
WriteMultipleRegisters = 0x10,
}
文中為方便請求類和響應類均直接繼承了 ModbusFunction,實際開發中請求類和響應類均沒有直接繼承 ModbusFunction,而是根據其他 Function Code 的 Data 進行再次抽象後繼承。
開源地址:modbus-tcp
DotNetty 實現 Modbus TCP 系列 (二) ModbusFunction 類圖及繼承舉例