diff --git a/S7.Net.UnitTest/Helpers/TestLongClass.cs b/S7.Net.UnitTest/Helpers/TestLongClass.cs
new file mode 100644
index 0000000..5ce76c8
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/TestLongClass.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace S7.UnitTest.Helpers
+{
+ ///
+ /// This is a class that contains more than 200 bytes and that needs 2 plc requests to complete a read/write cycle
+ ///
+ class TestLongClass
+ {
+ public short IntVariable0 { get; set; }
+ public short IntVariable1 { get; set; }
+ public short IntVariable2 { get; set; }
+ public short IntVariable3 { get; set; }
+ public short IntVariable4 { get; set; }
+ public short IntVariable5 { get; set; }
+ public short IntVariable6 { get; set; }
+ public short IntVariable7 { get; set; }
+ public short IntVariable8 { get; set; }
+ public short IntVariable9 { get; set; }
+
+ public short IntVariable10 { get; set; }
+ public short IntVariable11 { get; set; }
+ public short IntVariable12 { get; set; }
+ public short IntVariable13 { get; set; }
+ public short IntVariable14 { get; set; }
+ public short IntVariable15 { get; set; }
+ public short IntVariable16 { get; set; }
+ public short IntVariable17 { get; set; }
+ public short IntVariable18 { get; set; }
+ public short IntVariable19 { get; set; }
+
+ public short IntVariable20 { get; set; }
+ public short IntVariable21 { get; set; }
+ public short IntVariable22 { get; set; }
+ public short IntVariable23 { get; set; }
+ public short IntVariable24 { get; set; }
+ public short IntVariable25 { get; set; }
+ public short IntVariable26 { get; set; }
+ public short IntVariable27 { get; set; }
+ public short IntVariable28 { get; set; }
+ public short IntVariable29 { get; set; }
+
+ public short IntVariable30 { get; set; }
+ public short IntVariable31 { get; set; }
+ public short IntVariable32 { get; set; }
+ public short IntVariable33 { get; set; }
+ public short IntVariable34 { get; set; }
+ public short IntVariable35 { get; set; }
+ public short IntVariable36 { get; set; }
+ public short IntVariable37 { get; set; }
+ public short IntVariable38 { get; set; }
+ public short IntVariable39 { get; set; }
+
+ public short IntVariable40 { get; set; }
+ public short IntVariable41 { get; set; }
+ public short IntVariable42 { get; set; }
+ public short IntVariable43 { get; set; }
+ public short IntVariable44 { get; set; }
+ public short IntVariable45 { get; set; }
+ public short IntVariable46 { get; set; }
+ public short IntVariable47 { get; set; }
+ public short IntVariable48 { get; set; }
+ public short IntVariable49 { get; set; }
+
+ public short IntVariable50 { get; set; }
+ public short IntVariable51 { get; set; }
+ public short IntVariable52 { get; set; }
+ public short IntVariable53 { get; set; }
+ public short IntVariable54 { get; set; }
+ public short IntVariable55 { get; set; }
+ public short IntVariable56 { get; set; }
+ public short IntVariable57 { get; set; }
+ public short IntVariable58 { get; set; }
+ public short IntVariable59 { get; set; }
+
+ public short IntVariable60 { get; set; }
+ public short IntVariable61 { get; set; }
+ public short IntVariable62 { get; set; }
+ public short IntVariable63 { get; set; }
+ public short IntVariable64 { get; set; }
+ public short IntVariable65 { get; set; }
+ public short IntVariable66 { get; set; }
+ public short IntVariable67 { get; set; }
+ public short IntVariable68 { get; set; }
+ public short IntVariable69 { get; set; }
+
+ public short IntVariable70 { get; set; }
+ public short IntVariable71 { get; set; }
+ public short IntVariable72 { get; set; }
+ public short IntVariable73 { get; set; }
+ public short IntVariable74 { get; set; }
+ public short IntVariable75 { get; set; }
+ public short IntVariable76 { get; set; }
+ public short IntVariable77 { get; set; }
+ public short IntVariable78 { get; set; }
+ public short IntVariable79 { get; set; }
+
+ public short IntVariable80 { get; set; }
+ public short IntVariable81 { get; set; }
+ public short IntVariable82 { get; set; }
+ public short IntVariable83 { get; set; }
+ public short IntVariable84 { get; set; }
+ public short IntVariable85 { get; set; }
+ public short IntVariable86 { get; set; }
+ public short IntVariable87 { get; set; }
+ public short IntVariable88 { get; set; }
+ public short IntVariable89 { get; set; }
+
+ public short IntVariable90 { get; set; }
+ public short IntVariable91 { get; set; }
+ public short IntVariable92 { get; set; }
+ public short IntVariable93 { get; set; }
+ public short IntVariable94 { get; set; }
+ public short IntVariable95 { get; set; }
+ public short IntVariable96 { get; set; }
+ public short IntVariable97 { get; set; }
+ public short IntVariable98 { get; set; }
+ public short IntVariable99 { get; set; }
+
+ public short IntVariable100 { get; set; }
+ public short IntVariable101 { get; set; }
+ public short IntVariable102 { get; set; }
+ public short IntVariable103 { get; set; }
+ public short IntVariable104 { get; set; }
+ public short IntVariable105 { get; set; }
+ public short IntVariable106 { get; set; }
+ public short IntVariable107 { get; set; }
+ public short IntVariable108 { get; set; }
+ public short IntVariable109 { get; set; }
+
+ public short IntVariable110 { get; set; }
+ public short IntVariable111 { get; set; }
+ public short IntVariable112 { get; set; }
+ public short IntVariable113 { get; set; }
+ public short IntVariable114 { get; set; }
+ public short IntVariable115 { get; set; }
+ public short IntVariable116 { get; set; }
+ public short IntVariable117 { get; set; }
+ public short IntVariable118 { get; set; }
+ public short IntVariable119 { get; set; }
+ }
+}
diff --git a/S7.Net.UnitTest/Helpers/TestLongStruct.cs b/S7.Net.UnitTest/Helpers/TestLongStruct.cs
new file mode 100644
index 0000000..7c68356
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/TestLongStruct.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace S7.UnitTest.Helpers
+{
+ ///
+ /// This is a struct that contains more than 200 bytes and that needs 2 plc requests to complete a read/write cycle
+ ///
+ struct TestLongStruct
+ {
+ // these variables are not used, but are needed to match the size of the DB
+#pragma warning disable 0649
+
+
+ public short IntVariable0;
+ public short IntVariable1;
+ public short IntVariable2;
+ public short IntVariable3;
+ public short IntVariable4;
+ public short IntVariable5;
+ public short IntVariable6;
+ public short IntVariable7;
+ public short IntVariable8;
+ public short IntVariable9;
+
+ public short IntVariable10;
+ public short IntVariable11;
+ public short IntVariable12;
+ public short IntVariable13;
+ public short IntVariable14;
+ public short IntVariable15;
+ public short IntVariable16;
+ public short IntVariable17;
+ public short IntVariable18;
+ public short IntVariable19;
+
+ public short IntVariable20;
+ public short IntVariable21;
+ public short IntVariable22;
+ public short IntVariable23;
+ public short IntVariable24;
+ public short IntVariable25;
+ public short IntVariable26;
+ public short IntVariable27;
+ public short IntVariable28;
+ public short IntVariable29;
+
+ public short IntVariable30;
+ public short IntVariable31;
+ public short IntVariable32;
+ public short IntVariable33;
+ public short IntVariable34;
+ public short IntVariable35;
+ public short IntVariable36;
+ public short IntVariable37;
+ public short IntVariable38;
+ public short IntVariable39;
+
+ public short IntVariable40;
+ public short IntVariable41;
+ public short IntVariable42;
+ public short IntVariable43;
+ public short IntVariable44;
+ public short IntVariable45;
+ public short IntVariable46;
+ public short IntVariable47;
+ public short IntVariable48;
+ public short IntVariable49;
+
+ public short IntVariable50;
+ public short IntVariable51;
+ public short IntVariable52;
+ public short IntVariable53;
+ public short IntVariable54;
+ public short IntVariable55;
+ public short IntVariable56;
+ public short IntVariable57;
+ public short IntVariable58;
+ public short IntVariable59;
+
+ public short IntVariable60;
+ public short IntVariable61;
+ public short IntVariable62;
+ public short IntVariable63;
+ public short IntVariable64;
+ public short IntVariable65;
+ public short IntVariable66;
+ public short IntVariable67;
+ public short IntVariable68;
+ public short IntVariable69;
+
+ public short IntVariable70;
+ public short IntVariable71;
+ public short IntVariable72;
+ public short IntVariable73;
+ public short IntVariable74;
+ public short IntVariable75;
+ public short IntVariable76;
+ public short IntVariable77;
+ public short IntVariable78;
+ public short IntVariable79;
+
+ public short IntVariable80;
+ public short IntVariable81;
+ public short IntVariable82;
+ public short IntVariable83;
+ public short IntVariable84;
+ public short IntVariable85;
+ public short IntVariable86;
+ public short IntVariable87;
+ public short IntVariable88;
+ public short IntVariable89;
+
+ public short IntVariable90;
+ public short IntVariable91;
+ public short IntVariable92;
+ public short IntVariable93;
+ public short IntVariable94;
+ public short IntVariable95;
+ public short IntVariable96;
+ public short IntVariable97;
+ public short IntVariable98;
+ public short IntVariable99;
+
+ public short IntVariable100;
+ public short IntVariable101;
+ public short IntVariable102;
+ public short IntVariable103;
+ public short IntVariable104;
+ public short IntVariable105;
+ public short IntVariable106;
+ public short IntVariable107;
+ public short IntVariable108;
+ public short IntVariable109;
+
+ public short IntVariable110;
+ public short IntVariable111;
+ public short IntVariable112;
+ public short IntVariable113;
+ public short IntVariable114;
+ public short IntVariable115;
+ public short IntVariable116;
+ public short IntVariable117;
+ public short IntVariable118;
+ public short IntVariable119;
+
+#pragma warning restore 0649
+
+ }
+}
diff --git a/S7.Net.UnitTest/S7.Net.UnitTest.csproj b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
index 202e509..e148f86 100644
--- a/S7.Net.UnitTest/S7.Net.UnitTest.csproj
+++ b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
@@ -55,11 +55,13 @@
+
+
diff --git a/S7.Net.UnitTest/S7NetTests.cs b/S7.Net.UnitTest/S7NetTests.cs
index 51ca5b7..652ef7d 100644
--- a/S7.Net.UnitTest/S7NetTests.cs
+++ b/S7.Net.UnitTest/S7NetTests.cs
@@ -4,7 +4,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using S7.Net;
using S7.Net.UnitTest.Helpers;
using S7.Net.UnitTest;
-using System.ServiceProcess;
+using System.ServiceProcess;
+using S7.UnitTest.Helpers;
#endregion
@@ -185,7 +186,136 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
Assert.AreEqual(tc.RealVariable, Math.Round(tc2.RealVariable, 3));
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
- }
+ }
+
+ ///
+ /// Read/Write a struct that has the same properties of a DB with the same field in the same order
+ ///
+ [TestMethod]
+ public void T06_ReadAndWriteLongStruct()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ TestLongStruct tc = new TestLongStruct();
+ tc.IntVariable0 = 0;
+ tc.IntVariable1 = 1;
+ tc.IntVariable10 = 10;
+ tc.IntVariable11 = 11;
+ tc.IntVariable20 = 20;
+ tc.IntVariable21 = 21;
+ tc.IntVariable30 = 30;
+ tc.IntVariable31 = 31;
+ tc.IntVariable40 = 40;
+ tc.IntVariable41 = 41;
+ tc.IntVariable50 = 50;
+ tc.IntVariable51 = 51;
+ tc.IntVariable60 = 60;
+ tc.IntVariable61 = 61;
+ tc.IntVariable70 = 70;
+ tc.IntVariable71 = 71;
+ tc.IntVariable80 = 80;
+ tc.IntVariable81 = 81;
+ tc.IntVariable90 = 90;
+ tc.IntVariable91 = 91;
+ tc.IntVariable100 = 100;
+ tc.IntVariable101 = 101;
+ tc.IntVariable110 = 200;
+ tc.IntVariable111 = 201;
+ plc.WriteStruct(tc, DB2);
+ Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
+ // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
+ TestLongStruct tc2 = (TestLongStruct)plc.ReadStruct(typeof(TestLongStruct), DB2);
+ Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
+ Assert.AreEqual( tc.IntVariable0, tc2.IntVariable0 );
+ Assert.AreEqual( tc.IntVariable1, tc2.IntVariable1 );
+ Assert.AreEqual( tc.IntVariable10, tc2.IntVariable10);
+ Assert.AreEqual( tc.IntVariable11, tc2.IntVariable11);
+ Assert.AreEqual( tc.IntVariable20, tc2.IntVariable20);
+ Assert.AreEqual( tc.IntVariable21, tc2.IntVariable21);
+ Assert.AreEqual( tc.IntVariable30, tc2.IntVariable30);
+ Assert.AreEqual( tc.IntVariable31, tc2.IntVariable31);
+ Assert.AreEqual( tc.IntVariable40, tc2.IntVariable40);
+ Assert.AreEqual( tc.IntVariable41, tc2.IntVariable41);
+ Assert.AreEqual( tc.IntVariable50, tc2.IntVariable50);
+ Assert.AreEqual( tc.IntVariable51, tc2.IntVariable51);
+ Assert.AreEqual( tc.IntVariable60, tc2.IntVariable60);
+ Assert.AreEqual( tc.IntVariable61, tc2.IntVariable61);
+ Assert.AreEqual( tc.IntVariable70, tc2.IntVariable70);
+ Assert.AreEqual( tc.IntVariable71, tc2.IntVariable71);
+ Assert.AreEqual( tc.IntVariable80, tc2.IntVariable80);
+ Assert.AreEqual( tc.IntVariable81, tc2.IntVariable81);
+ Assert.AreEqual( tc.IntVariable90, tc2.IntVariable90);
+ Assert.AreEqual(tc.IntVariable91, tc2.IntVariable91);
+ Assert.AreEqual(tc.IntVariable100, tc2.IntVariable100);
+ Assert.AreEqual(tc.IntVariable101, tc2.IntVariable101);
+ Assert.AreEqual(tc.IntVariable110, tc2.IntVariable110);
+ Assert.AreEqual(tc.IntVariable111, tc2.IntVariable111);
+ }
+
+ ///
+ /// Read/Write a class that has the same properties of a DB with the same field in the same order
+ ///
+ [TestMethod]
+ public void T07_ReadAndWriteLongClass()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ TestLongClass tc = new TestLongClass();
+ tc.IntVariable0 = 0;
+ tc.IntVariable1 = 1;
+ tc.IntVariable10 = 10;
+ tc.IntVariable11 = 11;
+ tc.IntVariable20 = 20;
+ tc.IntVariable21 = 21;
+ tc.IntVariable30 = 30;
+ tc.IntVariable31 = 31;
+ tc.IntVariable40 = 40;
+ tc.IntVariable41 = 41;
+ tc.IntVariable50 = 50;
+ tc.IntVariable51 = 51;
+ tc.IntVariable60 = 60;
+ tc.IntVariable61 = 61;
+ tc.IntVariable70 = 70;
+ tc.IntVariable71 = 71;
+ tc.IntVariable80 = 80;
+ tc.IntVariable81 = 81;
+ tc.IntVariable90 = 90;
+ tc.IntVariable91 = 91;
+ tc.IntVariable100 = 100;
+ tc.IntVariable101 = 101;
+ tc.IntVariable110 = 200;
+ tc.IntVariable111 = 201;
+ plc.WriteClass(tc, DB2);
+ Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
+ // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
+ TestLongClass tc2 = new TestLongClass();
+ plc.ReadClass(tc2, DB2);
+ Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
+ Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
+ Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
+ Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
+ Assert.AreEqual(tc.IntVariable11, tc2.IntVariable11);
+ Assert.AreEqual(tc.IntVariable20, tc2.IntVariable20);
+ Assert.AreEqual(tc.IntVariable21, tc2.IntVariable21);
+ Assert.AreEqual(tc.IntVariable30, tc2.IntVariable30);
+ Assert.AreEqual(tc.IntVariable31, tc2.IntVariable31);
+ Assert.AreEqual(tc.IntVariable40, tc2.IntVariable40);
+ Assert.AreEqual(tc.IntVariable41, tc2.IntVariable41);
+ Assert.AreEqual(tc.IntVariable50, tc2.IntVariable50);
+ Assert.AreEqual(tc.IntVariable51, tc2.IntVariable51);
+ Assert.AreEqual(tc.IntVariable60, tc2.IntVariable60);
+ Assert.AreEqual(tc.IntVariable61, tc2.IntVariable61);
+ Assert.AreEqual(tc.IntVariable70, tc2.IntVariable70);
+ Assert.AreEqual(tc.IntVariable71, tc2.IntVariable71);
+ Assert.AreEqual(tc.IntVariable80, tc2.IntVariable80);
+ Assert.AreEqual(tc.IntVariable81, tc2.IntVariable81);
+ Assert.AreEqual(tc.IntVariable90, tc2.IntVariable90);
+ Assert.AreEqual(tc.IntVariable91, tc2.IntVariable91);
+ Assert.AreEqual(tc.IntVariable100, tc2.IntVariable100);
+ Assert.AreEqual(tc.IntVariable101, tc2.IntVariable101);
+ Assert.AreEqual(tc.IntVariable110, tc2.IntVariable110);
+ Assert.AreEqual(tc.IntVariable111, tc2.IntVariable111);
+ }
#endregion
diff --git a/S7.Net/PLC.cs b/S7.Net/PLC.cs
index dfbbb5f..bf63dda 100644
--- a/S7.Net/PLC.cs
+++ b/S7.Net/PLC.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -505,11 +507,12 @@ namespace S7.Net
public object ReadStruct(Type structType, int db)
{
- double numBytes = Types.Struct.GetStructSize(structType);
+ int numBytes = Types.Struct.GetStructSize(structType);
// now read the package
- byte[] bytes = (byte[])Read(DataType.DataBlock, db, 0, VarType.Byte, (int)numBytes);
+ List resultBytes = ReadMultipleBytes(numBytes, db);
+
// and decode it
- return Types.Struct.FromBytes(structType, bytes);
+ return Types.Struct.FromBytes(structType, resultBytes.ToArray());
}
///
@@ -520,11 +523,11 @@ namespace S7.Net
public void ReadClass(object sourceClass, int db)
{
Type classType = sourceClass.GetType();
- double numBytes = Types.Class.GetClassSize(classType);
+ int numBytes = Types.Class.GetClassSize(classType);
// now read the package
- byte[] bytes = (byte[])Read(DataType.DataBlock, db, 0, VarType.Byte, (int)numBytes);
+ List resultBytes = ReadMultipleBytes(numBytes, db);
// and decode it
- Types.Class.FromBytes(sourceClass, classType, bytes);
+ Types.Class.FromBytes(sourceClass, classType, resultBytes.ToArray());
}
public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
@@ -794,36 +797,76 @@ namespace S7.Net
public ErrorCode WriteStruct(object structValue, int db)
{
- try
- {
- byte[] bytes = Types.Struct.ToBytes(structValue);
- ErrorCode errCode = WriteBytes(DataType.DataBlock, db, 0, bytes);
- return errCode;
- }
- catch
- {
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = "An error occurred while writing data.";
- return LastErrorCode;
- }
+ var bytes = Types.Struct.ToBytes(structValue).ToList();
+ var errCode = WriteMultipleBytes(bytes, db);
+ return errCode;
}
public ErrorCode WriteClass(object classValue, int db)
{
+ var bytes = Types.Class.ToBytes(classValue).ToList();
+ var errCode = WriteMultipleBytes(bytes, db);
+ return errCode;
+ }
+
+ ///
+ /// Writes multiple bytes in a DB starting from index 0. This handles more than 200 bytes with multiple requests.
+ ///
+ /// The bytes to be written
+ /// The DB number
+ /// ErrorCode when writing (NoError if everything was ok)
+ private ErrorCode WriteMultipleBytes(List bytes, int db)
+ {
+ ErrorCode errCode = ErrorCode.NoError;
+ int index = 0;
try
{
- byte[] bytes = Types.Class.ToBytes(classValue);
- ErrorCode errCode = WriteBytes(DataType.DataBlock, db, 0, bytes);
- return errCode;
+ while (bytes.Count > 0)
+ {
+ var maxToWrite = Math.Min(bytes.Count, 200);
+ var part = bytes.ToList().GetRange(0, maxToWrite);
+ errCode = WriteBytes(DataType.DataBlock, db, index, part.ToArray());
+ bytes.RemoveRange(0, maxToWrite);
+ index += maxToWrite;
+ if (errCode != ErrorCode.NoError)
+ {
+ break;
+ }
+ }
}
catch
{
LastErrorCode = ErrorCode.WriteData;
LastErrorString = "An error occurred while writing data.";
- return LastErrorCode;
}
+ return errCode;
}
+ ///
+ /// Reads a number of bytes from a DB starting from index 0. This handles more than 200 bytes with multiple requests.
+ ///
+ ///
+ ///
+ ///
+ private List ReadMultipleBytes(int numBytes, int db)
+ {
+ List resultBytes = new List();
+ int index = 0;
+ while (numBytes > 0)
+ {
+ var maxToRead = (int)Math.Min(numBytes, 200);
+ byte[] bytes = (byte[])Read(DataType.DataBlock, db, index, VarType.Byte, (int)maxToRead);
+ resultBytes.AddRange(bytes);
+ numBytes -= maxToRead;
+ index += maxToRead;
+ }
+ return resultBytes;
+ }
+
+
+
+ #region IDisposable members
+
public void Dispose()
{
if (_mSocket != null)
@@ -835,6 +878,8 @@ namespace S7.Net
}
//((IDisposable)_mSocket).Dispose();
}
- }
+ }
+
+ #endregion
}
}