From 00e22ee214f2022e57808956162caef38bd27a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20J=C3=A4ger?= Date: Wed, 16 May 2018 15:50:00 +0200 Subject: [PATCH] Incorporate fixes from #117 (moved to helpers) fix array naming. --- S7.Net.UnitTest/S7NetTestsAsync.cs | 97 ++++++++++++++++++++++++++---- S7.Net.UnitTest/S7NetTestsSync.cs | 6 +- S7.Net/PLCAsynchronous.cs | 34 +++-------- S7.Net/PLCHelpers.cs | 29 +++++++++ S7.Net/PLCSynchronous.cs | 28 +++------ S7.Net/Types/ByteArray.cs | 4 +- S7.Net/Types/Counter.cs | 2 +- S7.Net/Types/DInt.cs | 2 +- S7.Net/Types/DWord.cs | 2 +- S7.Net/Types/Double.cs | 2 +- S7.Net/Types/Timer.cs | 2 +- S7.Net/Types/Word.cs | 2 +- 12 files changed, 142 insertions(+), 68 deletions(-) diff --git a/S7.Net.UnitTest/S7NetTestsAsync.cs b/S7.Net.UnitTest/S7NetTestsAsync.cs index af0788a..6c6d977 100644 --- a/S7.Net.UnitTest/S7NetTestsAsync.cs +++ b/S7.Net.UnitTest/S7NetTestsAsync.cs @@ -359,20 +359,51 @@ namespace S7.Net.UnitTest public async Task Test_Async_ReadMultipleBytes() { Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor."); + bool val = true; + await plc.WriteAsync("DB2.DBX0.5", val); + bool result = (bool)await plc.ReadAsync("DB2.DBX0.5"); + Assert.AreEqual(val, result); - ushort val = 16384; - await plc.WriteAsync("DB2.DBW16384", val); - ushort result = (ushort)await plc.ReadAsync("DB2.DBW16384"); - Assert.AreEqual(val, result, "A ushort goes from 0 to 64512"); + ushort val1 = 16384; + await plc.WriteAsync("DB2.DBW16384", val1); + ushort result1 = (ushort)await plc.ReadAsync("DB2.DBW16384"); + Assert.AreEqual(val1, result1, "A ushort goes from 0 to 64512"); - ushort val2 = 129; - await plc.WriteAsync("DB2.DBW16", val2); - ushort result2 = (ushort)await plc.ReadAsync("DB2.DBW16"); - Assert.AreEqual(val2, result2, "A ushort goes from 0 to 64512"); + bool val2 = true; + await plc.WriteAsync("DB2.DBX8192.7", val2); + bool result2 = (bool)await plc.ReadAsync("DB2.DBX8192.7"); + Assert.AreEqual(val2, result2); + + ushort val3 = 129; + await plc.WriteAsync("DB2.DBW16", val3); + ushort result3 = (ushort)await plc.ReadAsync("DB2.DBW16"); + Assert.AreEqual(val3, result3, "A ushort goes from 0 to 64512"); + + byte[] val4 = new byte[] { 0x12, 0x34 }; + await plc.WriteAsync("DB2.DBB2048", val4[0]); + await plc.WriteAsync("DB2.DBB2049", val4[1]); + byte result4b0 = (byte)await plc.ReadAsync("DB2.DBB2048"); + byte result4b1 = (byte)await plc.ReadAsync("DB2.DBB2049"); + Assert.AreEqual(val4[0], result4b0); + Assert.AreEqual(val4[1], result4b1); + + bool val6 = true; + await plc.WriteAsync("DB2.DBX16384.6", val6); + bool result6 = (bool)await plc.ReadAsync("DB2.DBX16384.6"); + Assert.AreEqual(val6, result6); var dataItems = new List() { new DataItem + { + Count = 1, + DataType = DataType.DataBlock, + DB = 2, + StartByteAdr = 0, + BitAdr = 5, + VarType = VarType.Bit + } + ,new DataItem { Count = 1, DataType = DataType.DataBlock, @@ -381,19 +412,61 @@ namespace S7.Net.UnitTest VarType = VarType.Word }, new DataItem + { + Count = 1, + DataType = DataType.DataBlock, + DB = 2, + StartByteAdr = 8192, + BitAdr = 7, + VarType = VarType.Bit + }, + new DataItem { Count = 1, DataType = DataType.DataBlock, DB = 2, StartByteAdr = 16, VarType = VarType.Word - } + }, + // single byte + new DataItem + { + Count = 1, + DataType = DataType.DataBlock, + DB = 2, + StartByteAdr = 2048, + VarType = VarType.Byte + }, + // multiple bytes + new DataItem + { + Count = 2, + DataType = DataType.DataBlock, + DB = 2, + StartByteAdr = 2048, + VarType = VarType.Byte + }, + new DataItem + { + Count = 1, + DataType = DataType.DataBlock, + DB = 2, + StartByteAdr = 16384, + BitAdr = 6, + VarType = VarType.Bit + }, }; - dataItems = await plc.ReadMultipleVarsAsync(dataItems); + var dataItemsRes = await plc.ReadMultipleVarsAsync(dataItems); - Assert.AreEqual(dataItems[0].Value, val); - Assert.AreEqual(dataItems[1].Value, val2); + Assert.AreEqual(val, dataItemsRes[0].Value); + Assert.AreEqual(val1, dataItemsRes[1].Value); + Assert.AreEqual(val2, dataItemsRes[2].Value); + Assert.AreEqual(val3, dataItemsRes[3].Value); + Assert.AreEqual(val4[0], dataItemsRes[4].Value); + Assert.AreEqual(val4[0], ((byte[])dataItemsRes[5].Value)[0]); //dataItem[5].Value should be byte[2] + Assert.AreEqual(val4[1], ((byte[])dataItemsRes[5].Value)[1]); + Assert.AreEqual(val6, dataItemsRes[6].Value); } /// diff --git a/S7.Net.UnitTest/S7NetTestsSync.cs b/S7.Net.UnitTest/S7NetTestsSync.cs index 6889a16..1c3f4d5 100644 --- a/S7.Net.UnitTest/S7NetTestsSync.cs +++ b/S7.Net.UnitTest/S7NetTestsSync.cs @@ -908,8 +908,10 @@ namespace S7.Net.UnitTest { Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor."); - var tc = new TestSmallClass(); - tc.Bool1 = true; + var tc = new TestSmallClass + { + Bool1 = true + }; plc.WriteClass(tc, DB2); var tc2 = plc.ReadClass(DB2); diff --git a/S7.Net/PLCAsynchronous.cs b/S7.Net/PLCAsynchronous.cs index a0ca312..5ac01d4 100644 --- a/S7.Net/PLCAsynchronous.cs +++ b/S7.Net/PLCAsynchronous.cs @@ -102,7 +102,7 @@ namespace S7.Net public async Task ReadAsync(string variable) { var adr = new PLCAddress(variable); - return await ReadAsync(adr.dataType, adr.DBNumber, adr.Address, adr.varType, 1, (byte)adr.BitNumber); + return await ReadAsync(adr.dataType, adr.DBNumber, adr.Address, adr.varType, 1, (byte)adr.BitNumber); } /// @@ -213,12 +213,11 @@ namespace S7.Net throw new Exception("Too many vars requested"); if (cntBytes > 222) throw new Exception("Too many bytes requested"); // TODO: proper TDU check + split in multiple requests - try { // first create the header int packageSize = 19 + (dataItems.Count * 12); - Types.ByteArray package = new ByteArray(packageSize); + ByteArray package = new ByteArray(packageSize); package.Add(ReadHeaderPackage(dataItems.Count)); // package.Add(0x02); // datenart foreach (var dataItem in dataItems) @@ -226,28 +225,13 @@ namespace S7.Net package.Add(CreateReadDataRequestPackage(dataItem.DataType, dataItem.DB, dataItem.StartByteAdr, VarTypeToByteLength(dataItem.VarType, dataItem.Count))); } - await socket.SendAsync(package.array, 0, package.array.Length, SocketFlags.None); + socket.Send(package.Array, package.Array.Length, SocketFlags.None); - var s7data = await COTP.TSDU.ReadAsync(socket); //TODO use Async + var s7data = await COTP.TSDU.ReadAsync(socket); if (s7data == null || s7data[14] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); - int offset = 18; - foreach (var dataItem in dataItems) - { - int byteCnt = VarTypeToByteLength(dataItem.VarType, dataItem.Count); - byte[] bytes = new byte[byteCnt]; - - for (int i = 0; i < byteCnt; i++) - { - bytes[i] = s7data[i + offset]; - } - - offset += byteCnt + 4; - - dataItem.Value = ParseBytes(dataItem.VarType, bytes, dataItem.Count); - } - return dataItems; + ParseDataIntoDataItems(s7data, dataItems); } catch (SocketException socketException) { @@ -259,7 +243,7 @@ namespace S7.Net LastErrorCode = ErrorCode.WriteData; LastErrorString = exc.Message; } - return null; + return dataItems; } /// @@ -416,7 +400,7 @@ namespace S7.Net // package.Add(0x02); // datenart package.Add(CreateReadDataRequestPackage(dataType, db, startByteAdr, count)); - await socket.SendAsync(package.array, 0, package.array.Length, SocketFlags.None); + await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None); var s7data = await COTP.TSDU.ReadAsync(socket); if (s7data == null || s7data[14] != 0xff) @@ -468,7 +452,7 @@ namespace S7.Net // now join the header and the data package.Add(value); - await socket.SendAsync(package.array, 0, package.array.Length, SocketFlags.None); + await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None); var s7data = await COTP.TSDU.ReadAsync(socket); if (s7data == null || s7data[14] != 0xff) @@ -518,7 +502,7 @@ namespace S7.Net // now join the header and the data package.Add(value); - await socket.SendAsync(package.array, 0, package.array.Length, SocketFlags.None); + await socket.SendAsync(package.Array, 0, package.Array.Length, SocketFlags.None); var s7data = await COTP.TSDU.ReadAsync(socket); if (s7data == null || s7data[14] != 0xff) diff --git a/S7.Net/PLCHelpers.cs b/S7.Net/PLCHelpers.cs index 8e03166..d4c42ce 100644 --- a/S7.Net/PLCHelpers.cs +++ b/S7.Net/PLCHelpers.cs @@ -481,5 +481,34 @@ namespace S7.Net 7, 80 //Try 1920 PDU Size. Same as libnodave. }; } + + private void ParseDataIntoDataItems(byte[] s7data, List dataItems) + { + int offset = 14; + foreach (var dataItem in dataItems) + { + // check for Return Code = Success + if (s7data[offset] != 0xff) + throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); + + // to Data bytes + offset += 4; + + int byteCnt = VarTypeToByteLength(dataItem.VarType, dataItem.Count); + dataItem.Value = ParseBytes( + dataItem.VarType, + s7data.Skip(offset).Take(byteCnt).ToArray(), + dataItem.Count, + dataItem.BitAdr + ); + + // next Item + offset += byteCnt; + + // Fill byte in response when bytecount is odd + if (dataItem.Count % 2 != 0 && (dataItem.VarType == VarType.Byte || dataItem.VarType == VarType.Bit)) + offset++; + } + } } } diff --git a/S7.Net/PLCSynchronous.cs b/S7.Net/PLCSynchronous.cs index a77297b..40ee2dc 100644 --- a/S7.Net/PLCSynchronous.cs +++ b/S7.Net/PLCSynchronous.cs @@ -373,7 +373,8 @@ namespace S7.Net private byte[] ReadBytesWithSingleRequest(DataType dataType, int db, int startByteAdr, int count) { byte[] bytes = new byte[count]; - try { + try + { // first create the header int packageSize = 31; ByteArray package = new ByteArray(packageSize); @@ -381,7 +382,7 @@ namespace S7.Net // package.Add(0x02); // datenart package.Add(CreateReadDataRequestPackage(dataType, db, startByteAdr, count)); - socket.Send(package.array, 0, package.array.Length, SocketFlags.None); + socket.Send(package.Array, 0, package.Array.Length, SocketFlags.None); var s7data = COTP.TSDU.Read(socket); if (s7data == null || s7data[14] != 0xff) @@ -435,7 +436,7 @@ namespace S7.Net // now join the header and the data package.Add(value); - socket.Send(package.array, package.array.Length, SocketFlags.None); + socket.Send(package.Array, package.Array.Length, SocketFlags.None); var s7data = COTP.TSDU.Read(socket); if (s7data == null || s7data[14] != 0xff) @@ -484,7 +485,7 @@ namespace S7.Net // now join the header and the data package.Add(value); - socket.Send(package.array, package.array.Length, SocketFlags.None); + socket.Send(package.Array, package.Array.Length, SocketFlags.None); var s7data = COTP.TSDU.Read(socket); if (s7data == null || s7data[14] != 0xff) @@ -519,7 +520,6 @@ namespace S7.Net throw new Exception("Too many vars requested"); if (cntBytes > 222) throw new Exception("Too many bytes requested"); // TODO: proper TDU check + split in multiple requests - try { // first create the header @@ -532,27 +532,13 @@ namespace S7.Net package.Add(CreateReadDataRequestPackage(dataItem.DataType, dataItem.DB, dataItem.StartByteAdr, VarTypeToByteLength(dataItem.VarType, dataItem.Count))); } - socket.Send(package.array, 0, package.array.Length, SocketFlags.None); + socket.Send(package.Array, package.Array.Length, SocketFlags.None); var s7data = COTP.TSDU.Read(socket); if (s7data == null || s7data[14] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); - int offset = 18; - foreach (var dataItem in dataItems) - { - int byteCnt = VarTypeToByteLength(dataItem.VarType, dataItem.Count); - byte[] bytes = new byte[byteCnt]; - - for (int i = 0; i < byteCnt; i++) - { - bytes[i] = s7data[i + offset]; - } - - offset += byteCnt + 4; - - dataItem.Value = ParseBytes(dataItem.VarType, bytes, dataItem.Count); - } + ParseDataIntoDataItems(s7data, dataItems); } catch (SocketException socketException) { diff --git a/S7.Net/Types/ByteArray.cs b/S7.Net/Types/ByteArray.cs index 0b0c708..ca8456a 100644 --- a/S7.Net/Types/ByteArray.cs +++ b/S7.Net/Types/ByteArray.cs @@ -6,7 +6,7 @@ namespace S7.Net.Types { List list = new List(); - public byte[] array + public byte[] Array { get { return list.ToArray(); } } @@ -38,7 +38,7 @@ namespace S7.Net.Types public void Add(ByteArray byteArray) { - list.AddRange(byteArray.array); + list.AddRange(byteArray.Array); } } } diff --git a/S7.Net/Types/Counter.cs b/S7.Net/Types/Counter.cs index 7a56cf7..f52f727 100644 --- a/S7.Net/Types/Counter.cs +++ b/S7.Net/Types/Counter.cs @@ -43,7 +43,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (UInt16 val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } /// diff --git a/S7.Net/Types/DInt.cs b/S7.Net/Types/DInt.cs index a5b5caa..4d42bde 100644 --- a/S7.Net/Types/DInt.cs +++ b/S7.Net/Types/DInt.cs @@ -43,7 +43,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (Int32 val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } /// diff --git a/S7.Net/Types/DWord.cs b/S7.Net/Types/DWord.cs index 14bc2a4..87c254f 100644 --- a/S7.Net/Types/DWord.cs +++ b/S7.Net/Types/DWord.cs @@ -53,7 +53,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (UInt32 val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } /// diff --git a/S7.Net/Types/Double.cs b/S7.Net/Types/Double.cs index f06385b..857784f 100644 --- a/S7.Net/Types/Double.cs +++ b/S7.Net/Types/Double.cs @@ -70,7 +70,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (double val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } /// diff --git a/S7.Net/Types/Timer.cs b/S7.Net/Types/Timer.cs index ede6af8..b5ecd45 100644 --- a/S7.Net/Types/Timer.cs +++ b/S7.Net/Types/Timer.cs @@ -60,7 +60,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (UInt16 val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } /// diff --git a/S7.Net/Types/Word.cs b/S7.Net/Types/Word.cs index 1631fae..8004992 100644 --- a/S7.Net/Types/Word.cs +++ b/S7.Net/Types/Word.cs @@ -51,7 +51,7 @@ namespace S7.Net.Types ByteArray arr = new ByteArray(); foreach (UInt16 val in value) arr.Add(ToByteArray(val)); - return arr.array; + return arr.Array; } ///