[Modbus] 如何 用 C# 開發 Modbus Master Protocol - (05) 實作 TcpModbusResponse

[Modbus] 如何 用 C# 開發 Modbus Master Protocol - (05) 實作 TcpModbusResponse

續上篇,接下來,我要實作Modbus TCP 的 Response Protocol ,這個 TcpModbusResponse 類別主要是驗証資料的正確性

如下圖紅框:

image

 

TcpModbusResponse 實作 AbsModbusResponse 抽像類別:

  1. 指派 FunctionCodePosition ,它表示 Function Code 的位置,由下圖得知,Function Code 的索引值是 7。
  2. CheckDataValidate 方法,沒有處理任何工作。
  3. GetResultArray 方法則是取出結果,例如下圖取出 Coil Status 的結果
    image

 

程式碼如下:

{
    private byte _functionCodePosition = 7;

    protected override byte FunctionCodePosition
    {
        get { return _functionCodePosition; }
        set { _functionCodePosition = value; }
    }

    protected override void CheckDataValidate(byte[] ResponseArray)
    {
    }

    protected override byte[] GetResultArray(byte[] ResponseArray)
    {
        //get result data
        var counterPosition = this.FunctionCodePosition + 1;
        var counter = ResponseArray[counterPosition];
        var resultArray = new byte[counter];
        Array.Copy(ResponseArray, counterPosition + 1, resultArray, 0, counter);
        return resultArray;
    }
}

 


 

建立單元測試,同樣的我們需要驗証資料處理的正確性,在這裡我用到了驅動測試

下圖為測試檔案。

image

驅動測試詳細作法請參考:[Visual Studio 2012 ] 建立資料驅動單元測試

 

測試程式碼如下:

[TestMethod()]
[DeploymentItem("TestDoc\\TcpReadFunc1Test.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestDoc\\TcpReadFunc1Test.csv",
    "TcpReadFunc1Test#csv", DataAccessMethod.Sequential)]
public void ReadCoilsTest()
{
    TcpModbusResponse target = new TcpModbusResponse();

    byte[] RequestArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[0].ToString());
    byte[] ResponseArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[1].ToString());
    byte[] expected = _modbusUtility.HexStringToBytes(TestContext.DataRow[2].ToString());
    var actual = target.ReadCoils(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
[DeploymentItem("TestDoc\\TcpReadFunc2Test.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestDoc\\TcpReadFunc2Test.csv",
    "TcpReadFunc2Test#csv", DataAccessMethod.Sequential)]
public void ReadDiscreteInputsTest()
{
    TcpModbusResponse target = new TcpModbusResponse();

    byte[] RequestArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[0].ToString());
    byte[] ResponseArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[1].ToString());
    byte[] expected = _modbusUtility.HexStringToBytes(TestContext.DataRow[2].ToString());
    var actual = target.ReadDiscreteInputs(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
[DeploymentItem("TestDoc\\TcpReadFunc3Test.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestDoc\\TcpReadFunc3Test.csv",
    "TcpReadFunc3Test#csv", DataAccessMethod.Sequential)]
public void ReadHoldingRegistersTest()
{
    TcpModbusResponse target = new TcpModbusResponse();

    byte[] RequestArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[0].ToString());
    byte[] ResponseArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[1].ToString());
    byte[] expected = _modbusUtility.HexStringToBytes(TestContext.DataRow[2].ToString());

    var actual = target.ReadHoldingRegisters(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
[DeploymentItem("TestDoc\\TcpReadFunc4Test.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestDoc\\TcpReadFunc4Test.csv",
    "TcpReadFunc4Test#csv", DataAccessMethod.Sequential)]
public void ReadInputRegistersTest()
{
    TcpModbusResponse target = new TcpModbusResponse();

    byte[] RequestArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[0].ToString());
    byte[] ResponseArray = _modbusUtility.HexStringToBytes(TestContext.DataRow[1].ToString());
    byte[] expected = _modbusUtility.HexStringToBytes(TestContext.DataRow[2].ToString());

    var actual = target.ReadInputRegisters(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
public void WriteSingleCoilTest()
{
    TcpModbusResponse target = new TcpModbusResponse();
    byte[] RequestArray = _modbusUtility.HexStringToBytes("04 52 00 00 00 06 01 05 00 00 FF 00");
    byte[] ResponseArray = _modbusUtility.HexStringToBytes("04 52 00 00 00 06 01 05 00 00 FF 00");
    byte[] expected = ResponseArray;
    byte[] actual;
    actual = target.WriteSingleCoil(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
public void WriteSingleRegisterTest()
{
    TcpModbusResponse target = new TcpModbusResponse();
    byte[] RequestArray = _modbusUtility.HexStringToBytes("04 F9 00 00 00 06 01 06 00 01 01 00");
    byte[] ResponseArray = _modbusUtility.HexStringToBytes("04 F9 00 00 00 06 01 06 00 01 01 00");

    byte[] expected = ResponseArray;
    byte[] actual;
    actual = target.WriteSingleRegister(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
public void WriteMultipleCoilsTest()
{
    TcpModbusResponse target = new TcpModbusResponse();
    byte[] RequestArray = _modbusUtility.HexStringToBytes("03 7F 00 00 00 09 01 0F 00 00 00 09 02 0E 00");
    byte[] ResponseArray = _modbusUtility.HexStringToBytes("03 7F 00 00 00 06 01 0F 00 00 00 09");

    byte[] expected = ResponseArray;
    byte[] actual;
    actual = target.WriteMultipleCoils(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

[TestMethod()]
public void WriteMultipleRegistersTest()
{
    TcpModbusResponse target = new TcpModbusResponse();
    byte[] RequestArray =
        _modbusUtility.HexStringToBytes(
            "03 DA 00 00 00 1B 01 10 00 00 00 0A 14 00 4E 00 57 FF B2 FF A9 00 17 00 23 00 7B 00 0C 00 21 00 06");
    byte[] ResponseArray = _modbusUtility.HexStringToBytes("03 DA 00 00 00 06 01 10 00 00 00 0A");

    byte[] expected = ResponseArray;
    byte[] actual;
    actual = target.WriteMultipleRegisters(RequestArray, ResponseArray);
    Assert.IsTrue(expected.SequenceEqual(actual));
}

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo