diff --git a/S7.Net.UnitTest/S7NetTestsAsync.cs b/S7.Net.UnitTest/S7NetTestsAsync.cs
index 48d9ae1..0adb91b 100644
--- a/S7.Net.UnitTest/S7NetTestsAsync.cs
+++ b/S7.Net.UnitTest/S7NetTestsAsync.cs
@@ -226,10 +226,8 @@ namespace S7.Net.UnitTest
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)await plc.ReadStructAsync(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);
@@ -292,11 +290,9 @@ namespace S7.Net.UnitTest
IntVariable111 = 201
};
await plc.WriteClassAsync(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();
await plc.ReadClassAsync(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);
@@ -571,7 +567,7 @@ namespace S7.Net.UnitTest
[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
- public async Task Test_Async_ReadBytesThrowsExceptionIfPlcIsNotConnected()
+ public async Task Test_Async_ReadBytesReturnsNullIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
@@ -831,11 +827,9 @@ namespace S7.Net.UnitTest
{
double test_value = 55.66;
await plc.WriteAsync("DB1.DBD0", test_value);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Double");
var helper = await plc.ReadAsync("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Read Double");
Assert.AreEqual(test_value, test_value2, 0.01, "Compare Write/Read"); //Need delta here because S7 only has 32 bit reals
}
@@ -844,11 +838,9 @@ namespace S7.Net.UnitTest
{
float test_value = 55.6632f;
await plc.WriteAsync("DB1.DBD0", test_value);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Single");
var helper = await plc.ReadAsync("DB1.DBD0");
float test_value2 = Conversion.ConvertToFloat((uint)helper);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Read Single");
Assert.AreEqual(test_value, test_value2, "Compare Write/Read"); //No delta, datatype matches
}
diff --git a/S7.Net.UnitTest/S7NetTestsSync.cs b/S7.Net.UnitTest/S7NetTestsSync.cs
index 151b1bd..a3b01c9 100644
--- a/S7.Net.UnitTest/S7NetTestsSync.cs
+++ b/S7.Net.UnitTest/S7NetTestsSync.cs
@@ -81,8 +81,14 @@ namespace S7.Net.UnitTest
{
if (plc.IsConnected == false)
{
- var error = plc.Open();
- Assert.AreEqual(ErrorCode.NoError, error, "If you have s7 installed you must close s7oiehsx64 service.");
+ try
+ {
+ plc.Open();
+ }
+ catch (Exception e)
+ {
+ throw new Exception("If you have s7 installed you must close s7oiehsx64 service.", e);
+ }
}
}
@@ -257,10 +263,8 @@ namespace S7.Net.UnitTest
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);
@@ -321,11 +325,9 @@ namespace S7.Net.UnitTest
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);
@@ -596,19 +598,14 @@ namespace S7.Net.UnitTest
}
- [TestMethod]
- public void T13_ReadBytesReturnsEmptyArrayIfPlcIsNotConnected()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T13_ReadBytesThrowsIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
Assert.IsFalse(notConnectedPlc.IsConnected);
-
- int expectedReadBytes = 0; // 0 bytes, because no connection was established
-
TestClass tc = new TestClass();
int actualReadBytes = notConnectedPlc.ReadClass(tc, DB2);
-
- Assert.AreEqual(expectedReadBytes, actualReadBytes);
}
}
@@ -642,8 +639,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
}
- [TestMethod]
- public void T15_ReadClassWithGenericReturnsNullIfPlcIsNotConnected()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T15_ReadClassWithGenericThrowsIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
@@ -684,8 +681,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
}
- [TestMethod]
- public void T17_ReadClassWithGenericAndClassFactoryReturnsNullIfPlcIsNotConnected()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T17_ReadClassWithGenericAndClassFactoryThrowsIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
@@ -697,8 +694,8 @@ namespace S7.Net.UnitTest
}
}
- [TestMethod]
- public void T18_ReadStructReturnsNullIfPlcIsNotConnected()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T18_ReadStructThrowsIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
@@ -739,8 +736,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
}
- [TestMethod]
- public void T20_ReadStructWithGenericReturnsNullIfPlcIsNotConnected()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T20_ReadStructThrowsIfPlcIsNotConnected()
{
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{
@@ -883,11 +880,9 @@ namespace S7.Net.UnitTest
{
double test_value = 55.66;
plc.Write("DB1.DBD0", test_value);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Double");
var helper = plc.Read("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Read Double");
Assert.AreEqual(test_value, test_value2, 0.01, "Compare Write/Read"); //Need delta here because S7 only has 32 bit reals
}
@@ -929,19 +924,17 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc.Bool1, tc2.Bool1);
}
- [TestMethod]
- public void T29_Read_Write_ExceptionHandlingWhenPlcIsNotReachable()
+ [TestMethod, ExpectedException(typeof(PlcException))]
+ public void T29_Read_Write_ThrowsWhenPlcIsNotReachable()
{
// leave plc Open
S7TestServer.Stop();
double test_value = 55.66;
plc.Write("DB1.DBD0", test_value);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.WriteData, "No Write Error.");
var helper = plc.Read("DB1.DBD0");
Assert.AreEqual(helper, null, "Value in Read.");
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.ReadData, "No Read Error.");
}
[TestMethod]
@@ -949,11 +942,9 @@ namespace S7.Net.UnitTest
{
float test_value = 55.6632f;
plc.Write("DB1.DBD0", test_value);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Single");
var helper = plc.Read("DB1.DBD0");
float test_value2 = Conversion.ConvertToFloat((uint)helper);
- Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Read Single");
Assert.AreEqual(test_value, test_value2, "Compare Write/Read"); //No delta, datatype matches
}
diff --git a/S7.Net/PLC.cs b/S7.Net/PLC.cs
index 80cefba..284b81b 100644
--- a/S7.Net/PLC.cs
+++ b/S7.Net/PLC.cs
@@ -48,7 +48,15 @@ namespace S7.Net
//TODO: Fix This
get
{
- return Connect() == ErrorCode.NoError;
+ try
+ {
+ Connect();
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
}
}
@@ -72,16 +80,6 @@ namespace S7.Net
catch { return false; }
}
}
-
- ///
- /// Contains the last error registered when executing a function
- ///
- public string LastErrorString { get; private set; }
-
- ///
- /// Contains the last error code registered when executing a function
- ///
- public ErrorCode LastErrorCode { get; private set; }
///
/// Creates a PLC object with all the parameters needed for connections.
diff --git a/S7.Net/PLCHelpers.cs b/S7.Net/PLCHelpers.cs
index 2136b36..6f772a7 100644
--- a/S7.Net/PLCHelpers.cs
+++ b/S7.Net/PLCHelpers.cs
@@ -312,15 +312,6 @@ namespace S7.Net
}
}
- ///
- /// Sets the to and to .
- ///
- public void ClearLastError()
- {
- LastErrorCode = ErrorCode.NoError;
- LastErrorString = string.Empty;
- }
-
///
/// Given a S7 (Bool, Word, DWord, etc.), it returns how many bytes to read.
///
@@ -367,7 +358,7 @@ namespace S7.Net
{
// check for Return Code = Success
if (s7data[offset] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
// to Data bytes
offset += 4;
diff --git a/S7.Net/PlcAsynchronous.cs b/S7.Net/PlcAsynchronous.cs
index c829963..cde83b8 100644
--- a/S7.Net/PlcAsynchronous.cs
+++ b/S7.Net/PlcAsynchronous.cs
@@ -14,10 +14,9 @@ namespace S7.Net
public partial class Plc
{
///
- /// Open a and connects to the PLC, sending all the corrected package
- /// and returning if the connection was successful () of it was wrong.
+ /// Connects to the PLC and performs a COTP ConnectionRequest and S7 CommunicationSetup.
///
- /// Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode
+ /// A task that represents the asynchronous open operation.
public async Task OpenAsync()
{
await ConnectAsync();
@@ -227,19 +226,17 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
ParseDataIntoDataItems(s7data, dataItems);
}
catch (SocketException socketException)
{
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = socketException.Message;
+ throw new PlcException(ErrorCode.ReadData, socketException);
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = exc.Message;
+ throw new PlcException(ErrorCode.ReadData, exc);
}
return dataItems;
}
@@ -252,8 +249,8 @@ namespace S7.Net
/// Address of the memory area (if you want to read DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public async Task WriteBytesAsync(DataType dataType, int db, int startByteAdr, byte[] value)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteBytesAsync(DataType dataType, int db, int startByteAdr, byte[] value)
{
int localIndex = 0;
int count = value.Length;
@@ -263,15 +260,10 @@ namespace S7.Net
//Snap7 seems to choke on PDU sizes above 256 even if snap7
//replies with bigger PDU size in connection setup.
var maxToWrite = (int)Math.Min(count, 200);
- ErrorCode lastError = await WriteBytesWithASingleRequestAsync(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
- if (lastError != ErrorCode.NoError)
- {
- return lastError;
- }
+ await WriteBytesWithASingleRequestAsync(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
count -= maxToWrite;
localIndex += maxToWrite;
}
- return ErrorCode.NoError;
}
///
@@ -282,19 +274,13 @@ namespace S7.Net
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// The address of the bit. (0-7)
/// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{
if (bitAdr < 0 || bitAdr > 7)
throw new InvalidAddressException(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr));
- ErrorCode lastError = await WriteBitWithASingleRequestAsync(dataType, db, startByteAdr, bitAdr, value);
- if (lastError != ErrorCode.NoError)
- {
- return lastError;
- }
-
- return ErrorCode.NoError;
+ await WriteBitWithASingleRequestAsync(dataType, db, startByteAdr, bitAdr, value);
}
///
@@ -305,13 +291,13 @@ namespace S7.Net
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// The address of the bit. (0-7)
/// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
{
if (value < 0 || value > 1)
throw new ArgumentException("Value must be 0 or 1", nameof(value));
- return await WriteBitAsync(dataType, db, startByteAdr, bitAdr, value == 1);
+ await WriteBitAsync(dataType, db, startByteAdr, bitAdr, value == 1);
}
///
@@ -324,26 +310,29 @@ namespace S7.Net
/// Start byte address. If you want to read DB1.DBW200, this is 200.
/// Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.
/// The address of the bit. (0-7)
- /// NoError if it was successful, or the error is specified
- public async Task WriteAsync(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteAsync(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
{
if (bitAdr != -1)
{
//Must be writing a bit value as bitAdr is specified
if (value is bool)
{
- return await WriteBitAsync(dataType, db, startByteAdr, bitAdr, (bool)value);
+ await WriteBitAsync(dataType, db, startByteAdr, bitAdr, (bool) value);
}
else if (value is int intValue)
{
if (intValue < 0 || intValue > 7)
- throw new ArgumentOutOfRangeException(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr), nameof(bitAdr));
+ throw new ArgumentOutOfRangeException(
+ string.Format(
+ "Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid",
+ bitAdr), nameof(bitAdr));
- return await WriteBitAsync(dataType, db, startByteAdr, bitAdr, intValue == 1);
+ await WriteBitAsync(dataType, db, startByteAdr, bitAdr, intValue == 1);
}
- throw new ArgumentException("Value must be a bool or an int to write a bit", nameof(value));
+ else throw new ArgumentException("Value must be a bool or an int to write a bit", nameof(value));
}
- return await WriteBytesAsync(dataType, db, startByteAdr, Serialization.SerializeValue(value));
+ else await WriteBytesAsync(dataType, db, startByteAdr, Serialization.SerializeValue(value));
}
///
@@ -352,11 +341,11 @@ namespace S7.Net
///
/// Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
/// Value to be written to the PLC
- /// NoError if it was successful, or the error is specified
- public async Task WriteAsync(string variable, object value)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteAsync(string variable, object value)
{
var adr = new PLCAddress(variable);
- return await WriteAsync(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber);
+ await WriteAsync(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber);
}
///
@@ -365,12 +354,11 @@ namespace S7.Net
/// The struct to be written
/// Db address
/// Start bytes on the PLC
- /// NoError if it was successful, or the error is specified
- public async Task WriteStructAsync(object structValue, int db, int startByteAdr = 0)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteStructAsync(object structValue, int db, int startByteAdr = 0)
{
var bytes = Struct.ToBytes(structValue).ToList();
- var errCode = await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
- return errCode;
+ await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
}
///
@@ -379,12 +367,11 @@ namespace S7.Net
/// The class to be written
/// Db address
/// Start bytes on the PLC
- /// NoError if it was successful, or the error is specified
- public async Task WriteClassAsync(object classValue, int db, int startByteAdr = 0)
+ /// A task that represents the asynchronous write operation.
+ public async Task WriteClassAsync(object classValue, int db, int startByteAdr = 0)
{
var bytes = Types.Class.ToBytes(classValue).ToList();
- var errCode = await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
- return errCode;
+ await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
}
private async Task ReadBytesWithSingleRequestAsync(DataType dataType, int db, int startByteAdr, int count)
@@ -402,7 +389,7 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
for (int cnt = 0; cnt < count; cnt++)
bytes[cnt] = s7data[cnt + 18];
@@ -427,15 +414,14 @@ namespace S7.Net
}
///
- /// Writes up to 200 bytes to the PLC and returns NoError if successful. You must specify the memory area type, memory are address, byte start address and bytes count.
- /// If the write was not successful, check LastErrorCode or LastErrorString.
+ /// Writes up to 200 bytes to the PLC. You must specify the memory area type, memory are address, byte start address and bytes count.
///
/// Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.
/// Address of the memory area (if you want to read DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.
/// Start byte address. If you want to read DB1.DBW200, this is 200.
/// Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.
- /// NoError if it was successful, or the error is specified
- private async Task WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, byte[] value)
+ /// A task that represents the asynchronous write operation.
+ private async Task WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, byte[] value)
{
byte[] bReceive = new byte[513];
int varCount = 0;
@@ -471,27 +457,23 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
{
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
}
-
- return ErrorCode.NoError;
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = exc.Message;
- return LastErrorCode;
+ throw new PlcException(ErrorCode.WriteData, exc);
}
}
- private async Task WriteBitWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
+ private async Task WriteBitWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
{
byte[] bReceive = new byte[513];
int varCount = 0;
try
{
- var value = new[] { bitValue ? (byte)1 : (byte)0 };
+ var value = new[] {bitValue ? (byte) 1 : (byte) 0};
varCount = value.Length;
// first create the header
int packageSize = 35 + value.Length;
@@ -520,15 +502,11 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
-
- return ErrorCode.NoError;
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = exc.Message;
- return LastErrorCode;
+ throw new PlcException(ErrorCode.WriteData, exc);
}
}
}
diff --git a/S7.Net/PlcException.cs b/S7.Net/PlcException.cs
new file mode 100644
index 0000000..772060b
--- /dev/null
+++ b/S7.Net/PlcException.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace S7.Net
+{
+ #if NET_FULL
+ [Serializable]
+ #endif
+ public class PlcException : Exception
+ {
+ public ErrorCode ErrorCode { get; }
+
+ public PlcException(ErrorCode errorCode) : this(errorCode, $"PLC communication failed with error '{errorCode}'.")
+ {
+ }
+
+ public PlcException(ErrorCode errorCode, Exception innerException) : this(errorCode, innerException.Message,
+ innerException)
+ {
+ }
+
+ public PlcException(ErrorCode errorCode, string message) : base(message)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public PlcException(ErrorCode errorCode, string message, Exception inner) : base(message, inner)
+ {
+ ErrorCode = errorCode;
+ }
+
+ #if NET_FULL
+ protected PlcException(System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context) : base(info, context)
+ {
+ ErrorCode = (ErrorCode) info.GetInt32(nameof(ErrorCode));
+ }
+ #endif
+ }
+}
\ No newline at end of file
diff --git a/S7.Net/PlcSynchronous.cs b/S7.Net/PlcSynchronous.cs
index 8f1b5bc..35847a5 100644
--- a/S7.Net/PlcSynchronous.cs
+++ b/S7.Net/PlcSynchronous.cs
@@ -11,16 +11,12 @@ namespace S7.Net
public partial class Plc
{
///
- /// Open a and connects to the PLC, sending all the corrected package
- /// and returning if the connection was successful () of it was wrong.
+ /// Connects to the PLC and performs a COTP ConnectionRequest and S7 CommunicationSetup.
///
- /// Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode
- public ErrorCode Open()
+ public void Open()
{
- if (Connect() != ErrorCode.NoError)
- {
- return LastErrorCode;
- }
+ Connect();
+
try
{
stream.Write(ConnectionRequest.GetCOTPConnectionRequest(CPU, Rack, Slot), 0, 22);
@@ -41,14 +37,12 @@ namespace S7.Net
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.ConnectionError;
- LastErrorString = string.Format("Couldn't establish the connection to {0}.\nMessage: {1}", IP, exc.Message);
- return ErrorCode.ConnectionError;
+ throw new PlcException(ErrorCode.ConnectionError,
+ $"Couldn't establish the connection to {IP}.\nMessage: {exc.Message}", exc);
}
- return ErrorCode.NoError;
}
- private ErrorCode Connect()
+ private void Connect()
{
try
{
@@ -59,23 +53,15 @@ namespace S7.Net
catch (SocketException sex)
{
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
- if (sex.SocketErrorCode == SocketError.TimedOut)
- {
- LastErrorCode = ErrorCode.IPAddressNotAvailable;
- }
- else
- {
- LastErrorCode = ErrorCode.ConnectionError;
- }
-
- LastErrorString = sex.Message;
+ throw new PlcException(
+ sex.SocketErrorCode == SocketError.TimedOut
+ ? ErrorCode.IPAddressNotAvailable
+ : ErrorCode.ConnectionError, sex);
}
catch (Exception ex)
{
- LastErrorCode = ErrorCode.ConnectionError;
- LastErrorString = ex.Message;
+ throw new PlcException(ErrorCode.ConnectionError, ex);
}
- return LastErrorCode;
}
///
@@ -231,8 +217,7 @@ namespace S7.Net
/// Address of the memory area (if you want to read DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
+ public void WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
{
int localIndex = 0;
int count = value.Length;
@@ -241,16 +226,11 @@ namespace S7.Net
//TODO: Figure out how to use MaxPDUSize here
//Snap7 seems to choke on PDU sizes above 256 even if snap7
//replies with bigger PDU size in connection setup.
- var maxToWrite = (int)Math.Min(count, 200);
- ErrorCode lastError = WriteBytesWithASingleRequest(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
- if (lastError != ErrorCode.NoError)
- {
- return lastError;
- }
+ var maxToWrite = Math.Min(count, 200);
+ WriteBytesWithASingleRequest(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
count -= maxToWrite;
localIndex += maxToWrite;
}
- return ErrorCode.NoError;
}
///
@@ -261,36 +241,28 @@ namespace S7.Net
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// The address of the bit. (0-7)
/// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public ErrorCode WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
+ public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{
if (bitAdr < 0 || bitAdr > 7)
throw new InvalidAddressException(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr));
- ErrorCode lastError = WriteBitWithASingleRequest(dataType, db, startByteAdr, bitAdr, value);
- if (lastError != ErrorCode.NoError)
- {
- return lastError;
- }
-
- return ErrorCode.NoError;
+ WriteBitWithASingleRequest(dataType, db, startByteAdr, bitAdr, value);
}
///
- /// Write a single bit from a DB with the specified index.
+ /// Write a single bit to a DB with the specified index.
///
/// Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.
- /// Address of the memory area (if you want to read DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.
+ /// Address of the memory area (if you want to write DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.
/// Start byte address. If you want to write DB1.DBW200, this is 200.
/// The address of the bit. (0-7)
- /// Bytes to write. If more than 200, multiple requests will be made.
- /// NoError if it was successful, or the error is specified
- public ErrorCode WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
+ /// Value to write (0 or 1).
+ public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
{
if (value < 0 || value > 1)
throw new ArgumentException("Value must be 0 or 1", nameof(value));
- return WriteBit(dataType, db, startByteAdr, bitAdr, value == 1);
+ WriteBit(dataType, db, startByteAdr, bitAdr, value == 1);
}
///
@@ -303,26 +275,29 @@ namespace S7.Net
/// Start byte address. If you want to read DB1.DBW200, this is 200.
/// Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.
/// The address of the bit. (0-7)
- /// NoError if it was successful, or the error is specified
- public ErrorCode Write(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
+ public void Write(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
{
if (bitAdr != -1)
{
//Must be writing a bit value as bitAdr is specified
if (value is bool)
{
- return WriteBit(dataType, db, startByteAdr, bitAdr, (bool)value);
+ WriteBit(dataType, db, startByteAdr, bitAdr, (bool) value);
}
else if (value is int intValue)
{
if (intValue < 0 || intValue > 7)
- throw new ArgumentOutOfRangeException(string.Format("Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid", bitAdr), nameof(bitAdr));
+ throw new ArgumentOutOfRangeException(
+ string.Format(
+ "Addressing Error: You can only reference bitwise locations 0-7. Address {0} is invalid",
+ bitAdr), nameof(bitAdr));
- return WriteBit(dataType, db, startByteAdr, bitAdr, intValue == 1);
+ WriteBit(dataType, db, startByteAdr, bitAdr, intValue == 1);
}
- throw new ArgumentException("Value must be a bool or an int to write a bit", nameof(value));
+ else
+ throw new ArgumentException("Value must be a bool or an int to write a bit", nameof(value));
}
- return WriteBytes(dataType, db, startByteAdr, Serialization.SerializeValue(value));
+ else WriteBytes(dataType, db, startByteAdr, Serialization.SerializeValue(value));
}
///
@@ -331,11 +306,10 @@ namespace S7.Net
///
/// Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
/// Value to be written to the PLC
- /// NoError if it was successful, or the error is specified
- public ErrorCode Write(string variable, object value)
+ public void Write(string variable, object value)
{
var adr = new PLCAddress(variable);
- return Write(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber);
+ Write(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber);
}
///
@@ -344,10 +318,9 @@ namespace S7.Net
/// The struct to be written
/// Db address
/// Start bytes on the PLC
- /// NoError if it was successful, or the error is specified
- public ErrorCode WriteStruct(object structValue, int db, int startByteAdr = 0)
+ public void WriteStruct(object structValue, int db, int startByteAdr = 0)
{
- return WriteStructAsync(structValue, db, startByteAdr).Result;
+ WriteStructAsync(structValue, db, startByteAdr).GetAwaiter().GetResult();
}
///
@@ -356,10 +329,9 @@ namespace S7.Net
/// The class to be written
/// Db address
/// Start bytes on the PLC
- /// NoError if it was successful, or the error is specified
- public ErrorCode WriteClass(object classValue, int db, int startByteAdr = 0)
+ public void WriteClass(object classValue, int db, int startByteAdr = 0)
{
- return WriteClassAsync(classValue, db, startByteAdr).Result;
+ WriteClassAsync(classValue, db, startByteAdr).GetAwaiter().GetResult();
}
private byte[] ReadBytesWithSingleRequest(DataType dataType, int db, int startByteAdr, int count)
@@ -378,24 +350,16 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
for (int cnt = 0; cnt < count; cnt++)
bytes[cnt] = s7data[cnt + 18];
return bytes;
}
- catch (SocketException socketException)
- {
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = socketException.Message;
- return null;
- }
catch (Exception exc)
{
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = exc.Message;
- return null;
+ throw new PlcException(ErrorCode.ReadData, exc);
}
}
@@ -414,7 +378,7 @@ namespace S7.Net
S7WriteMultiple.ParseResponse(response, response.Length, dataItems);
}
- private ErrorCode WriteBytesWithASingleRequest(DataType dataType, int db, int startByteAdr, byte[] value)
+ private void WriteBytesWithASingleRequest(DataType dataType, int db, int startByteAdr, byte[] value)
{
int varCount = 0;
try
@@ -448,26 +412,22 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
{
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
}
-
- return ErrorCode.NoError;
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = exc.Message;
- return LastErrorCode;
+ throw new PlcException(ErrorCode.WriteData, exc);
}
}
- private ErrorCode WriteBitWithASingleRequest(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
+ private void WriteBitWithASingleRequest(DataType dataType, int db, int startByteAdr, int bitAdr, bool bitValue)
{
int varCount = 0;
try
{
- var value = new[] { bitValue ? (byte)1 : (byte)0 };
+ var value = new[] {bitValue ? (byte) 1 : (byte) 0};
varCount = value.Length;
// first create the header
int packageSize = 35 + value.Length;
@@ -496,15 +456,11 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
-
- return ErrorCode.NoError;
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
}
catch (Exception exc)
{
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = exc.Message;
- return LastErrorCode;
+ throw new PlcException(ErrorCode.WriteData, exc);
}
}
@@ -531,7 +487,7 @@ namespace S7.Net
{
// first create the header
int packageSize = 19 + (dataItems.Count * 12);
- Types.ByteArray package = new ByteArray(packageSize);
+ ByteArray package = new ByteArray(packageSize);
package.Add(ReadHeaderPackage(dataItems.Count));
// package.Add(0x02); // datenart
foreach (var dataItem in dataItems)
@@ -543,19 +499,13 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff)
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
ParseDataIntoDataItems(s7data, dataItems);
}
- catch (SocketException socketException)
- {
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = socketException.Message;
- }
catch (Exception exc)
{
- LastErrorCode = ErrorCode.ReadData;
- LastErrorString = exc.Message;
+ throw new PlcException(ErrorCode.ReadData, exc);
}
}
}