Added support for strings in Struct type class

This commit is contained in:
Mike Cremer
2021-01-24 13:56:07 +01:00
parent dfcc4c7408
commit de0a9e64dc
5 changed files with 159 additions and 14 deletions

View File

@@ -1,4 +1,5 @@

using S7.Net.Types;
namespace S7.Net.UnitTest.Helpers
{
public struct TestStruct
@@ -7,6 +8,7 @@ namespace S7.Net.UnitTest.Helpers
/// DB1.DBX0.0
/// </summary>
public bool BitVariable00;
public bool BitVariable01;
public bool BitVariable02;
public bool BitVariable03;
@@ -19,6 +21,7 @@ namespace S7.Net.UnitTest.Helpers
/// DB1.DBX1.0
/// </summary>
public bool BitVariable10;
public bool BitVariable11;
public bool BitVariable12;
public bool BitVariable13;
@@ -51,5 +54,16 @@ namespace S7.Net.UnitTest.Helpers
/// DB1.DBD16
/// </summary>
public ushort DWordVariable;
/// <summary>
/// DB1.DBX20.0
/// </summary>
[S7String(S7StringType.S7WString, 10)] public string WStringVariable;
/// <summary>
/// DB1.DBX44.0
/// </summary>
[S7String(S7StringType.S7String, 10)]
public string StringVariable;
}
}

View File

@@ -211,7 +211,9 @@ namespace S7.Net.UnitTest
IntVariable = -15000,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
DWordVariable = 850,
WStringVariable = "ÄÜÉÊéà",
StringVariable = "Hallo"
};
plc.WriteStruct(tc, DB2);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
@@ -223,6 +225,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
}
/// <summary>
@@ -739,7 +743,9 @@ namespace S7.Net.UnitTest
IntVariable = -15000,
LRealVariable = -154.789,
RealVariable = -154.789f,
DWordVariable = 850
DWordVariable = 850,
WStringVariable = "ÄÜÉÊéà",
StringVariable = "Hallo"
};
plc.WriteStruct(ts, DB2);
@@ -756,6 +762,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(ts2.LRealVariable, ts2Generic.LRealVariable);
Assert.AreEqual(ts2.RealVariable, ts2Generic.RealVariable);
Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
Assert.AreEqual(ts2.WStringVariable, ts2Generic.WStringVariable);
Assert.AreEqual(ts2.StringVariable, ts2Generic.StringVariable);
}
[TestMethod]

View File

@@ -212,6 +212,9 @@ namespace S7.Net.UnitTest
tc.LRealVariable = -154.789;
tc.RealVariable = -154.789f;
tc.DWordVariable = 850;
tc.WStringVariable = "ÄÜÉÊéà";
tc.StringVariable = "Hallo";
plc.WriteStruct(tc, DB2);
// Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
TestStruct tc2 = (TestStruct)plc.ReadStruct(typeof(TestStruct), DB2);
@@ -222,6 +225,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
}
/// <summary>
@@ -783,6 +788,8 @@ namespace S7.Net.UnitTest
ts.LRealVariable = -154.789;
ts.RealVariable = -154.789f;
ts.DWordVariable = 850;
ts.WStringVariable = "ÄÜÉÊéà";
ts.StringVariable = "Hallo";
plc.WriteStruct(ts, DB2);
@@ -797,6 +804,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(ts2.LRealVariable, ts2Generic.LRealVariable);
Assert.AreEqual(ts2.RealVariable, ts2Generic.RealVariable);
Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
Assert.AreEqual(ts2.WStringVariable, ts2Generic.WStringVariable);
Assert.AreEqual(ts2.StringVariable, ts2Generic.StringVariable);
}
[TestMethod, ExpectedException(typeof(PlcException))]

View File

@@ -0,0 +1,67 @@
using System;
namespace S7.Net.Types
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class S7StringAttribute : Attribute
{
private readonly S7StringType type;
private readonly int reservedLength;
/// <summary>
/// Initializes a new instance of the <see cref="S7StringAttribute"/> class.
/// </summary>
/// <param name="type">The string type.</param>
/// <param name="reservedLength">Reserved length of the string in characters (default value is 254).</param>
/// <exception cref="ArgumentException">Please use a valid value for the string type</exception>
public S7StringAttribute(S7StringType type, int reservedLength = 254)
{
if (!Enum.IsDefined(typeof(S7StringType), type))
throw new ArgumentException("Please use a valid value for the string type");
this.type = type;
this.reservedLength = reservedLength;
}
/// <summary>
/// Gets the type of the string.
/// </summary>
/// <value>
/// The string type.
/// </value>
public S7StringType Type => type;
/// <summary>
/// Gets the reserved length of the string in characters.
/// </summary>
/// <value>
/// The reserved length of the string in characters.
/// </value>
public int ReservedLength => reservedLength;
/// <summary>
/// Gets the reserved length in bytes.
/// </summary>
/// <value>
/// The reserved length in bytes.
/// </value>
public int ReservedLengthInBytes => type == S7StringType.S7String ? reservedLength + 2 : (reservedLength * 2) + 4;
}
/// <summary>
/// String type.
/// </summary>
public enum S7StringType
{
/// <summary>
/// ASCII string.
/// </summary>
S7String,
/// <summary>
/// Unicode string.
/// </summary>
S7WString
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Reflection;
namespace S7.Net.Types
@@ -18,11 +19,11 @@ namespace S7.Net.Types
double numBytes = 0.0;
var infos = structType
#if NETSTANDARD1_3
#if NETSTANDARD1_3
.GetTypeInfo().DeclaredFields;
#else
#else
.GetFields();
#endif
#endif
foreach (var info in infos)
{
@@ -61,6 +62,16 @@ namespace S7.Net.Types
numBytes++;
numBytes += 8;
break;
case "String":
S7StringAttribute? attribute = info.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
if (attribute == default(S7StringAttribute))
throw new ArgumentException("Please add S7StringAttribute to the field you are trying to read or write");
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += attribute.ReservedLengthInBytes;
break;
default:
numBytes += GetStructSize(info.FieldType);
break;
@@ -91,11 +102,11 @@ namespace S7.Net.Types
var infos = structValue.GetType()
#if NETSTANDARD1_3
#if NETSTANDARD1_3
.GetTypeInfo().DeclaredFields;
#else
#else
.GetFields();
#endif
#endif
foreach (var info in infos)
{
@@ -178,6 +189,32 @@ namespace S7.Net.Types
info.SetValue(structValue, LReal.FromByteArray(data));
numBytes += 8;
break;
case "String":
S7StringAttribute? attribute = info.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
if (attribute == default(S7StringAttribute))
throw new ArgumentException("Please add S7StringAttribute to the field you are trying to read or write");
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
var sData = new byte[attribute.ReservedLengthInBytes];
Array.Copy(bytes, (int)numBytes, sData, 0, sData.Length);
switch (attribute.Type)
{
case S7StringType.S7String:
info.SetValue(structValue, S7String.FromByteArray(sData));
break;
case S7StringType.S7WString:
info.SetValue(structValue, S7WString.FromByteArray(sData));
break;
default:
throw new ArgumentException("Please use a valid string type for the S7StringAttribute");
}
numBytes += sData.Length;
break;
default:
var buffer = new byte[GetStructSize(info.FieldType)];
if (buffer.Length == 0)
@@ -209,11 +246,11 @@ namespace S7.Net.Types
double numBytes = 0.0;
var infos = type
#if NETSTANDARD1_3
#if NETSTANDARD1_3
.GetTypeInfo().DeclaredFields;
#else
#else
.GetFields();
#endif
#endif
foreach (var info in infos)
{
@@ -254,6 +291,18 @@ namespace S7.Net.Types
case "Double":
bytes2 = LReal.ToByteArray((double)info.GetValue(structValue));
break;
case "String":
S7StringAttribute? attribute = info.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
if (attribute == default(S7StringAttribute))
throw new ArgumentException("Please add S7StringAttribute to the field you are trying to read or write");
bytes2 = attribute.Type switch
{
S7StringType.S7String => S7String.ToByteArray((string)info.GetValue(structValue), attribute.ReservedLength),
S7StringType.S7WString => S7WString.ToByteArray((string)info.GetValue(structValue), attribute.ReservedLength),
_ => throw new ArgumentException("Please use a valid string type for the S7StringAttribute")
};
break;
}
if (bytes2 != null)
{
@@ -269,7 +318,5 @@ namespace S7.Net.Types
}
return bytes;
}
}
}