mirror of
https://github.com/S7NetPlus/s7netplus.git
synced 2026-02-17 14:28:25 +08:00
Merge remote-tracking branch 's7netplus/develop' into fb-fixClassUint32
# Conflicts: # S7.Net/Types/Class.cs
This commit is contained in:
8
.github/workflows/test.yml
vendored
8
.github/workflows/test.yml
vendored
@@ -14,14 +14,14 @@ jobs:
|
|||||||
DOTNET_NOLOGO : 1
|
DOTNET_NOLOGO : 1
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
os: [windows-latest, ubuntu-20.04, macos-latest]
|
||||||
test-framework: [netcoreapp3.1, net5.0]
|
test-framework: [netcoreapp3.1, net5.0]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-20.04
|
||||||
test-framework: netcoreapp3.1
|
test-framework: netcoreapp3.1
|
||||||
installSnap7: true
|
installSnap7: true
|
||||||
dotnet-sdk: '3.1.x'
|
dotnet-sdk: '3.1.x'
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-20.04
|
||||||
test-framework: net5.0
|
test-framework: net5.0
|
||||||
installSnap7: true
|
installSnap7: true
|
||||||
dotnet-sdk: '5.0.x'
|
dotnet-sdk: '5.0.x'
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Install Snap7 Linux
|
- name: Install Snap7 Linux
|
||||||
if: ${{ matrix.installSnap7 && matrix.os == 'ubuntu-latest' }}
|
if: ${{ matrix.installSnap7 && matrix.os == 'ubuntu-20.04' }}
|
||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository ppa:gijzelaar/snap7
|
sudo add-apt-repository ppa:gijzelaar/snap7
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
using S7.Net.Types;
|
||||||
|
|
||||||
namespace S7.Net.UnitTest.Helpers
|
namespace S7.Net.UnitTest.Helpers
|
||||||
{
|
{
|
||||||
class TestClass
|
class TestClass
|
||||||
@@ -51,5 +53,16 @@ namespace S7.Net.UnitTest.Helpers
|
|||||||
/// DB1.DBD16
|
/// DB1.DBD16
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort DWordVariable { get; set; }
|
public ushort DWordVariable { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DB1.DBX20.0
|
||||||
|
/// </summary>
|
||||||
|
[S7String(S7StringType.S7WString, 10)]
|
||||||
|
public string WStringVariable { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// DB1.DBX44.0
|
||||||
|
/// </summary>
|
||||||
|
[S7String(S7StringType.S7String, 10)]
|
||||||
|
public string StringVariable { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using S7.Net.Types;
|
|||||||
using S7.UnitTest.Helpers;
|
using S7.UnitTest.Helpers;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -154,7 +155,9 @@ namespace S7.Net.UnitTest
|
|||||||
IntVariable = -15000,
|
IntVariable = -15000,
|
||||||
LRealVariable = -154.789,
|
LRealVariable = -154.789,
|
||||||
RealVariable = -154.789f,
|
RealVariable = -154.789f,
|
||||||
DWordVariable = 850
|
DWordVariable = 850,
|
||||||
|
WStringVariable = "ÄÜÉÊéà",
|
||||||
|
StringVariable = "Hallo"
|
||||||
};
|
};
|
||||||
|
|
||||||
await plc.WriteClassAsync(tc, DB2);
|
await plc.WriteClassAsync(tc, DB2);
|
||||||
@@ -168,6 +171,8 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
|
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
|
||||||
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
|
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
|
||||||
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
|
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
|
||||||
|
Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
|
||||||
|
Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -580,7 +585,9 @@ namespace S7.Net.UnitTest
|
|||||||
IntVariable = -15000,
|
IntVariable = -15000,
|
||||||
LRealVariable = -154.789,
|
LRealVariable = -154.789,
|
||||||
RealVariable = -154.789f,
|
RealVariable = -154.789f,
|
||||||
DWordVariable = 850
|
DWordVariable = 850,
|
||||||
|
WStringVariable = "ÄÜÉÊéà",
|
||||||
|
StringVariable = "Hallo"
|
||||||
};
|
};
|
||||||
|
|
||||||
await plc.WriteClassAsync(tc, DB2);
|
await plc.WriteClassAsync(tc, DB2);
|
||||||
@@ -628,7 +635,10 @@ namespace S7.Net.UnitTest
|
|||||||
IntVariable = -15000,
|
IntVariable = -15000,
|
||||||
LRealVariable = -154.789,
|
LRealVariable = -154.789,
|
||||||
RealVariable = -154.789f,
|
RealVariable = -154.789f,
|
||||||
DWordVariable = 850
|
DWordVariable = 850,
|
||||||
|
WStringVariable = "ÄÜÉÊéà",
|
||||||
|
StringVariable = "Hallo"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await plc.WriteClassAsync(tc, DB2);
|
await plc.WriteClassAsync(tc, DB2);
|
||||||
@@ -646,6 +656,9 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
|
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
|
||||||
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
|
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
|
||||||
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
|
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
|
||||||
|
Assert.AreEqual(tc2.WStringVariable, tc2Generic.WStringVariable);
|
||||||
|
Assert.AreEqual(tc2.StringVariable, tc2Generic.StringVariable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -671,7 +684,9 @@ namespace S7.Net.UnitTest
|
|||||||
IntVariable = -15000,
|
IntVariable = -15000,
|
||||||
LRealVariable = -154.789,
|
LRealVariable = -154.789,
|
||||||
RealVariable = -154.789f,
|
RealVariable = -154.789f,
|
||||||
DWordVariable = 850
|
DWordVariable = 850,
|
||||||
|
WStringVariable = "ÄÜÉÊéà",
|
||||||
|
StringVariable = "Hallo"
|
||||||
};
|
};
|
||||||
|
|
||||||
await plc.WriteClassAsync(tc, DB2);
|
await plc.WriteClassAsync(tc, DB2);
|
||||||
@@ -686,6 +701,8 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
|
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
|
||||||
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
|
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
|
||||||
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
|
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
|
||||||
|
Assert.AreEqual(tc2Generic.WStringVariable, tc2GenericWithClassFactory.WStringVariable);
|
||||||
|
Assert.AreEqual(tc2Generic.StringVariable, tc2GenericWithClassFactory.StringVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -792,7 +809,9 @@ namespace S7.Net.UnitTest
|
|||||||
IntVariable = -15000,
|
IntVariable = -15000,
|
||||||
LRealVariable = -154.789,
|
LRealVariable = -154.789,
|
||||||
RealVariable = -154.789f,
|
RealVariable = -154.789f,
|
||||||
DWordVariable = 850
|
DWordVariable = 850,
|
||||||
|
WStringVariable = "ÄÜÉÊéà",
|
||||||
|
StringVariable = "Hallo"
|
||||||
};
|
};
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|||||||
using S7.Net.UnitTest.Helpers;
|
using S7.Net.UnitTest.Helpers;
|
||||||
using S7.Net.Types;
|
using S7.Net.Types;
|
||||||
using S7.UnitTest.Helpers;
|
using S7.UnitTest.Helpers;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -183,6 +184,9 @@ namespace S7.Net.UnitTest
|
|||||||
tc.LRealVariable = -154.789;
|
tc.LRealVariable = -154.789;
|
||||||
tc.RealVariable = -154.789f;
|
tc.RealVariable = -154.789f;
|
||||||
tc.DWordVariable = 850;
|
tc.DWordVariable = 850;
|
||||||
|
tc.WStringVariable = "ÄÜÉÊéà";
|
||||||
|
tc.StringVariable = "Hallo";
|
||||||
|
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
TestClass tc2 = new TestClass();
|
TestClass tc2 = new TestClass();
|
||||||
// Values that are read from a class are stored inside the class itself, that is passed by reference
|
// Values that are read from a class are stored inside the class itself, that is passed by reference
|
||||||
@@ -194,6 +198,8 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
|
Assert.AreEqual(tc.LRealVariable, tc2.LRealVariable);
|
||||||
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
|
Assert.AreEqual(tc.RealVariable, tc2.RealVariable);
|
||||||
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
|
Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
|
||||||
|
Assert.AreEqual(tc.WStringVariable, tc2.WStringVariable);
|
||||||
|
Assert.AreEqual(tc.StringVariable, tc2.StringVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -577,6 +583,8 @@ namespace S7.Net.UnitTest
|
|||||||
tc.LRealVariable = -154.789;
|
tc.LRealVariable = -154.789;
|
||||||
tc.RealVariable = -154.789f;
|
tc.RealVariable = -154.789f;
|
||||||
tc.DWordVariable = 850;
|
tc.DWordVariable = 850;
|
||||||
|
tc.WStringVariable = "ÄÜÉÊéà";
|
||||||
|
tc.StringVariable = "Hallo";
|
||||||
|
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
|
|
||||||
@@ -622,6 +630,8 @@ namespace S7.Net.UnitTest
|
|||||||
tc.LRealVariable = -154.789;
|
tc.LRealVariable = -154.789;
|
||||||
tc.RealVariable = -154.789f;
|
tc.RealVariable = -154.789f;
|
||||||
tc.DWordVariable = 850;
|
tc.DWordVariable = 850;
|
||||||
|
tc.WStringVariable = "ÄÜÉÊéà";
|
||||||
|
tc.StringVariable = "Hallo";
|
||||||
|
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
|
|
||||||
@@ -637,6 +647,8 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
|
Assert.AreEqual(Math.Round(tc2.LRealVariable, 3), Math.Round(tc2Generic.LRealVariable, 3));
|
||||||
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
|
Assert.AreEqual(tc2.RealVariable, tc2Generic.RealVariable);
|
||||||
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
|
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
|
||||||
|
Assert.AreEqual(tc2.WStringVariable, tc2Generic.WStringVariable);
|
||||||
|
Assert.AreEqual(tc2.StringVariable, tc2Generic.StringVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod, ExpectedException(typeof(PlcException))]
|
[TestMethod, ExpectedException(typeof(PlcException))]
|
||||||
@@ -665,6 +677,8 @@ namespace S7.Net.UnitTest
|
|||||||
tc.LRealVariable = -154.789;
|
tc.LRealVariable = -154.789;
|
||||||
tc.RealVariable = -154.789f;
|
tc.RealVariable = -154.789f;
|
||||||
tc.DWordVariable = 850;
|
tc.DWordVariable = 850;
|
||||||
|
tc.WStringVariable = "ÄÜÉÊéà";
|
||||||
|
tc.StringVariable = "Hallo";
|
||||||
|
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
|
|
||||||
@@ -679,6 +693,8 @@ namespace S7.Net.UnitTest
|
|||||||
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
|
Assert.AreEqual(Math.Round(tc2Generic.LRealVariable, 3), Math.Round(tc2GenericWithClassFactory.LRealVariable, 3));
|
||||||
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
|
Assert.AreEqual(tc2Generic.RealVariable, tc2GenericWithClassFactory.RealVariable);
|
||||||
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
|
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
|
||||||
|
Assert.AreEqual(tc2Generic.WStringVariable, tc2GenericWithClassFactory.WStringVariable);
|
||||||
|
Assert.AreEqual(tc2Generic.StringVariable, tc2GenericWithClassFactory.StringVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod, ExpectedException(typeof(PlcException))]
|
[TestMethod, ExpectedException(typeof(PlcException))]
|
||||||
@@ -837,6 +853,9 @@ namespace S7.Net.UnitTest
|
|||||||
tc.LRealVariable = -154.789;
|
tc.LRealVariable = -154.789;
|
||||||
tc.RealVariable = -154.789f;
|
tc.RealVariable = -154.789f;
|
||||||
tc.DWordVariable = 850;
|
tc.DWordVariable = 850;
|
||||||
|
tc.WStringVariable = "ÄÜÉÊéà";
|
||||||
|
tc.StringVariable = "Hallo";
|
||||||
|
|
||||||
plc.WriteClass(tc, DB2);
|
plc.WriteClass(tc, DB2);
|
||||||
|
|
||||||
int expectedReadBytes = (int)Types.Class.GetClassSize(tc);
|
int expectedReadBytes = (int)Types.Class.GetClassSize(tc);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace S7.Net
|
|||||||
/// <returns>A task that represents the asynchronous open operation.</returns>
|
/// <returns>A task that represents the asynchronous open operation.</returns>
|
||||||
public async Task OpenAsync(CancellationToken cancellationToken = default)
|
public async Task OpenAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var stream = await ConnectAsync().ConfigureAwait(false);
|
var stream = await ConnectAsync(cancellationToken).ConfigureAwait(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await queue.Enqueue(async () =>
|
await queue.Enqueue(async () =>
|
||||||
@@ -44,11 +44,16 @@ namespace S7.Net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<NetworkStream> ConnectAsync()
|
private async Task<NetworkStream> ConnectAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
tcpClient = new TcpClient();
|
tcpClient = new TcpClient();
|
||||||
ConfigureConnection();
|
ConfigureConnection();
|
||||||
|
|
||||||
|
#if NET5_0_OR_GREATER
|
||||||
|
await tcpClient.ConnectAsync(IP, Port, cancellationToken).ConfigureAwait(false);
|
||||||
|
#else
|
||||||
await tcpClient.ConnectAsync(IP, Port).ConfigureAwait(false);
|
await tcpClient.ConnectAsync(IP, Port).ConfigureAwait(false);
|
||||||
|
#endif
|
||||||
return tcpClient.GetStream();
|
return tcpClient.GetStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net452;netstandard2.0;netstandard1.3</TargetFrameworks>
|
<TargetFrameworks>net452;netstandard2.0;netstandard1.3;net5.0</TargetFrameworks>
|
||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>Properties\S7.Net.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>Properties\S7.Net.snk</AssemblyOriginatorKeyFile>
|
||||||
<InternalsVisibleTo>S7.Net.UnitTest</InternalsVisibleTo>
|
<InternalsVisibleTo>S7.Net.UnitTest</InternalsVisibleTo>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace S7.Net.Types
|
namespace S7.Net.Types
|
||||||
{
|
{
|
||||||
@@ -25,7 +26,7 @@ namespace S7.Net.Types
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double GetIncreasedNumberOfBytes(double numBytes, Type type)
|
private static double GetIncreasedNumberOfBytes(double numBytes, Type type, PropertyInfo? propertyInfo)
|
||||||
{
|
{
|
||||||
switch (type.Name)
|
switch (type.Name)
|
||||||
{
|
{
|
||||||
@@ -38,30 +39,30 @@ namespace S7.Net.Types
|
|||||||
break;
|
break;
|
||||||
case "Int16":
|
case "Int16":
|
||||||
case "UInt16":
|
case "UInt16":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
numBytes += 2;
|
numBytes += 2;
|
||||||
break;
|
break;
|
||||||
case "Int32":
|
case "Int32":
|
||||||
case "UInt32":
|
case "UInt32":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
numBytes += 4;
|
numBytes += 4;
|
||||||
break;
|
break;
|
||||||
case "Single":
|
case "Single":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
numBytes += 4;
|
numBytes += 4;
|
||||||
break;
|
break;
|
||||||
case "Double":
|
case "Double":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
numBytes += 8;
|
numBytes += 8;
|
||||||
break;
|
break;
|
||||||
|
case "String":
|
||||||
|
S7StringAttribute? attribute = propertyInfo?.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
|
||||||
|
if (attribute == default(S7StringAttribute))
|
||||||
|
throw new ArgumentException("Please add S7StringAttribute to the string field");
|
||||||
|
|
||||||
|
IncrementToEven(ref numBytes);
|
||||||
|
numBytes += attribute.ReservedLengthInBytes;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
var propertyClass = Activator.CreateInstance(type);
|
var propertyClass = Activator.CreateInstance(type);
|
||||||
numBytes = GetClassSize(propertyClass, numBytes, true);
|
numBytes = GetClassSize(propertyClass, numBytes, true);
|
||||||
@@ -93,12 +94,12 @@ namespace S7.Net.Types
|
|||||||
IncrementToEven(ref numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
for (int i = 0; i < array.Length; i++)
|
for (int i = 0; i < array.Length; i++)
|
||||||
{
|
{
|
||||||
numBytes = GetIncreasedNumberOfBytes(numBytes, elementType);
|
numBytes = GetIncreasedNumberOfBytes(numBytes, elementType, property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
numBytes = GetIncreasedNumberOfBytes(numBytes, property.PropertyType);
|
numBytes = GetIncreasedNumberOfBytes(numBytes, property.PropertyType, property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (false == isInnerProperty)
|
if (false == isInnerProperty)
|
||||||
@@ -111,7 +112,7 @@ namespace S7.Net.Types
|
|||||||
return numBytes;
|
return numBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object? GetPropertyValue(Type propertyType, byte[] bytes, ref double numBytes)
|
private static object? GetPropertyValue(Type propertyType, PropertyInfo? propertyInfo, byte[] bytes, ref double numBytes)
|
||||||
{
|
{
|
||||||
object? value = null;
|
object? value = null;
|
||||||
|
|
||||||
@@ -133,26 +134,20 @@ namespace S7.Net.Types
|
|||||||
numBytes++;
|
numBytes++;
|
||||||
break;
|
break;
|
||||||
case "Int16":
|
case "Int16":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
// hier auswerten
|
// hier auswerten
|
||||||
ushort source = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
|
ushort source = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
|
||||||
value = source.ConvertToShort();
|
value = source.ConvertToShort();
|
||||||
numBytes += 2;
|
numBytes += 2;
|
||||||
break;
|
break;
|
||||||
case "UInt16":
|
case "UInt16":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
// hier auswerten
|
// hier auswerten
|
||||||
value = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
|
value = Word.FromBytes(bytes[(int)numBytes + 1], bytes[(int)numBytes]);
|
||||||
numBytes += 2;
|
numBytes += 2;
|
||||||
break;
|
break;
|
||||||
case "Int32":
|
case "Int32":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
var wordBuffer = new byte[4];
|
var wordBuffer = new byte[4];
|
||||||
Array.Copy(bytes, (int)numBytes, wordBuffer, 0, wordBuffer.Length);
|
Array.Copy(bytes, (int)numBytes, wordBuffer, 0, wordBuffer.Length);
|
||||||
uint sourceUInt = DWord.FromByteArray(wordBuffer);
|
uint sourceUInt = DWord.FromByteArray(wordBuffer);
|
||||||
@@ -160,18 +155,14 @@ namespace S7.Net.Types
|
|||||||
numBytes += 4;
|
numBytes += 4;
|
||||||
break;
|
break;
|
||||||
case "UInt32":
|
case "UInt32":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
var wordBuffer2 = new byte[4];
|
var wordBuffer2 = new byte[4];
|
||||||
Array.Copy(bytes, (int)numBytes, wordBuffer2, 0, wordBuffer2.Length);
|
Array.Copy(bytes, (int)numBytes, wordBuffer2, 0, wordBuffer2.Length);
|
||||||
value = DWord.FromByteArray(wordBuffer2);
|
value = DWord.FromByteArray(wordBuffer2);
|
||||||
numBytes += 4;
|
numBytes += 4;
|
||||||
break;
|
break;
|
||||||
case "Single":
|
case "Single":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
// hier auswerten
|
// hier auswerten
|
||||||
value = Real.FromByteArray(
|
value = Real.FromByteArray(
|
||||||
new byte[] {
|
new byte[] {
|
||||||
@@ -182,15 +173,31 @@ namespace S7.Net.Types
|
|||||||
numBytes += 4;
|
numBytes += 4;
|
||||||
break;
|
break;
|
||||||
case "Double":
|
case "Double":
|
||||||
numBytes = Math.Ceiling(numBytes);
|
IncrementToEven(ref numBytes);
|
||||||
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
|
|
||||||
numBytes++;
|
|
||||||
var buffer = new byte[8];
|
var buffer = new byte[8];
|
||||||
Array.Copy(bytes, (int)numBytes, buffer, 0, 8);
|
Array.Copy(bytes, (int)numBytes, buffer, 0, 8);
|
||||||
// hier auswerten
|
// hier auswerten
|
||||||
value = LReal.FromByteArray(buffer);
|
value = LReal.FromByteArray(buffer);
|
||||||
numBytes += 8;
|
numBytes += 8;
|
||||||
break;
|
break;
|
||||||
|
case "String":
|
||||||
|
S7StringAttribute? attribute = propertyInfo?.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
|
||||||
|
if (attribute == default(S7StringAttribute))
|
||||||
|
throw new ArgumentException("Please add S7StringAttribute to the string field");
|
||||||
|
|
||||||
|
IncrementToEven(ref numBytes);
|
||||||
|
|
||||||
|
// get the value
|
||||||
|
var sData = new byte[attribute.ReservedLengthInBytes];
|
||||||
|
Array.Copy(bytes, (int)numBytes, sData, 0, sData.Length);
|
||||||
|
value = attribute.Type switch
|
||||||
|
{
|
||||||
|
S7StringType.S7String => S7String.FromByteArray(sData),
|
||||||
|
S7StringType.S7WString => S7WString.FromByteArray(sData),
|
||||||
|
_ => throw new ArgumentException("Please use a valid string type for the S7StringAttribute")
|
||||||
|
};
|
||||||
|
numBytes += sData.Length;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
var propClass = Activator.CreateInstance(propertyType);
|
var propClass = Activator.CreateInstance(propertyType);
|
||||||
numBytes = FromBytes(propClass, bytes, numBytes);
|
numBytes = FromBytes(propClass, bytes, numBytes);
|
||||||
@@ -222,7 +229,7 @@ namespace S7.Net.Types
|
|||||||
for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
|
for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
|
||||||
{
|
{
|
||||||
array.SetValue(
|
array.SetValue(
|
||||||
GetPropertyValue(elementType, bytes, ref numBytes),
|
GetPropertyValue(elementType, property, bytes, ref numBytes),
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +237,7 @@ namespace S7.Net.Types
|
|||||||
{
|
{
|
||||||
property.SetValue(
|
property.SetValue(
|
||||||
sourceClass,
|
sourceClass,
|
||||||
GetPropertyValue(property.PropertyType, bytes, ref numBytes),
|
GetPropertyValue(property.PropertyType, property, bytes, ref numBytes),
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +245,7 @@ namespace S7.Net.Types
|
|||||||
return numBytes;
|
return numBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes)
|
private static double SetBytesFromProperty(object propertyValue, PropertyInfo? propertyInfo, byte[] bytes, double numBytes)
|
||||||
{
|
{
|
||||||
int bytePos = 0;
|
int bytePos = 0;
|
||||||
int bitPos = 0;
|
int bitPos = 0;
|
||||||
@@ -280,6 +287,18 @@ namespace S7.Net.Types
|
|||||||
case "Double":
|
case "Double":
|
||||||
bytes2 = LReal.ToByteArray((double)propertyValue);
|
bytes2 = LReal.ToByteArray((double)propertyValue);
|
||||||
break;
|
break;
|
||||||
|
case "String":
|
||||||
|
S7StringAttribute? attribute = propertyInfo?.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
|
||||||
|
if (attribute == default(S7StringAttribute))
|
||||||
|
throw new ArgumentException("Please add S7StringAttribute to the string field");
|
||||||
|
|
||||||
|
bytes2 = attribute.Type switch
|
||||||
|
{
|
||||||
|
S7StringType.S7String => S7String.ToByteArray((string)propertyValue, attribute.ReservedLength),
|
||||||
|
S7StringType.S7WString => S7WString.ToByteArray((string)propertyValue, attribute.ReservedLength),
|
||||||
|
_ => throw new ArgumentException("Please use a valid string type for the S7StringAttribute")
|
||||||
|
};
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
numBytes = ToBytes(propertyValue, bytes, numBytes);
|
numBytes = ToBytes(propertyValue, bytes, numBytes);
|
||||||
break;
|
break;
|
||||||
@@ -315,12 +334,12 @@ namespace S7.Net.Types
|
|||||||
Type elementType = property.PropertyType.GetElementType();
|
Type elementType = property.PropertyType.GetElementType();
|
||||||
for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
|
for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
|
||||||
{
|
{
|
||||||
numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes);
|
numBytes = SetBytesFromProperty(array.GetValue(i), property, bytes, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
numBytes = SetBytesFromProperty(property.GetValue(sourceClass, null), bytes, numBytes);
|
numBytes = SetBytesFromProperty(property.GetValue(sourceClass, null), property, bytes, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return numBytes;
|
return numBytes;
|
||||||
|
|||||||
@@ -8,7 +8,19 @@ namespace S7.Net.Types
|
|||||||
/// An S7 String has a preceeding 2 byte header containing its capacity and length
|
/// An S7 String has a preceeding 2 byte header containing its capacity and length
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class S7String
|
public static class S7String
|
||||||
{
|
{
|
||||||
|
private static Encoding stringEncoding = Encoding.ASCII;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Encoding used when serializing and deserializing S7String (Encoding.ASCII by default)
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentNullException">StringEncoding must not be null</exception>
|
||||||
|
public static Encoding StringEncoding
|
||||||
|
{
|
||||||
|
get => stringEncoding;
|
||||||
|
set => stringEncoding = value ?? throw new ArgumentNullException(nameof(StringEncoding));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts S7 bytes to a string
|
/// Converts S7 bytes to a string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -30,7 +42,7 @@ namespace S7.Net.Types
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Encoding.ASCII.GetString(bytes, 2, length);
|
return StringEncoding.GetString(bytes, 2, length);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -38,7 +50,6 @@ namespace S7.Net.Types
|
|||||||
$"Failed to parse {VarType.S7String} from data. Following fields were read: size: '{size}', actual length: '{length}', total number of bytes (including header): '{bytes.Length}'.",
|
$"Failed to parse {VarType.S7String} from data. Following fields were read: size: '{size}', actual length: '{length}', total number of bytes (including header): '{bytes.Length}'.",
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -56,7 +67,7 @@ namespace S7.Net.Types
|
|||||||
|
|
||||||
if (reservedLength > 254) throw new ArgumentException($"The maximum string length supported is 254.");
|
if (reservedLength > 254) throw new ArgumentException($"The maximum string length supported is 254.");
|
||||||
|
|
||||||
var bytes = Encoding.ASCII.GetBytes(value);
|
var bytes = StringEncoding.GetBytes(value);
|
||||||
if (bytes.Length > reservedLength) throw new ArgumentException($"The provided string length ({bytes.Length} is larger than the specified reserved length ({reservedLength}).");
|
if (bytes.Length > reservedLength) throw new ArgumentException($"The provided string length ({bytes.Length} is larger than the specified reserved length ({reservedLength}).");
|
||||||
|
|
||||||
var buffer = new byte[2 + reservedLength];
|
var buffer = new byte[2 + reservedLength];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace S7.Net.Types
|
namespace S7.Net.Types
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||||
public sealed class S7StringAttribute : Attribute
|
public sealed class S7StringAttribute : Attribute
|
||||||
{
|
{
|
||||||
private readonly S7StringType type;
|
private readonly S7StringType type;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
image: Visual Studio 2019
|
image: Visual Studio 2022
|
||||||
configuration: Release
|
configuration: Release
|
||||||
install:
|
install:
|
||||||
- choco install gitversion.portable -y
|
- choco install gitversion.portable -y
|
||||||
|
|||||||
Reference in New Issue
Block a user