diff --git a/S7.Net.UnitTest/S7.Net.UnitTest.csproj b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
index bfaa48e..d65a804 100644
--- a/S7.Net.UnitTest/S7.Net.UnitTest.csproj
+++ b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
@@ -78,6 +78,7 @@
+
diff --git a/S7.Net.UnitTest/TypeTests/StringExTests.cs b/S7.Net.UnitTest/TypeTests/StringExTests.cs
new file mode 100644
index 0000000..164ba4f
--- /dev/null
+++ b/S7.Net.UnitTest/TypeTests/StringExTests.cs
@@ -0,0 +1,115 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using S7.Net.Types;
+
+namespace S7.Net.UnitTest.TypeTests
+{
+ [TestClass]
+ public class StringExTests
+ {
+ [TestMethod]
+ public void ReadEmptyStringWithZeroByteLength()
+ {
+ AssertFromByteArrayEquals("", 0, 0);
+ }
+
+ [TestMethod]
+ public void ReadEmptyStringWithOneByteLength()
+ {
+ AssertFromByteArrayEquals("", 1, 0, 0);
+ }
+
+ [TestMethod]
+ public void ReadEmptyStringWithOneByteGarbage()
+ {
+ AssertFromByteArrayEquals("", 1, 0, (byte) 'a');
+ }
+
+ [TestMethod]
+ public void ReadA()
+ {
+ AssertFromByteArrayEquals("A", 1, 1, (byte) 'A');
+ }
+
+ [TestMethod]
+ public void ReadAbc()
+ {
+ AssertFromByteArrayEquals("Abc", 1, 3, (byte) 'A', (byte) 'b', (byte) 'c');
+ }
+
+ [TestMethod]
+ public void WriteNullWithReservedLengthZero()
+ {
+ AssertToByteArrayEquals(null, 0, 0, 0);
+ }
+
+ [TestMethod]
+ public void WriteEmptyStringWithReservedLengthZero()
+ {
+ AssertToByteArrayEquals("", 0, 0, 0);
+ }
+
+ [TestMethod]
+ public void WriteAWithReservedLengthZero()
+ {
+ AssertToByteArrayEquals("A", 0, 0, 0);
+ }
+
+ [TestMethod]
+ public void WriteNullWithReservedLengthOne()
+ {
+ AssertToByteArrayEquals(null, 1, 1, 0);
+ }
+
+ [TestMethod]
+ public void WriteEmptyStringWithReservedLengthOne()
+ {
+ AssertToByteArrayEquals("", 1, 1, 0);
+ }
+
+ [TestMethod]
+ public void WriteAWithReservedLengthOne()
+ {
+ AssertToByteArrayEquals("A", 1, 1, 1, (byte) 'A');
+ }
+
+ [TestMethod]
+ public void WriteAWithReservedLengthTwo()
+ {
+ AssertToByteArrayEquals("A", 2, 2, 1, (byte) 'A');
+ }
+
+ [TestMethod]
+ public void WriteAbcWithReservedLengthOne()
+ {
+ AssertToByteArrayEquals("Abc", 1, 1, 1, (byte) 'A');
+ }
+
+ [TestMethod]
+ public void WriteAbcWithReservedLengthTwo()
+ {
+ AssertToByteArrayEquals("Abc", 2, 2, 2, (byte) 'A', (byte) 'b');
+ }
+
+ [TestMethod]
+ public void WriteAbcWithReservedLengthThree()
+ {
+ AssertToByteArrayEquals("Abc", 3, 3, 3, (byte) 'A', (byte) 'b', (byte) 'c');
+ }
+
+ [TestMethod]
+ public void WriteAbcWithReservedLengthFour()
+ {
+ AssertToByteArrayEquals("Abc", 4, 4, 3, (byte) 'A', (byte) 'b', (byte) 'c');
+ }
+
+ private static void AssertFromByteArrayEquals(string expected, params byte[] bytes)
+ {
+ Assert.AreEqual(expected, StringEx.FromByteArray(bytes));
+ }
+
+ private static void AssertToByteArrayEquals(string value, int reservedLength, params byte[] expected)
+ {
+ CollectionAssert.AreEqual(expected, StringEx.ToByteArray(value, reservedLength));
+ }
+ }
+}
diff --git a/S7.Net/Protocol/S7WriteMultiple.cs b/S7.Net/Protocol/S7WriteMultiple.cs
index f4b2457..f5f32bd 100644
--- a/S7.Net/Protocol/S7WriteMultiple.cs
+++ b/S7.Net/Protocol/S7WriteMultiple.cs
@@ -23,7 +23,7 @@ namespace S7.Net.Protocol
foreach (var item in dataItems)
{
message.Add(Parameter.Template);
- var value = Serialization.SerializeValue(item.Value);
+ var value = Serialization.SerializeDataItem(item);
var wordLen = item.Value is bool ? 1 : 2;
message[paramOffset + Parameter.Offsets.WordLength] = (byte) wordLen;
diff --git a/S7.Net/Protocol/Serialization.cs b/S7.Net/Protocol/Serialization.cs
index acda50b..8e3c4da 100644
--- a/S7.Net/Protocol/Serialization.cs
+++ b/S7.Net/Protocol/Serialization.cs
@@ -11,6 +11,16 @@ namespace S7.Net.Protocol
return (ushort)((buf[index] << 8) + buf[index]);
}
+ public static byte[] SerializeDataItem(DataItem dataItem)
+ {
+ if (dataItem.Value is string s)
+ return dataItem.VarType == VarType.StringEx
+ ? StringEx.ToByteArray(s, dataItem.Count)
+ : Types.String.ToByteArray(s);
+
+ return SerializeValue(dataItem.Value);
+ }
+
public static byte[] SerializeValue(object value)
{
switch (value.GetType().Name)
diff --git a/S7.Net/Types/StringEx.cs b/S7.Net/Types/StringEx.cs
index e22282b..1aec9ab 100644
--- a/S7.Net/Types/StringEx.cs
+++ b/S7.Net/Types/StringEx.cs
@@ -1,4 +1,7 @@
-namespace S7.Net.Types
+using System;
+using System.Text;
+
+namespace S7.Net.Types
{
///
/// Contains the methods to convert from S7 strings to C# strings
@@ -21,6 +24,27 @@
return System.Text.Encoding.ASCII.GetString(bytes, 2, length);
}
-
+
+ ///
+ /// Converts a to S7 string with 2-byte header.
+ ///
+ /// The string to convert to byte array.
+ /// The length (in bytes) allocated in PLC for string excluding header.
+ /// A containing the string header and string value with a maximum length of + 2.
+ public static byte[] ToByteArray(string value, int reservedLength)
+ {
+ if (reservedLength > byte.MaxValue) throw new ArgumentException($"The maximum string length supported is {byte.MaxValue}.");
+
+ var length = value?.Length;
+ if (length > reservedLength) length = reservedLength;
+
+ var bytes = new byte[(length ?? 0) + 2];
+ bytes[0] = (byte) reservedLength;
+
+ if (value == null) return bytes;
+
+ bytes[1] = (byte) Encoding.ASCII.GetBytes(value, 0, length.Value, bytes, 2);
+ return bytes;
+ }
}
}