diff --git a/S7.Net.Core/PLC.cs b/S7.Net.Core/PLC.cs
index 4185137..52cfd38 100644
--- a/S7.Net.Core/PLC.cs
+++ b/S7.Net.Core/PLC.cs
@@ -5,17 +5,33 @@ using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
+using S7.Net.Types;
using Double = System.Double;
namespace S7.Net
{
- public class Plc
+ public class Plc : IDisposable
{
private SocketClient _mSocket; //TCP connection to device
+ ///
+ /// Ip address of the plc
+ ///
public string IP { get; private set; }
+
+ ///
+ /// Cpu type of the plc
+ ///
public CpuType CPU { get; private set; }
+
+ ///
+ /// Rack of the plc
+ ///
public Int16 Rack { get; private set; }
+
+ ///
+ /// Slot of the CPU of the plc
+ ///
public Int16 Slot { get; private set; }
///
@@ -36,7 +52,7 @@ namespace S7.Net
//{
// result = null;
//}
- return (!string.IsNullOrEmpty(IP)); // result != null && result.Status == IPStatus.Success;
+ return (!string.IsNullOrWhiteSpace(IP)); // result != null && result.Status == IPStatus.Success;
//}
}
}
@@ -59,9 +75,16 @@ 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.
@@ -69,12 +92,11 @@ namespace S7.Net
/// You need slot > 0 if you are connecting to external ethernet card (CP).
/// For S7-300 and S7-400 the default is rack = 0 and slot = 2.
///
- ///
- ///
- ///
- ///
- ///
- ///
+ /// CpuType of the plc (select from the enum)
+ /// Ip address of the plc
+ /// rack of the plc, usually it's 0, but check in the hardware configuration of Step7 or TIA portal
+ /// slot of the CPU of the plc, usually it's 2 for S7300-S7400, 0 for S7-1200 and S7-1500.
+ /// If you use an external ethernet card, this must be set accordingly.
public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot)
{
IP = ip;
@@ -83,85 +105,92 @@ namespace S7.Net
Slot = slot;
}
+ ///
+ /// Open a socket and connects to the plc, sending all the corrected package and returning if the connection was successful (ErroreCode.NoError) of it was wrong.
+ ///
+ /// Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode
public ErrorCode Open()
- {
- byte[] bReceive = new byte[256];
+ {
+ byte[] bReceive = new byte[256];
- try
+ try
{
- // check if available
+ // check if available
if (!IsAvailable)
{
throw new Exception();
}
}
- catch
+ catch
{
- LastErrorCode = ErrorCode.IPAddressNotAvailable;
- LastErrorString = string.Format("Destination IP-Address '{0}' is not available!", IP);
- return LastErrorCode;
- }
+ LastErrorCode = ErrorCode.IPAddressNotAvailable;
+ LastErrorString = string.Format("Destination IP-Address '{0}' is not available!", IP);
+ return LastErrorCode;
+ }
- try {
- // open the channel
- _mSocket = new SocketClient(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
- _mSocket.SetReceiveTimeout(1000);
- _mSocket.SetSendTimeout(1000);
-
- IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102);
- _mSocket.Connect(server);
- }
- catch (Exception ex) {
- LastErrorCode = ErrorCode.ConnectionError;
- LastErrorString = ex.Message;
- return ErrorCode.ConnectionError;
- }
-
- try
+ try
{
- byte[] bSend1 = { 3, 0, 0, 22, 17, 224, 0, 0, 0, 46, 0, 193, 2, 1, 0, 194, 2, 3, 0, 192, 1, 9 };
+ // open the channel
+ _mSocket = new SocketClient(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- switch (CPU) {
- case CpuType.S7200:
- //S7200: Chr(193) & Chr(2) & Chr(16) & Chr(0) 'Eigener Tsap
- bSend1[11] = 193;
- bSend1[12] = 2;
- bSend1[13] = 16;
- bSend1[14] = 0;
- //S7200: Chr(194) & Chr(2) & Chr(16) & Chr(0) 'Fremder Tsap
- bSend1[15] = 194;
- bSend1[16] = 2;
- bSend1[17] = 16;
- bSend1[18] = 0;
- break;
+ _mSocket.SetReceiveTimeout(1000);
+ _mSocket.SetSendTimeout(1000);
+
+ IPEndPoint server = new IPEndPoint(IPAddress.Parse(IP), 102);
+ _mSocket.Connect(server);
+ }
+ catch (Exception ex)
+ {
+ LastErrorCode = ErrorCode.ConnectionError;
+ LastErrorString = ex.Message;
+ return ErrorCode.ConnectionError;
+ }
+
+ try
+ {
+ byte[] bSend1 = { 3, 0, 0, 22, 17, 224, 0, 0, 0, 46, 0, 193, 2, 1, 0, 194, 2, 3, 0, 192, 1, 9 };
+
+ switch (CPU)
+ {
+ case CpuType.S7200:
+ //S7200: Chr(193) & Chr(2) & Chr(16) & Chr(0) 'Eigener Tsap
+ bSend1[11] = 193;
+ bSend1[12] = 2;
+ bSend1[13] = 16;
+ bSend1[14] = 0;
+ //S7200: Chr(194) & Chr(2) & Chr(16) & Chr(0) 'Fremder Tsap
+ bSend1[15] = 194;
+ bSend1[16] = 2;
+ bSend1[17] = 16;
+ bSend1[18] = 0;
+ break;
case CpuType.S71200:
- case CpuType.S7300:
- //S7300: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
- bSend1[11] = 193;
- bSend1[12] = 2;
- bSend1[13] = 1;
- bSend1[14] = 0;
- //S7300: Chr(194) & Chr(2) & Chr(3) & Chr(2) 'Fremder Tsap
- bSend1[15] = 194;
- bSend1[16] = 2;
- bSend1[17] = 3;
- bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
- break;
- case CpuType.S7400:
- //S7400: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
- bSend1[11] = 193;
- bSend1[12] = 2;
- bSend1[13] = 1;
- bSend1[14] = 0;
- //S7400: Chr(194) & Chr(2) & Chr(3) & Chr(3) 'Fremder Tsap
- bSend1[15] = 194;
- bSend1[16] = 2;
- bSend1[17] = 3;
+ case CpuType.S7300:
+ //S7300: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
+ bSend1[11] = 193;
+ bSend1[12] = 2;
+ bSend1[13] = 1;
+ bSend1[14] = 0;
+ //S7300: Chr(194) & Chr(2) & Chr(3) & Chr(2) 'Fremder Tsap
+ bSend1[15] = 194;
+ bSend1[16] = 2;
+ bSend1[17] = 3;
+ bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
+ break;
+ case CpuType.S7400:
+ //S7400: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
+ bSend1[11] = 193;
+ bSend1[12] = 2;
+ bSend1[13] = 1;
+ bSend1[14] = 0;
+ //S7400: Chr(194) & Chr(2) & Chr(3) & Chr(3) 'Fremder Tsap
+ bSend1[15] = 194;
+ bSend1[16] = 2;
+ bSend1[17] = 3;
bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
break;
case CpuType.S71500:
- // Eigener Tsap
+ // Eigener Tsap
bSend1[11] = 193;
bSend1[12] = 2;
bSend1[13] = 0x10;
@@ -172,102 +201,181 @@ namespace S7.Net
bSend1[17] = 0x3;
bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
break;
- default:
- return ErrorCode.WrongCPU_Type;
- }
+ default:
+ return ErrorCode.WrongCPU_Type;
+ }
- _mSocket.Send(bSend1, 22);
- if (_mSocket.Receive(bReceive, 22) != 22)
- {
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
- }
+ _mSocket.Send(bSend1, 22);
+ if (_mSocket.Receive(bReceive, 22) != 22)
+ {
+ throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ }
- byte[] bsend2 = { 3, 0, 0, 25, 2, 240, 128, 50, 1, 0, 0, 255, 255, 0, 8, 0, 0, 240, 0, 0, 3, 0, 3, 1, 0 };
- _mSocket.Send(bsend2, 25);
+ byte[] bsend2 = { 3, 0, 0, 25, 2, 240, 128, 50, 1, 0, 0, 255, 255, 0, 8, 0, 0, 240, 0, 0, 3, 0, 3, 1, 0 };
+ _mSocket.Send(bsend2, 25);
- if (_mSocket.Receive(bReceive, 27) != 27)
- {
- throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
- }
- }
- catch
- {
- LastErrorCode = ErrorCode.ConnectionError;
- LastErrorString = string.Format("Couldn't establish the connection to {0}!", IP);
- return ErrorCode.ConnectionError;
- }
-
- return ErrorCode.NoError;
- }
-
- public void Close()
- {
- if (_mSocket != null && _mSocket.Connected)
- {
- _mSocket.Close();
+ if (_mSocket.Receive(bReceive, 27) != 27)
+ {
+ throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+ }
+ }
+ catch
+ {
+ LastErrorCode = ErrorCode.ConnectionError;
+ LastErrorString = string.Format("Couldn't establish the connection to {0}!", IP);
+ return ErrorCode.ConnectionError;
}
- }
+ return ErrorCode.NoError;
+ }
+
+ ///
+ /// Disonnects from the plc and close the socket
+ ///
+ public void Close()
+ {
+ if (_mSocket != null && _mSocket.Connected)
+ {
+ _mSocket.Close();
+ }
+ }
+
+ private Types.ByteArray ReadDataRequestPackage(DataType dataType, int DB, int startByteAdr, int count = 1)
+ {
+ //single data req = 12
+ var package = new Types.ByteArray(12);
+ package.Add(new byte[] { 0x12, 0x0a, 0x10 });
+ switch (dataType)
+ {
+ case DataType.Timer:
+ case DataType.Counter:
+ package.Add((byte)dataType);
+ break;
+ default:
+ package.Add(0x02);
+ break;
+ }
+
+ package.Add(Types.Word.ToByteArray((ushort)(count)));
+ package.Add(Types.Word.ToByteArray((ushort)(DB)));
+ package.Add((byte)dataType);
+ var overflow = (int)(startByteAdr * 8 / 0xffffU); // handles words with address bigger than 8191
+ package.Add((byte)overflow);
+ switch (dataType)
+ {
+ case DataType.Timer:
+ case DataType.Counter:
+ package.Add(Types.Word.ToByteArray((ushort)(startByteAdr)));
+ break;
+ default:
+ package.Add(Types.Word.ToByteArray((ushort)((startByteAdr) * 8)));
+ break;
+ }
+
+ return package;
+ }
+
+ ///
+ /// Reads multiple vars in a single request.
+ /// You have to create and pass a list of DataItems and you obtain in response the same list with the values.
+ /// Values are stored in the property "Value" of the dataItem and are already converted.
+ /// If you don't want the conversion, just create a dataItem of bytes.
+ /// DataItems must not be more than 20 (protocol restriction) and bytes must not be more than 200 + 22 of header (protocol restriction).
+ ///
+ /// List of dataitems that contains the list of variables that must be read. Maximum 20 dataitems are accepted.
+ public void ReadMultipleVars(List dataItems)
+ {
+ int cntBytes = dataItems.Sum(dataItem => VarTypeToByteLength(dataItem.VarType, dataItem.Count));
+
+ if (dataItems.Count > 20) throw new Exception("Too many vars requested");
+ if (cntBytes > 222) throw new Exception("Too many bytes requested"); //todo, proper TDU check + split in multiple requests
+
+ try
+ {
+ // first create the header
+ int packageSize = 19 + (dataItems.Count * 12);
+ Types.ByteArray package = new ByteArray(packageSize);
+ package.Add(ReadHeaderPackage(dataItems.Count));
+ // package.Add(0x02); // datenart
+ foreach (var dataItem in dataItems)
+ {
+ package.Add(ReadDataRequestPackage(dataItem.DataType, dataItem.DB, dataItem.StartByteAdr, VarTypeToByteLength(dataItem.VarType, dataItem.Count)));
+ }
+
+ _mSocket.Send(package.array, package.array.Length);
+
+ byte[] bReceive = new byte[512];
+ int numReceived = _mSocket.Receive(bReceive, 512);
+ if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
+
+ int offset = 25;
+ foreach (var dataItem in dataItems)
+ {
+ int byteCnt = VarTypeToByteLength(dataItem.VarType, dataItem.Count);
+ byte[] bytes = new byte[byteCnt];
+
+ for (int i = 0; i < byteCnt; i++)
+ {
+ bytes[i] = bReceive[i + offset];
+ }
+
+ offset += byteCnt + 4;
+
+ dataItem.Value = ParseBytes(dataItem.VarType, bytes, dataItem.Count);
+ }
+ }
+ catch (SocketException socketException)
+ {
+ LastErrorCode = ErrorCode.WriteData;
+ LastErrorString = socketException.Message;
+ }
+ catch (Exception exc)
+ {
+ LastErrorCode = ErrorCode.WriteData;
+ LastErrorString = exc.Message;
+ }
+ }
+
+ ///
+ /// Reads up to 200 bytes from the plc and returns an array of bytes. You must specify the memory area type, memory are address, byte start address and bytes count.
+ /// If the read was not successful, check LastErrorCode or LastErrorString.
+ ///
+ /// 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.
+ /// Byte count, if you want to read 120 bytes, set this to 120. This parameter can't be higher than 200. If you need more, use recursion.
+ /// Returns the bytes in an array
public byte[] ReadBytes(DataType dataType, int DB, int startByteAdr, int count)
{
byte[] bytes = new byte[count];
- try
- {
- // first create the header
- int packageSize = 31;
- Types.ByteArray package = new Types.ByteArray(packageSize);
+ try
+ {
+ // first create the header
+ int packageSize = 31;
+ Types.ByteArray package = new ByteArray(packageSize);
+ package.Add(ReadHeaderPackage());
+ // package.Add(0x02); // datenart
+ package.Add(ReadDataRequestPackage(dataType, DB, startByteAdr, count));
- package.Add(new byte[] {0x03, 0x00, 0x00});
- package.Add((byte) packageSize);
- package.Add(new byte[]
- {0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x04, 0x01, 0x12, 0x0a, 0x10});
- // package.Add(0x02); // datenart
- switch (dataType)
- {
- case DataType.Timer:
- case DataType.Counter:
- package.Add((byte) dataType);
- break;
- default:
- package.Add(0x02);
- break;
- }
+ _mSocket.Send(package.array, package.array.Length);
- package.Add(Types.Word.ToByteArray((ushort) (count)));
- package.Add(Types.Word.ToByteArray((ushort) (DB)));
- package.Add((byte) dataType);
- var overflow = (int)(startByteAdr * 8 / 0xffffU); // handles words with address bigger than 8191
- package.Add((byte)overflow);
- switch (dataType)
- {
- case DataType.Timer:
- case DataType.Counter:
- package.Add(Types.Word.ToByteArray((ushort) (startByteAdr)));
- break;
- default:
- package.Add(Types.Word.ToByteArray((ushort) ((startByteAdr)*8)));
- break;
- }
+ byte[] bReceive = new byte[512];
+ int numReceived = _mSocket.Receive(bReceive, 512);
+ if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
- _mSocket.Send(package.array, package.array.Length);
+ for (int cnt = 0; cnt < count; cnt++)
+ bytes[cnt] = bReceive[cnt + 25];
- byte[] bReceive = new byte[512];
- int numReceived = _mSocket.Receive(bReceive, 512);
- if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
-
- for (int cnt = 0; cnt < count; cnt++)
- bytes[cnt] = bReceive[cnt + 25];
-
- return bytes;
- }
- catch (SocketException socketException)
- {
- LastErrorCode = ErrorCode.WriteData;
- LastErrorString = socketException.Message;
- return null;
- }
- catch(Exception exc)
+ return bytes;
+ }
+ catch (SocketException socketException)
+ {
+ LastErrorCode = ErrorCode.WriteData;
+ LastErrorString = socketException.Message;
+ return null;
+ }
+ catch (Exception exc)
{
LastErrorCode = ErrorCode.WriteData;
LastErrorString = exc.Message;
@@ -275,96 +383,109 @@ namespace S7.Net
}
}
- public object Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount)
+ public int VarTypeToByteLength(VarType varType, int varCount = 1)
{
- byte[] bytes = null;
- int cntBytes = 0;
+ switch (varType)
+ {
+ case VarType.Bit:
+ return varCount; //TODO
+ case VarType.Byte:
+ return (varCount < 1) ? 1 : varCount;
+ case VarType.String:
+ return varCount;
+ case VarType.Word:
+ case VarType.Timer:
+ case VarType.Int:
+ case VarType.Counter:
+ return varCount * 2;
+ case VarType.DWord:
+ case VarType.DInt:
+ case VarType.Real:
+ return varCount * 4;
+ default:
+ return 0;
+ }
+ }
+
+ public object ParseBytes(VarType varType, byte[] bytes, int varCount)
+ {
+ if (bytes == null) return null;
switch (varType)
{
case VarType.Byte:
- cntBytes = varCount;
- if (cntBytes < 1) cntBytes = 1;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
if (varCount == 1)
return bytes[0];
else
return bytes;
case VarType.Word:
- cntBytes = varCount * 2;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.Word.FromByteArray(bytes);
else
return Types.Word.ToArray(bytes);
case VarType.Int:
- cntBytes = varCount * 2;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.Int.FromByteArray(bytes);
else
return Types.Int.ToArray(bytes);
case VarType.DWord:
- cntBytes = varCount * 4;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.DWord.FromByteArray(bytes);
else
return Types.DWord.ToArray(bytes);
case VarType.DInt:
- cntBytes = varCount * 4;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.DInt.FromByteArray(bytes);
else
return Types.DInt.ToArray(bytes);
case VarType.Real:
- cntBytes = varCount * 4;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.Double.FromByteArray(bytes);
else
return Types.Double.ToArray(bytes);
case VarType.String:
- cntBytes = varCount;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
return Types.String.FromByteArray(bytes);
case VarType.Timer:
- cntBytes = varCount * 2;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.Timer.FromByteArray(bytes);
else
return Types.Timer.ToArray(bytes);
case VarType.Counter:
- cntBytes = varCount * 2;
- bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
- if (bytes == null) return null;
-
if (varCount == 1)
return Types.Counter.FromByteArray(bytes);
else
return Types.Counter.ToArray(bytes);
+ case VarType.Bit:
+ return null; //TODO
default:
return null;
}
}
+ ///
+ /// Read and decode a certain number of bytes of the "VarType" provided.
+ /// This can be used to read multiple consecutive variables of the same type (Word, DWord, Int, etc).
+ /// If the read was not successful, check LastErrorCode or LastErrorString.
+ ///
+ /// 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.
+ /// Type of the variable/s that you are reading
+ /// Number of
+ public object Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount)
+ {
+ int cntBytes = VarTypeToByteLength(varType, varCount);
+ byte[] bytes = ReadBytes(dataType, db, startByteAdr, cntBytes);
+
+ return ParseBytes(varType, bytes, varCount);
+ }
+
+ ///
+ /// Reads a single variable from the plc, takes in input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
+ /// If the read was not successful, check LastErrorCode or LastErrorString.
+ ///
+ /// Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
+ /// Returns an object that contains the value. This object must be cast accordingly.
public object Read(string variable)
{
DataType mDataType;
@@ -400,17 +521,17 @@ namespace S7.Net
byte obj = (byte)Read(DataType.DataBlock, mDB, dbIndex, VarType.Byte, 1);
return obj;
case "DBW":
- UInt16 objI = (UInt16)Read(DataType.DataBlock, mDB, dbIndex, VarType.Word, 1);
+ UInt16 objI = (UInt16)Read(DataType.DataBlock, mDB, dbIndex, VarType.Word, 1);
return objI;
case "DBD":
- UInt32 objU = (UInt32)Read(DataType.DataBlock, mDB, dbIndex, VarType.DWord, 1);
+ UInt32 objU = (UInt32)Read(DataType.DataBlock, mDB, dbIndex, VarType.DWord, 1);
return objU;
case "DBX":
mByte = dbIndex;
mBit = int.Parse(strings[2]);
if (mBit > 7) throw new Exception();
byte obj2 = (byte)Read(DataType.DataBlock, mDB, mByte, VarType.Byte, 1);
- objBoolArray = new BitArray(new byte[] { obj2 });
+ objBoolArray = new BitArray(new byte[] { obj2 });
return objBoolArray[mBit];
default:
throw new Exception();
@@ -488,11 +609,11 @@ namespace S7.Net
mBit = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1));
if (mBit > 7) throw new Exception();
var obj3 = (byte)Read(mDataType, 0, mByte, VarType.Byte, 1);
- objBoolArray = new BitArray(new byte[]{obj3});
+ objBoolArray = new BitArray(new byte[] { obj3 });
return objBoolArray[mBit];
}
}
- catch
+ catch
{
LastErrorCode = ErrorCode.WrongVarFormat;
LastErrorString = "The variable'" + variable + "' could not be read. Please check the syntax and try again.";
@@ -500,12 +621,14 @@ namespace S7.Net
}
}
- public object ReadStruct(Type structType, int db)
- {
- return ReadStruct(structType, db, 0);
- }
-
- public object ReadStruct(Type structType, int db, int startByteAdr)
+ ///
+ /// Reads all the bytes needed to fill a struct in C#, starting from a certain address, and return an object that can be casted to the struct.
+ ///
+ /// Type of the struct to be readed (es.: TypeOf(MyStruct)).
+ /// Address of the DB.
+ /// Start byte address. If you want to read DB1.DBW200, this is 200.
+ /// Returns a struct that must be cast.
+ public object ReadStruct(Type structType, int db, int startByteAdr = 0)
{
int numBytes = Types.Struct.GetStructSize(structType);
// now read the package
@@ -516,16 +639,13 @@ namespace S7.Net
}
///
- /// Read a class from plc. Only properties are readed
+ /// Reads all the bytes needed to fill a class in C#, starting from a certain address, and set all the properties values to the value that are read from the plc.
+ /// This reads ony properties, it doesn't read private variable or public variable without {get;set;} specified.
///
/// Instance of the class that will store the values
/// Index of the DB; es.: 1 is for DB1
- public void ReadClass(object sourceClass, int db)
- {
- ReadClass(sourceClass, db, 0);
- }
-
- public void ReadClass(object sourceClass, int db, int startByteAdr)
+ /// Start byte address. If you want to read DB1.DBW200, this is 200.
+ public void ReadClass(object sourceClass, int db, int startByteAdr = 0)
{
Type classType = sourceClass.GetType();
int numBytes = Types.Class.GetClassSize(classType);
@@ -654,14 +774,14 @@ namespace S7.Net
switch (txt.Substring(0, 2))
{
case "DB":
- string[] strings = txt.Split(new char[]{'.'});
+ string[] strings = txt.Split(new char[] { '.' });
if (strings.Length < 2)
throw new Exception();
mDB = int.Parse(strings[0].Substring(2));
string dbType = strings[1].Substring(0, 3);
- int dbIndex = int.Parse(strings[1].Substring(3));
-
+ int dbIndex = int.Parse(strings[1].Substring(3));
+
switch (dbType)
{
case "DBB":
@@ -767,14 +887,14 @@ namespace S7.Net
// Counter
return Write(DataType.Counter, 0, int.Parse(txt.Substring(1)), (short)value);
default:
- throw new Exception(string.Format("Unknown variable type {0}.",txt.Substring(0,1)));
+ throw new Exception(string.Format("Unknown variable type {0}.", txt.Substring(0, 1)));
}
addressLocation = txt.Substring(1);
int decimalPointIndex = addressLocation.IndexOf(".");
if (decimalPointIndex == -1)
{
- throw new Exception(string.Format("Cannot parse variable {0}. Input, Output, Memory Address, Timer, and Counter types require bit-level addressing (e.g. I0.1).",addressLocation));
+ throw new Exception(string.Format("Cannot parse variable {0}. Input, Output, Memory Address, Timer, and Counter types require bit-level addressing (e.g. I0.1).", addressLocation));
}
mByte = int.Parse(addressLocation.Substring(0, decimalPointIndex));
@@ -793,7 +913,7 @@ namespace S7.Net
return Write(mDataType, 0, mByte, (byte)_byte);
}
}
- catch
+ catch
{
LastErrorCode = ErrorCode.WrongVarFormat;
LastErrorString = "The variable'" + variable + "' could not be parsed. Please check the syntax and try again.";
@@ -801,42 +921,21 @@ namespace S7.Net
}
}
- public ErrorCode WriteStruct(object structValue, int db)
- {
- return WriteStruct(structValue, db, 0);
- }
-
- public ErrorCode WriteStruct(object structValue, int db, int startByteAdr)
+ public ErrorCode WriteStruct(object structValue, int db, int startByteAdr = 0)
{
var bytes = Types.Struct.ToBytes(structValue).ToList();
var errCode = WriteMultipleBytes(bytes, db, startByteAdr);
return errCode;
}
- public ErrorCode WriteClass(object classValue, int db)
- {
- return WriteClass(classValue, db, 0);
- }
-
- public ErrorCode WriteClass(object classValue, int db, int startByteAdr)
+ public ErrorCode WriteClass(object classValue, int db, int startByteAdr = 0)
{
var bytes = Types.Class.ToBytes(classValue).ToList();
var errCode = WriteMultipleBytes(bytes, db, startByteAdr);
return errCode;
}
- ///
- /// Writes multiple bytes in a DB starting from index 0. This handles more than 200 bytes with multiple requests.
- ///
- /// The bytes to be written
- /// The DB number
- /// ErrorCode when writing (NoError if everything was ok)
- private ErrorCode WriteMultipleBytes(List bytes, int db)
- {
- return WriteMultipleBytes(bytes, db, 0);
- }
-
- private ErrorCode WriteMultipleBytes(List bytes, int db, int startByteAdr)
+ private ErrorCode WriteMultipleBytes(List bytes, int db, int startByteAdr = 0)
{
ErrorCode errCode = ErrorCode.NoError;
int index = startByteAdr;
@@ -864,17 +963,13 @@ namespace S7.Net
}
///
- /// Reads a number of bytes from a DB starting from index 0. This handles more than 200 bytes with multiple requests.
+ /// Reads a number of bytes from a DB starting from a specified index. This handles more than 200 bytes with multiple requests.
///
///
///
+ ///
///
- private List ReadMultipleBytes(int numBytes, int db)
- {
- return ReadMultipleBytes(numBytes, db, 0);
- }
-
- private List ReadMultipleBytes(int numBytes, int db, int startByteAdr)
+ private List ReadMultipleBytes(int numBytes, int db, int startByteAdr = 0)
{
List resultBytes = new List();
int index = startByteAdr;
@@ -891,6 +986,28 @@ namespace S7.Net
return resultBytes;
}
+ ///
+ /// Creates the header to read bytes from the plc
+ ///
+ ///
+ ///
+ private Types.ByteArray ReadHeaderPackage(int amount = 1)
+ {
+ //header size = 19 bytes
+ var package = new Types.ByteArray(19);
+ package.Add(new byte[] { 0x03, 0x00, 0x00 });
+ //complete package size
+ package.Add((byte)(19 + (12 * amount)));
+ package.Add(new byte[] { 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00 });
+ //data part size
+ package.Add(Types.Word.ToByteArray((ushort)(2 + (amount * 12))));
+ package.Add(new byte[] { 0x00, 0x00, 0x04 });
+ //amount of requests
+ package.Add((byte)amount);
+
+ return package;
+ }
+
#region IDisposable members
@@ -906,7 +1023,7 @@ namespace S7.Net
}
//((IDisposable)_mSocket).Dispose();
}
- }
+ }
#endregion
}