Replace LastErrorCode and LastErrorString with exceptions

This commit is contained in:
Michael Croes
2018-07-07 13:36:16 +02:00
parent ff7e13cd49
commit 1538de148b
7 changed files with 163 additions and 224 deletions

View File

@@ -226,10 +226,8 @@ namespace S7.Net.UnitTest
IntVariable111 = 201 IntVariable111 = 201
}; };
plc.WriteStruct(tc, DB2); 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 // 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); TestLongStruct tc2 = (TestLongStruct)await plc.ReadStructAsync(typeof(TestLongStruct), DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0); Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1); Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10); Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
@@ -292,11 +290,9 @@ namespace S7.Net.UnitTest
IntVariable111 = 201 IntVariable111 = 201
}; };
await plc.WriteClassAsync(tc, DB2); 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 // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
TestLongClass tc2 = new TestLongClass(); TestLongClass tc2 = new TestLongClass();
await plc.ReadClassAsync(tc2, DB2); await plc.ReadClassAsync(tc2, DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0); Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1); Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10); Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
@@ -571,7 +567,7 @@ namespace S7.Net.UnitTest
[TestMethod] [TestMethod]
[ExpectedException(typeof(NullReferenceException))] [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)) 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; double test_value = 55.66;
await plc.WriteAsync("DB1.DBD0", test_value); await plc.WriteAsync("DB1.DBD0", test_value);
Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Double");
var helper = await plc.ReadAsync("DB1.DBD0"); var helper = await plc.ReadAsync("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper); 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 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; float test_value = 55.6632f;
await plc.WriteAsync("DB1.DBD0", test_value); await plc.WriteAsync("DB1.DBD0", test_value);
Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Single");
var helper = await plc.ReadAsync("DB1.DBD0"); var helper = await plc.ReadAsync("DB1.DBD0");
float test_value2 = Conversion.ConvertToFloat((uint)helper); 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 Assert.AreEqual(test_value, test_value2, "Compare Write/Read"); //No delta, datatype matches
} }

View File

@@ -81,8 +81,14 @@ namespace S7.Net.UnitTest
{ {
if (plc.IsConnected == false) if (plc.IsConnected == false)
{ {
var error = plc.Open(); try
Assert.AreEqual(ErrorCode.NoError, error, "If you have s7 installed you must close s7oiehsx64 service."); {
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.IntVariable110 = 200;
tc.IntVariable111 = 201; tc.IntVariable111 = 201;
plc.WriteStruct(tc, DB2); 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 // 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); TestLongStruct tc2 = (TestLongStruct)plc.ReadStruct(typeof(TestLongStruct), DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0); Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1); Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10); Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
@@ -321,11 +325,9 @@ namespace S7.Net.UnitTest
tc.IntVariable110 = 200; tc.IntVariable110 = 200;
tc.IntVariable111 = 201; tc.IntVariable111 = 201;
plc.WriteClass(tc, DB2); 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 // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
TestLongClass tc2 = new TestLongClass(); TestLongClass tc2 = new TestLongClass();
plc.ReadClass(tc2, DB2); plc.ReadClass(tc2, DB2);
Assert.AreEqual(ErrorCode.NoError, plc.LastErrorCode);
Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0); Assert.AreEqual(tc.IntVariable0, tc2.IntVariable0);
Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1); Assert.AreEqual(tc.IntVariable1, tc2.IntVariable1);
Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10); Assert.AreEqual(tc.IntVariable10, tc2.IntVariable10);
@@ -596,19 +598,14 @@ namespace S7.Net.UnitTest
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T13_ReadBytesReturnsEmptyArrayIfPlcIsNotConnected() public void T13_ReadBytesThrowsIfPlcIsNotConnected()
{ {
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0)) using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{ {
Assert.IsFalse(notConnectedPlc.IsConnected); Assert.IsFalse(notConnectedPlc.IsConnected);
int expectedReadBytes = 0; // 0 bytes, because no connection was established
TestClass tc = new TestClass(); TestClass tc = new TestClass();
int actualReadBytes = notConnectedPlc.ReadClass(tc, DB2); int actualReadBytes = notConnectedPlc.ReadClass(tc, DB2);
Assert.AreEqual(expectedReadBytes, actualReadBytes);
} }
} }
@@ -642,8 +639,8 @@ namespace S7.Net.UnitTest
Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable); Assert.AreEqual(tc2.DWordVariable, tc2Generic.DWordVariable);
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T15_ReadClassWithGenericReturnsNullIfPlcIsNotConnected() public void T15_ReadClassWithGenericThrowsIfPlcIsNotConnected()
{ {
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0)) 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); Assert.AreEqual(tc2Generic.DWordVariable, tc2GenericWithClassFactory.DWordVariable);
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T17_ReadClassWithGenericAndClassFactoryReturnsNullIfPlcIsNotConnected() public void T17_ReadClassWithGenericAndClassFactoryThrowsIfPlcIsNotConnected()
{ {
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0)) using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0))
{ {
@@ -697,8 +694,8 @@ namespace S7.Net.UnitTest
} }
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T18_ReadStructReturnsNullIfPlcIsNotConnected() public void T18_ReadStructThrowsIfPlcIsNotConnected()
{ {
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0)) 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); Assert.AreEqual(ts2.DWordVariable, ts2Generic.DWordVariable);
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T20_ReadStructWithGenericReturnsNullIfPlcIsNotConnected() public void T20_ReadStructThrowsIfPlcIsNotConnected()
{ {
using (var notConnectedPlc = new Plc(CpuType.S7300, "255.255.255.255", 0, 0)) 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; double test_value = 55.66;
plc.Write("DB1.DBD0", test_value); plc.Write("DB1.DBD0", test_value);
Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Double");
var helper = plc.Read("DB1.DBD0"); var helper = plc.Read("DB1.DBD0");
double test_value2 = Conversion.ConvertToDouble((uint)helper); 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 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); Assert.AreEqual(tc.Bool1, tc2.Bool1);
} }
[TestMethod] [TestMethod, ExpectedException(typeof(PlcException))]
public void T29_Read_Write_ExceptionHandlingWhenPlcIsNotReachable() public void T29_Read_Write_ThrowsWhenPlcIsNotReachable()
{ {
// leave plc Open // leave plc Open
S7TestServer.Stop(); S7TestServer.Stop();
double test_value = 55.66; double test_value = 55.66;
plc.Write("DB1.DBD0", test_value); plc.Write("DB1.DBD0", test_value);
Assert.AreEqual(plc.LastErrorCode, ErrorCode.WriteData, "No Write Error.");
var helper = plc.Read("DB1.DBD0"); var helper = plc.Read("DB1.DBD0");
Assert.AreEqual(helper, null, "Value in Read."); Assert.AreEqual(helper, null, "Value in Read.");
Assert.AreEqual(plc.LastErrorCode, ErrorCode.ReadData, "No Read Error.");
} }
[TestMethod] [TestMethod]
@@ -949,11 +942,9 @@ namespace S7.Net.UnitTest
{ {
float test_value = 55.6632f; float test_value = 55.6632f;
plc.Write("DB1.DBD0", test_value); plc.Write("DB1.DBD0", test_value);
Assert.AreEqual(plc.LastErrorCode, ErrorCode.NoError, "Write Single");
var helper = plc.Read("DB1.DBD0"); var helper = plc.Read("DB1.DBD0");
float test_value2 = Conversion.ConvertToFloat((uint)helper); 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 Assert.AreEqual(test_value, test_value2, "Compare Write/Read"); //No delta, datatype matches
} }

View File

@@ -48,7 +48,15 @@ namespace S7.Net
//TODO: Fix This //TODO: Fix This
get get
{ {
return Connect() == ErrorCode.NoError; try
{
Connect();
return true;
}
catch
{
return false;
}
} }
} }
@@ -72,16 +80,6 @@ namespace S7.Net
catch { return false; } catch { return false; }
} }
} }
/// <summary>
/// Contains the last error registered when executing a function
/// </summary>
public string LastErrorString { get; private set; }
/// <summary>
/// Contains the last error code registered when executing a function
/// </summary>
public ErrorCode LastErrorCode { get; private set; }
/// <summary> /// <summary>
/// Creates a PLC object with all the parameters needed for connections. /// Creates a PLC object with all the parameters needed for connections.

View File

@@ -312,15 +312,6 @@ namespace S7.Net
} }
} }
/// <summary>
/// Sets the <see cref="LastErrorCode"/> to <see cref="ErrorCode.NoError"/> and <see cref="LastErrorString"/> to <see cref="string.Empty"/>.
/// </summary>
public void ClearLastError()
{
LastErrorCode = ErrorCode.NoError;
LastErrorString = string.Empty;
}
/// <summary> /// <summary>
/// Given a S7 <see cref="VarType"/> (Bool, Word, DWord, etc.), it returns how many bytes to read. /// Given a S7 <see cref="VarType"/> (Bool, Word, DWord, etc.), it returns how many bytes to read.
/// </summary> /// </summary>
@@ -367,7 +358,7 @@ namespace S7.Net
{ {
// check for Return Code = Success // check for Return Code = Success
if (s7data[offset] != 0xff) if (s7data[offset] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
// to Data bytes // to Data bytes
offset += 4; offset += 4;

View File

@@ -14,10 +14,9 @@ namespace S7.Net
public partial class Plc public partial class Plc
{ {
/// <summary> /// <summary>
/// Open a <see cref="Socket"/> and connects to the PLC, sending all the corrected package /// Connects to the PLC and performs a COTP ConnectionRequest and S7 CommunicationSetup.
/// and returning if the connection was successful (<see cref="ErrorCode.NoError"/>) of it was wrong.
/// </summary> /// </summary>
/// <returns>Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode</returns> /// <returns>A task that represents the asynchronous open operation.</returns>
public async Task OpenAsync() public async Task OpenAsync()
{ {
await ConnectAsync(); await ConnectAsync();
@@ -227,19 +226,17 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream); //TODO use Async var s7data = await COTP.TSDU.ReadAsync(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
ParseDataIntoDataItems(s7data, dataItems); ParseDataIntoDataItems(s7data, dataItems);
} }
catch (SocketException socketException) catch (SocketException socketException)
{ {
LastErrorCode = ErrorCode.ReadData; throw new PlcException(ErrorCode.ReadData, socketException);
LastErrorString = socketException.Message;
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.ReadData; throw new PlcException(ErrorCode.ReadData, exc);
LastErrorString = exc.Message;
} }
return dataItems; return dataItems;
} }
@@ -252,8 +249,8 @@ namespace S7.Net
/// <param name="db">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.</param> /// <param name="db">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.</param>
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteBytesAsync(DataType dataType, int db, int startByteAdr, byte[] value) public async Task WriteBytesAsync(DataType dataType, int db, int startByteAdr, byte[] value)
{ {
int localIndex = 0; int localIndex = 0;
int count = value.Length; int count = value.Length;
@@ -263,15 +260,10 @@ namespace S7.Net
//Snap7 seems to choke on PDU sizes above 256 even if snap7 //Snap7 seems to choke on PDU sizes above 256 even if snap7
//replies with bigger PDU size in connection setup. //replies with bigger PDU size in connection setup.
var maxToWrite = (int)Math.Min(count, 200); var maxToWrite = (int)Math.Min(count, 200);
ErrorCode lastError = await WriteBytesWithASingleRequestAsync(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray()); await WriteBytesWithASingleRequestAsync(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
if (lastError != ErrorCode.NoError)
{
return lastError;
}
count -= maxToWrite; count -= maxToWrite;
localIndex += maxToWrite; localIndex += maxToWrite;
} }
return ErrorCode.NoError;
} }
/// <summary> /// <summary>
@@ -282,19 +274,13 @@ namespace S7.Net
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool value) public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{ {
if (bitAdr < 0 || bitAdr > 7) 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)); 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); await WriteBitWithASingleRequestAsync(dataType, db, startByteAdr, bitAdr, value);
if (lastError != ErrorCode.NoError)
{
return lastError;
}
return ErrorCode.NoError;
} }
/// <summary> /// <summary>
@@ -305,13 +291,13 @@ namespace S7.Net
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, int value) public async Task WriteBitAsync(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
{ {
if (value < 0 || value > 1) if (value < 0 || value > 1)
throw new ArgumentException("Value must be 0 or 1", nameof(value)); 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);
} }
/// <summary> /// <summary>
@@ -324,26 +310,29 @@ namespace S7.Net
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
/// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param> /// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteAsync(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1) public async Task WriteAsync(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
{ {
if (bitAdr != -1) if (bitAdr != -1)
{ {
//Must be writing a bit value as bitAdr is specified //Must be writing a bit value as bitAdr is specified
if (value is bool) 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) else if (value is int intValue)
{ {
if (intValue < 0 || intValue > 7) 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));
} }
/// <summary> /// <summary>
@@ -352,11 +341,11 @@ namespace S7.Net
/// </summary> /// </summary>
/// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param> /// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
/// <param name="value">Value to be written to the PLC</param> /// <param name="value">Value to be written to the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteAsync(string variable, object value) public async Task WriteAsync(string variable, object value)
{ {
var adr = new PLCAddress(variable); 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);
} }
/// <summary> /// <summary>
@@ -365,12 +354,11 @@ namespace S7.Net
/// <param name="structValue">The struct to be written</param> /// <param name="structValue">The struct to be written</param>
/// <param name="db">Db address</param> /// <param name="db">Db address</param>
/// <param name="startByteAdr">Start bytes on the PLC</param> /// <param name="startByteAdr">Start bytes on the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteStructAsync(object structValue, int db, int startByteAdr = 0) public async Task WriteStructAsync(object structValue, int db, int startByteAdr = 0)
{ {
var bytes = Struct.ToBytes(structValue).ToList(); var bytes = Struct.ToBytes(structValue).ToList();
var errCode = await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray()); await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
return errCode;
} }
/// <summary> /// <summary>
@@ -379,12 +367,11 @@ namespace S7.Net
/// <param name="classValue">The class to be written</param> /// <param name="classValue">The class to be written</param>
/// <param name="db">Db address</param> /// <param name="db">Db address</param>
/// <param name="startByteAdr">Start bytes on the PLC</param> /// <param name="startByteAdr">Start bytes on the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public async Task<ErrorCode> WriteClassAsync(object classValue, int db, int startByteAdr = 0) public async Task WriteClassAsync(object classValue, int db, int startByteAdr = 0)
{ {
var bytes = Types.Class.ToBytes(classValue).ToList(); var bytes = Types.Class.ToBytes(classValue).ToList();
var errCode = await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray()); await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray());
return errCode;
} }
private async Task<byte[]> ReadBytesWithSingleRequestAsync(DataType dataType, int db, int startByteAdr, int count) private async Task<byte[]> ReadBytesWithSingleRequestAsync(DataType dataType, int db, int startByteAdr, int count)
@@ -402,7 +389,7 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream); var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
for (int cnt = 0; cnt < count; cnt++) for (int cnt = 0; cnt < count; cnt++)
bytes[cnt] = s7data[cnt + 18]; bytes[cnt] = s7data[cnt + 18];
@@ -427,15 +414,14 @@ namespace S7.Net
} }
/// <summary> /// <summary>
/// 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. /// Writes up to 200 bytes to the PLC. 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.
/// </summary> /// </summary>
/// <param name="dataType">Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.</param> /// <param name="dataType">Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.</param>
/// <param name="db">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.</param> /// <param name="db">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.</param>
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
/// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param> /// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
private async Task<ErrorCode> WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, byte[] value) private async Task WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, byte[] value)
{ {
byte[] bReceive = new byte[513]; byte[] bReceive = new byte[513];
int varCount = 0; int varCount = 0;
@@ -471,27 +457,23 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream); var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
{ {
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
} }
return ErrorCode.NoError;
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.WriteData; throw new PlcException(ErrorCode.WriteData, exc);
LastErrorString = exc.Message;
return LastErrorCode;
} }
} }
private async Task<ErrorCode> 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]; byte[] bReceive = new byte[513];
int varCount = 0; int varCount = 0;
try try
{ {
var value = new[] { bitValue ? (byte)1 : (byte)0 }; var value = new[] {bitValue ? (byte) 1 : (byte) 0};
varCount = value.Length; varCount = value.Length;
// first create the header // first create the header
int packageSize = 35 + value.Length; int packageSize = 35 + value.Length;
@@ -520,15 +502,11 @@ namespace S7.Net
var s7data = await COTP.TSDU.ReadAsync(stream); var s7data = await COTP.TSDU.ReadAsync(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
return ErrorCode.NoError;
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.WriteData; throw new PlcException(ErrorCode.WriteData, exc);
LastErrorString = exc.Message;
return LastErrorCode;
} }
} }
} }

39
S7.Net/PlcException.cs Normal file
View File

@@ -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
}
}

View File

@@ -11,16 +11,12 @@ namespace S7.Net
public partial class Plc public partial class Plc
{ {
/// <summary> /// <summary>
/// Open a <see cref="Socket"/> and connects to the PLC, sending all the corrected package /// Connects to the PLC and performs a COTP ConnectionRequest and S7 CommunicationSetup.
/// and returning if the connection was successful (<see cref="ErrorCode.NoError"/>) of it was wrong.
/// </summary> /// </summary>
/// <returns>Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode</returns> public void Open()
public ErrorCode Open()
{ {
if (Connect() != ErrorCode.NoError) Connect();
{
return LastErrorCode;
}
try try
{ {
stream.Write(ConnectionRequest.GetCOTPConnectionRequest(CPU, Rack, Slot), 0, 22); stream.Write(ConnectionRequest.GetCOTPConnectionRequest(CPU, Rack, Slot), 0, 22);
@@ -41,14 +37,12 @@ namespace S7.Net
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.ConnectionError; throw new PlcException(ErrorCode.ConnectionError,
LastErrorString = string.Format("Couldn't establish the connection to {0}.\nMessage: {1}", IP, exc.Message); $"Couldn't establish the connection to {IP}.\nMessage: {exc.Message}", exc);
return ErrorCode.ConnectionError;
} }
return ErrorCode.NoError;
} }
private ErrorCode Connect() private void Connect()
{ {
try try
{ {
@@ -59,23 +53,15 @@ namespace S7.Net
catch (SocketException sex) catch (SocketException sex)
{ {
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
if (sex.SocketErrorCode == SocketError.TimedOut) throw new PlcException(
{ sex.SocketErrorCode == SocketError.TimedOut
LastErrorCode = ErrorCode.IPAddressNotAvailable; ? ErrorCode.IPAddressNotAvailable
} : ErrorCode.ConnectionError, sex);
else
{
LastErrorCode = ErrorCode.ConnectionError;
}
LastErrorString = sex.Message;
} }
catch (Exception ex) catch (Exception ex)
{ {
LastErrorCode = ErrorCode.ConnectionError; throw new PlcException(ErrorCode.ConnectionError, ex);
LastErrorString = ex.Message;
} }
return LastErrorCode;
} }
/// <summary> /// <summary>
@@ -231,8 +217,7 @@ namespace S7.Net
/// <param name="db">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.</param> /// <param name="db">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.</param>
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
public ErrorCode WriteBytes(DataType dataType, int db, int startByteAdr, byte[] value)
{ {
int localIndex = 0; int localIndex = 0;
int count = value.Length; int count = value.Length;
@@ -241,16 +226,11 @@ namespace S7.Net
//TODO: Figure out how to use MaxPDUSize here //TODO: Figure out how to use MaxPDUSize here
//Snap7 seems to choke on PDU sizes above 256 even if snap7 //Snap7 seems to choke on PDU sizes above 256 even if snap7
//replies with bigger PDU size in connection setup. //replies with bigger PDU size in connection setup.
var maxToWrite = (int)Math.Min(count, 200); var maxToWrite = Math.Min(count, 200);
ErrorCode lastError = WriteBytesWithASingleRequest(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray()); WriteBytesWithASingleRequest(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray());
if (lastError != ErrorCode.NoError)
{
return lastError;
}
count -= maxToWrite; count -= maxToWrite;
localIndex += maxToWrite; localIndex += maxToWrite;
} }
return ErrorCode.NoError;
} }
/// <summary> /// <summary>
@@ -261,36 +241,28 @@ namespace S7.Net
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
public ErrorCode WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, bool value)
{ {
if (bitAdr < 0 || bitAdr > 7) 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)); 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); WriteBitWithASingleRequest(dataType, db, startByteAdr, bitAdr, value);
if (lastError != ErrorCode.NoError)
{
return lastError;
}
return ErrorCode.NoError;
} }
/// <summary> /// <summary>
/// Write a single bit from a DB with the specified index. /// Write a single bit to a DB with the specified index.
/// </summary> /// </summary>
/// <param name="dataType">Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.</param> /// <param name="dataType">Data type of the memory area, can be DB, Timer, Counter, Merker(Memory), Input, Output.</param>
/// <param name="db">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.</param> /// <param name="db">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.</param>
/// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to write DB1.DBW200, this is 200.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <param name="value">Bytes to write. If more than 200, multiple requests will be made.</param> /// <param name="value">Value to write (0 or 1).</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
public ErrorCode WriteBit(DataType dataType, int db, int startByteAdr, int bitAdr, int value)
{ {
if (value < 0 || value > 1) if (value < 0 || value > 1)
throw new ArgumentException("Value must be 0 or 1", nameof(value)); 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);
} }
/// <summary> /// <summary>
@@ -303,26 +275,29 @@ namespace S7.Net
/// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param> /// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
/// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param> /// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param>
/// <param name="bitAdr">The address of the bit. (0-7)</param> /// <param name="bitAdr">The address of the bit. (0-7)</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void Write(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
public ErrorCode Write(DataType dataType, int db, int startByteAdr, object value, int bitAdr = -1)
{ {
if (bitAdr != -1) if (bitAdr != -1)
{ {
//Must be writing a bit value as bitAdr is specified //Must be writing a bit value as bitAdr is specified
if (value is bool) 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) else if (value is int intValue)
{ {
if (intValue < 0 || intValue > 7) 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));
} }
/// <summary> /// <summary>
@@ -331,11 +306,10 @@ namespace S7.Net
/// </summary> /// </summary>
/// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param> /// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
/// <param name="value">Value to be written to the PLC</param> /// <param name="value">Value to be written to the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void Write(string variable, object value)
public ErrorCode Write(string variable, object value)
{ {
var adr = new PLCAddress(variable); 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);
} }
/// <summary> /// <summary>
@@ -344,10 +318,9 @@ namespace S7.Net
/// <param name="structValue">The struct to be written</param> /// <param name="structValue">The struct to be written</param>
/// <param name="db">Db address</param> /// <param name="db">Db address</param>
/// <param name="startByteAdr">Start bytes on the PLC</param> /// <param name="startByteAdr">Start bytes on the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void WriteStruct(object structValue, int db, int startByteAdr = 0)
public ErrorCode WriteStruct(object structValue, int db, int startByteAdr = 0)
{ {
return WriteStructAsync(structValue, db, startByteAdr).Result; WriteStructAsync(structValue, db, startByteAdr).GetAwaiter().GetResult();
} }
/// <summary> /// <summary>
@@ -356,10 +329,9 @@ namespace S7.Net
/// <param name="classValue">The class to be written</param> /// <param name="classValue">The class to be written</param>
/// <param name="db">Db address</param> /// <param name="db">Db address</param>
/// <param name="startByteAdr">Start bytes on the PLC</param> /// <param name="startByteAdr">Start bytes on the PLC</param>
/// <returns>NoError if it was successful, or the error is specified</returns> public void WriteClass(object classValue, int db, int startByteAdr = 0)
public ErrorCode 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) private byte[] ReadBytesWithSingleRequest(DataType dataType, int db, int startByteAdr, int count)
@@ -378,24 +350,16 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream); var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
for (int cnt = 0; cnt < count; cnt++) for (int cnt = 0; cnt < count; cnt++)
bytes[cnt] = s7data[cnt + 18]; bytes[cnt] = s7data[cnt + 18];
return bytes; return bytes;
} }
catch (SocketException socketException)
{
LastErrorCode = ErrorCode.ReadData;
LastErrorString = socketException.Message;
return null;
}
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.ReadData; throw new PlcException(ErrorCode.ReadData, exc);
LastErrorString = exc.Message;
return null;
} }
} }
@@ -414,7 +378,7 @@ namespace S7.Net
S7WriteMultiple.ParseResponse(response, response.Length, dataItems); 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; int varCount = 0;
try try
@@ -448,26 +412,22 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream); var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
{ {
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
} }
return ErrorCode.NoError;
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.WriteData; throw new PlcException(ErrorCode.WriteData, exc);
LastErrorString = exc.Message;
return LastErrorCode;
} }
} }
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; int varCount = 0;
try try
{ {
var value = new[] { bitValue ? (byte)1 : (byte)0 }; var value = new[] {bitValue ? (byte) 1 : (byte) 0};
varCount = value.Length; varCount = value.Length;
// first create the header // first create the header
int packageSize = 35 + value.Length; int packageSize = 35 + value.Length;
@@ -496,15 +456,11 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream); var s7data = COTP.TSDU.Read(stream);
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
return ErrorCode.NoError;
} }
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.WriteData; throw new PlcException(ErrorCode.WriteData, exc);
LastErrorString = exc.Message;
return LastErrorCode;
} }
} }
@@ -531,7 +487,7 @@ namespace S7.Net
{ {
// first create the header // first create the header
int packageSize = 19 + (dataItems.Count * 12); int packageSize = 19 + (dataItems.Count * 12);
Types.ByteArray package = new ByteArray(packageSize); ByteArray package = new ByteArray(packageSize);
package.Add(ReadHeaderPackage(dataItems.Count)); package.Add(ReadHeaderPackage(dataItems.Count));
// package.Add(0x02); // datenart // package.Add(0x02); // datenart
foreach (var dataItem in dataItems) foreach (var dataItem in dataItems)
@@ -543,19 +499,13 @@ namespace S7.Net
var s7data = COTP.TSDU.Read(stream); //TODO use Async var s7data = COTP.TSDU.Read(stream); //TODO use Async
if (s7data == null || s7data[14] != 0xff) if (s7data == null || s7data[14] != 0xff)
throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); throw new PlcException(ErrorCode.WrongNumberReceivedBytes);
ParseDataIntoDataItems(s7data, dataItems); ParseDataIntoDataItems(s7data, dataItems);
} }
catch (SocketException socketException)
{
LastErrorCode = ErrorCode.ReadData;
LastErrorString = socketException.Message;
}
catch (Exception exc) catch (Exception exc)
{ {
LastErrorCode = ErrorCode.ReadData; throw new PlcException(ErrorCode.ReadData, exc);
LastErrorString = exc.Message;
} }
} }
} }