Skip to content

Commit

Permalink
Merge branch 'develop' into cleanupOpen
Browse files Browse the repository at this point in the history
  • Loading branch information
mycroes authored Sep 21, 2020
2 parents 33981ab + de87409 commit 2bcc5e6
Show file tree
Hide file tree
Showing 22 changed files with 206 additions and 152 deletions.
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ to my request for committing code, I decided to pick up where he left off here o
## Documentation
Check the Wiki and feel free to edit it: https://github.com/killnine/s7netplus/wiki

S7.Net Plus has a [User Manual](https://github.com/killnine/s7netplus/blob/master/Documentation/Documentation.pdf), check it out.

## Supported PLC

+ Compatible S7 PLC (S7-200, S7-300, S7-400, S7-1200, S7-1500)
Expand All @@ -36,6 +34,5 @@ PM> Install-Package S7netplus

## Running the tests

Unit tests use Snap7 server, so port 102 must be not in use.
If you have Siemens Step7 installed, the service s7oiehsx64 is stopped when running unit tests.
You have to restart the service manually if you need it.
Unit tests use Snap7 server.
On Windows, the DLL is included with the test project. On other platforms, Snap7 must be installed manually before running tests.
9 changes: 8 additions & 1 deletion S7.Net.UnitTest/Helpers/S7TestServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static void ReadEventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int S
Console.WriteLine(Server.EventText(ref Event));
}

public static void Start()
public static void Start(short port)
{
Server = new S7Server();
// Share some resources with our virtual PLC
Expand Down Expand Up @@ -59,7 +59,14 @@ public static void Start()
// Start the server onto the default adapter.
// To select an adapter we have to use Server->StartTo("192.168.x.y").
// Start() is the same of StartTo("0.0.0.0");

Server.SetParam(S7Consts.p_u16_LocalPort, ref port);

int Error = Server.Start();
if (Error != 0)
{
throw new Exception($"Error starting Snap7 server: {Server.ErrorText(Error)}");
}
//if (Error == 0)
//{
// // Now the server is running ... wait a key to terminate
Expand Down
30 changes: 29 additions & 1 deletion S7.Net.UnitTest/ProtocolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@

using System.IO;
using System.Threading.Tasks;
using S7.Net.Protocol;
using System.Collections;

namespace S7.Net.UnitTest
{
[TestClass]
public class ProtocolUnitTest
{
private TestContext TestContext { get; set; }
public TestContext TestContext { get; set; }

[TestMethod]
public async Task TPKT_Read()
Expand Down Expand Up @@ -64,6 +66,32 @@ public static byte[] StringToByteArray(string hex)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}


[TestMethod]
public void TestResponseCode()
{
var expected = StringToByteArray("320700000400000800080001120411440100ff09000400000000");
var m = new MemoryStream(StringToByteArray("0300000702f0000300000702f0000300002102f080320700000400000800080001120411440100ff09000400000000"));
var t = COTP.TSDU.Read(m);
Assert.IsTrue(expected.SequenceEqual(t));


// Test all possible byte values. Everything except 0xff should throw an exception.
var testData = Enumerable.Range(0, 256).Select(i => new { StatusCode = (ReadWriteErrorCode)i, ThrowsException = i != (byte)ReadWriteErrorCode.Success });

foreach (var entry in testData)
{
if (entry.ThrowsException)
{
Assert.ThrowsException<Exception>(() => Plc.ValidateResponseCode(entry.StatusCode));
}
else
{
Plc.ValidateResponseCode(entry.StatusCode);
}
}
}
}

}
13 changes: 5 additions & 8 deletions S7.Net.UnitTest/S7.Net.UnitTest.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452</TargetFrameworks>
<TargetFrameworks>net452;netcoreapp3.1</TargetFrameworks>

<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\S7.Net.snk</AssemblyOriginatorKeyFile>
<IsPackable>false</IsPackable>
<Copyright>Copyright © 2014</Copyright>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GitHubActionsTestLogger" Version="1.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
Expand All @@ -24,13 +26,8 @@
</ItemGroup>

<ItemGroup>
<Reference Include="System.ServiceProcess" />
</ItemGroup>

<ItemGroup>
<None Update="snap7.dll">
<None Update="runtimes\win-x64\native\snap7.dll" Link="snap7.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
4 changes: 0 additions & 4 deletions S7.Net.UnitTest/S7NetTestsAsync.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#region Using
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using S7.Net;
using S7.Net.UnitTest.Helpers;
using S7.Net.UnitTest;
using System.ServiceProcess;
using S7.Net.Types;
using S7.UnitTest.Helpers;
using System.Threading.Tasks;
Expand Down
33 changes: 11 additions & 22 deletions S7.Net.UnitTest/S7NetTestsSync.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#region Using
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using S7.Net;
using S7.Net.UnitTest.Helpers;
using S7.Net.UnitTest;
using System.ServiceProcess;
using S7.Net.Types;
using S7.UnitTest.Helpers;

Expand Down Expand Up @@ -41,6 +37,8 @@ public partial class S7NetTests : IDisposable
#region Constants
const int DB2 = 2;
const int DB4 = 4;
const short TestServerPort = 31122;
const string TestServerIp = "127.0.0.1";
#endregion

#region Private fields
Expand All @@ -53,16 +51,19 @@ public partial class S7NetTests : IDisposable
/// </summary>
public S7NetTests()
{
plc = new Plc(CpuType.S7300, "127.0.0.1", 0, 2);
//ConsoleManager.Show();
ShutDownServiceS7oiehsx64();
plc = CreatePlc();

}

private static Plc CreatePlc()
{
return new Plc(CpuType.S7300, TestServerIp, TestServerPort, 0, 2);
}

[TestInitialize]
public void Setup()
{
S7TestServer.Start();
S7TestServer.Start(TestServerPort);
plc.Open();
}

Expand Down Expand Up @@ -931,9 +932,9 @@ public void T25_IsAvailableReturnsTrueIfIPAddressIsReachable()
{
plc.Close();
S7TestServer.Stop();
S7TestServer.Start();
S7TestServer.Start(TestServerPort);

var reachablePlc = new Plc(CpuType.S7300, "127.0.0.1", 0, 2);
var reachablePlc = CreatePlc();
Assert.IsTrue(reachablePlc.IsAvailable);
}

Expand Down Expand Up @@ -1026,18 +1027,6 @@ public void T33_ReadWriteDateTimeLong()
#endregion

#region Private methods
private static void ShutDownServiceS7oiehsx64()
{
ServiceController[] services = ServiceController.GetServices();
var service = services.FirstOrDefault(s => s.ServiceName == "s7oiehsx64");
if (service != null)
{
if (service.Status == ServiceControllerStatus.Running)
{
service.Stop();
}
}
}

#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
Expand Down
7 changes: 2 additions & 5 deletions S7.Net.UnitTest/Snap7/snap7.net.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ namespace Snap7

public class S7Consts
{
#if __MonoCS__ // Assuming that we are using Unix release of Mono (otherwise modify it)
public const string Snap7LibName = "libsnap7.so";
#else
public const string Snap7LibName = "snap7.dll";
#endif
public const string Snap7LibName = "snap7";

//------------------------------------------------------------------------------
// PARAMS LIST
//------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion S7.Net.UnitTest/StreamTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public override void Write(byte[] buffer, int offset, int count)
[TestClass]
public class StreamTests
{
private TestContext TestContext { get; set; }
public TestContext TestContext { get; set; }

[TestMethod]
public async Task TPKT_ReadRestrictedStreamAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace S7.Net.UnitTest.TypeTests
{
[TestClass]
public class StringExTests
public class S7StringTests
{
[TestMethod]
public void ReadEmptyStringWithZeroByteLength()
Expand Down Expand Up @@ -36,7 +36,7 @@ public void ReadMalformedStringTooShort()
[TestMethod]
public void ReadMalformedStringSizeLargerThanCapacity()
{
Assert.ThrowsException<PlcException>(() => StringEx.FromByteArray(new byte[] { 3, 5, 0, 1, 2 }));
Assert.ThrowsException<PlcException>(() => S7String.FromByteArray(new byte[] { 3, 5, 0, 1, 2 }));
}

[TestMethod]
Expand Down Expand Up @@ -102,7 +102,7 @@ public void WriteAWithReservedLengthTwo()
[TestMethod]
public void WriteAbcWithStringLargetThanReservedLength()
{
Assert.ThrowsException<ArgumentException>(() => StringEx.ToByteArray("Abc", 2));
Assert.ThrowsException<ArgumentException>(() => S7String.ToByteArray("Abc", 2));
}

[TestMethod]
Expand All @@ -119,16 +119,16 @@ public void WriteAbcWithReservedLengthFour()

private static void AssertFromByteArrayEquals(string expected, params byte[] bytes)
{
var convertedString = StringEx.FromByteArray(bytes);
var convertedString = S7String.FromByteArray(bytes);
Assert.AreEqual(expected, convertedString);
}


private static void AssertToByteArrayAndBackEquals(string value, int reservedLength, params byte[] expected)
{
var convertedData = StringEx.ToByteArray(value, reservedLength);
var convertedData = S7String.ToByteArray(value, reservedLength);
CollectionAssert.AreEqual(expected, convertedData);
var convertedBack = StringEx.FromByteArray(convertedData);
var convertedBack = S7String.FromByteArray(convertedData);
Assert.AreEqual(value, convertedBack);
}
}
Expand Down
Binary file not shown.
Binary file removed S7.Net.UnitTest/snap7.dll
Binary file not shown.
6 changes: 3 additions & 3 deletions S7.Net/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,14 @@ public enum VarType
LReal,

/// <summary>
/// String variable type (variable)
/// Char Array / C-String variable type (variable)
/// </summary>
String,

/// <summary>
/// String variable type (variable)
/// S7 String variable type (variable)
/// </summary>
StringEx,
S7String,

/// <summary>
/// Timer variable type
Expand Down
32 changes: 27 additions & 5 deletions S7.Net/PLC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using S7.Net.Protocol;
using S7.Net.Types;


Expand All @@ -18,8 +19,8 @@ public partial class Plc : IDisposable
private TcpClient? tcpClient;
private NetworkStream? _stream;

private int readTimeout = System.Threading.Timeout.Infinite;
private int writeTimeout = System.Threading.Timeout.Infinite;
private int readTimeout = 0; // default no timeout
private int writeTimeout = 0; // default no timeout

/// <summary>
/// IP address of the PLC
Expand Down Expand Up @@ -234,13 +235,34 @@ PlcException NotEnoughBytes() =>

if (s7Data.Length < 15) throw NotEnoughBytes();

if (s7Data[14] != 0xff)
throw new PlcException(ErrorCode.ReadData,
$"Invalid response from PLC: '{BitConverter.ToString(s7Data)}'.");
ValidateResponseCode((ReadWriteErrorCode)s7Data[14]);

if (s7Data.Length < expectedLength) throw NotEnoughBytes();
}

internal static void ValidateResponseCode(ReadWriteErrorCode statusCode)
{
switch (statusCode)
{
case ReadWriteErrorCode.ObjectDoesNotExist:
throw new Exception("Received error from PLC: Object does not exist.");
case ReadWriteErrorCode.DataTypeInconsistent:
throw new Exception("Received error from PLC: Data type inconsistent.");
case ReadWriteErrorCode.DataTypeNotSupported:
throw new Exception("Received error from PLC: Data type not supported.");
case ReadWriteErrorCode.AccessingObjectNotAllowed:
throw new Exception("Received error from PLC: Accessing object not allowed.");
case ReadWriteErrorCode.AddressOutOfRange:
throw new Exception("Received error from PLC: Address out of range.");
case ReadWriteErrorCode.HardwareFault:
throw new Exception("Received error from PLC: Hardware fault.");
case ReadWriteErrorCode.Success:
break;
default:
throw new Exception( $"Invalid response from PLC: statusCode={(byte)statusCode}.");
}
}

#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls

Expand Down
6 changes: 3 additions & 3 deletions S7.Net/PLCHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ private void BuildReadDataRequestPackage(System.IO.MemoryStream stream, DataType

case VarType.String:
return Types.String.FromByteArray(bytes);
case VarType.StringEx:
return StringEx.FromByteArray(bytes);
case VarType.S7String:
return S7String.FromByteArray(bytes);

case VarType.Timer:
if (varCount == 1)
Expand Down Expand Up @@ -186,7 +186,7 @@ private int VarTypeToByteLength(VarType varType, int varCount = 1)
return (varCount < 1) ? 1 : varCount;
case VarType.String:
return varCount;
case VarType.StringEx:
case VarType.S7String:
return varCount + 2;
case VarType.Word:
case VarType.Timer:
Expand Down
Loading

0 comments on commit 2bcc5e6

Please sign in to comment.