[Modbus] 如何 用 C# 開發 Modbus Master Protocol - (05) 實作 TcpModbusResponse
續上篇,接下來,我要實作Modbus TCP 的 Response Protocol ,這個 TcpModbusResponse 類別主要是驗証資料的正確性
如下圖紅框:
TcpModbusResponse 實作 AbsModbusResponse 抽像類別:
- 指派 FunctionCodePosition ,它表示 Function Code 的位置,由下圖得知,Function Code 的索引值是 7。
- CheckDataValidate 方法,沒有處理任何工作。
- GetResultArray 方法則是取出結果,例如下圖取出 Coil Status 的結果
程式碼如下:
{ 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; } }
建立單元測試,同樣的我們需要驗証資料處理的正確性,在這裡我用到了驅動測試
下圖為測試檔案。
驅動測試詳細作法請參考:[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