diff --git a/S7.Net/COTP.cs b/S7.Net/COTP.cs deleted file mode 100644 index 432cffc..0000000 --- a/S7.Net/COTP.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.IO; -using System.Net.Sockets; - -namespace S7.Net -{ - - /// - /// COTP Protocol functions and types - /// - internal class COTP - { - /// - /// Describes a COTP TPDU (Transport protocol data unit) - /// - public class TPDU - { - public byte HeaderLength; - public byte PDUType; - public int TPDUNumber; - public byte[] Data; - public bool LastDataUnit; - - public TPDU(TPKT tPKT) - { - var br = new BinaryReader(new MemoryStream(tPKT.Data)); - HeaderLength = br.ReadByte(); - if (HeaderLength >= 2) - { - PDUType = br.ReadByte(); - if (PDUType == 0xf0) //DT Data - { - var flags = br.ReadByte(); - TPDUNumber = flags & 0x7F; - LastDataUnit = (flags & 0x80) > 0; - Data = br.ReadBytes(tPKT.Length - HeaderLength - 4); //4 = TPKT Size - return; - } - //TODO: Handle other PDUTypes - } - Data = new byte[0]; - } - - /// - /// Reads COTP TPDU (Transport protocol data unit) from the network stream - /// See: https://tools.ietf.org/html/rfc905 - /// - /// The socket to read from - /// COTP DPDU instance - public static TPDU Read(Socket socket) - { - var tpkt = TPKT.Read(socket); - return new TPDU(tpkt); - } - - public override string ToString() - { - return string.Format("Length: {0} PDUType: {1} TPDUNumber: {2} Last: {3} Segment Data: {4}", - HeaderLength, - PDUType, - TPDUNumber, - LastDataUnit, - BitConverter.ToString(Data) - ); - } - - } - - /// - /// Describes a COTP TSDU (Transport service data unit). One TSDU consist of 1 ore more TPDUs - /// - public class TSDU - { - /// - /// Reads the full COTP TSDU (Transport service data unit) - /// See: https://tools.ietf.org/html/rfc905 - /// - /// Data in TSDU - public static byte[] Read(Socket socket) - { - var segment = TPDU.Read(socket); - var output = new MemoryStream(segment.Data.Length); - output.Write(segment.Data, 0, segment.Data.Length); - - while (!segment.LastDataUnit) - { - segment = TPDU.Read(socket); - output.Write(segment.Data, (int)output.Position, segment.Data.Length); - } - return output.GetBuffer(); - } - } - } -} diff --git a/S7.Net/PLC.cs b/S7.Net/PLC.cs index 6d2c0fe..67ad57a 100644 --- a/S7.Net/PLC.cs +++ b/S7.Net/PLC.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.ComponentModel; 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 @@ -39,11 +41,6 @@ namespace S7.Net /// Slot of the CPU of the PLC /// public Int16 Slot { get; private set; } - - /// - /// Max PDU size this cpu supports - /// - public Int16 MaxPDUSize { get; private set; } /// /// Returns true if a connection to the PLC can be established @@ -163,6 +160,7 @@ namespace S7.Net /// Returns ErrorCode.NoError if the connection was successful, otherwise check the ErrorCode public ErrorCode Open() { + byte[] bReceive = new byte[256]; _mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000); @@ -173,27 +171,11 @@ namespace S7.Net return LastErrorCode; } - try + try { - byte[] bSend1 = { 3, 0, 0, 22, //TPKT - 17, //COTP Header Length - 224, //Connect Request - 0, 0, //Destination Reference - 0, 46, //Source Reference - 0, //Flags - 193, //Parameter Code (src-tasp) - 2, //Parameter Length - 1, 0, //Source TASP - 194, //Parameter Code (dst-tasp) - 2, //Parameter Length - 3, 0, //Destination TASP - 192, //Parameter Code (tpdu-size) - 1, //Parameter Length - 9 //TPDU Size (2^9 = 512) - }; + 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) - { + switch (CPU) { case CpuType.S7200: //S7200: Chr(193) & Chr(2) & Chr(16) & Chr(0) 'Eigener Tsap bSend1[11] = 193; @@ -247,33 +229,28 @@ namespace S7.Net return ErrorCode.WrongCPU_Type; } - //COTP Setup _mSocket.Send(bSend1, 22, SocketFlags.None); - var response = COTP.TPDU.Read(_mSocket); - if (response.PDUType != 0xd0) //Connect Confirm + if (_mSocket.Receive(bReceive, 22, SocketFlags.None) != 22) { throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); - } + } - //S7ComSetup 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, SocketFlags.None); - var s7data = COTP.TSDU.Read(_mSocket); - if (s7data.Length >= 2 && s7data[1] == 0x03) //Check for S7 Ack Data + if (_mSocket.Receive(bReceive, 27, SocketFlags.None) != 27) { - MaxPDUSize = (short)(s7data[18] * 256 + s7data[19]); - return ErrorCode.NoError; - } - - throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); + throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); + } } - catch (Exception exc) + catch(Exception exc) { LastErrorCode = ErrorCode.ConnectionError; LastErrorString = string.Format("Couldn't establish the connection to {0}.\nMessage: {1}", IP, exc.Message); return ErrorCode.ConnectionError; } + + return ErrorCode.NoError; } /// @@ -299,12 +276,11 @@ namespace S7.Net public void ReadMultipleVars(List dataItems) { int cntBytes = dataItems.Sum(dataItem => VarTypeToByteLength(dataItem.VarType, dataItem.Count)); - - //Is this really a limit? - //if (dataItems.Count > 20) - // throw new Exception("Too many vars requested"); - if (cntBytes > MaxPDUSize - 18) - throw new Exception(string.Format("Too many bytes requested Requested: {0} Max {1}", cntBytes, MaxPDUSize)); //TODO: split in multiple requests + + 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 { @@ -320,10 +296,12 @@ namespace S7.Net _mSocket.Send(package.array, package.array.Length, SocketFlags.None); - var s7data = COTP.TSDU.Read(_mSocket); - if (s7data[14] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); + byte[] bReceive = new byte[512]; + int numReceived = _mSocket.Receive(bReceive, 512, SocketFlags.None); + if (bReceive[21] != 0xff) + throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); - int offset = 18; + int offset = 25; foreach (var dataItem in dataItems) { int byteCnt = VarTypeToByteLength(dataItem.VarType, dataItem.Count); @@ -331,7 +309,7 @@ namespace S7.Net for (int i = 0; i < byteCnt; i++) { - bytes[i] = s7data[i + offset]; + bytes[i] = bReceive[i + offset]; } offset += byteCnt + 4; @@ -366,7 +344,7 @@ namespace S7.Net int index = startByteAdr; while (count > 0) { - var maxToRead = (int)Math.Min(count, MaxPDUSize); + var maxToRead = (int)Math.Min(count, 200); byte[] bytes = ReadBytesWithASingleRequest(dataType, db, index, maxToRead); if (bytes == null) return resultBytes.ToArray(); @@ -644,7 +622,7 @@ namespace S7.Net int count = value.Length; while (count > 0) { - var maxToWrite = (int)Math.Min(count, MaxPDUSize); + var maxToWrite = (int)Math.Min(count, 200); ErrorCode lastError = WriteBytesWithASingleRequest(dataType, db, startByteAdr + localIndex, value.Skip(localIndex).Take(maxToWrite).ToArray()); if (lastError != ErrorCode.NoError) { @@ -753,7 +731,7 @@ namespace S7.Net package = Types.DWord.ToByteArray((UInt32)value); break; case "Double": - package = Types.Double.ToByteArray((double)value); + package = Types.Double.ToByteArray((Double)value); break; case "Byte[]": package = (byte[])value; @@ -837,12 +815,10 @@ namespace S7.Net { return Write(DataType.DataBlock, mDB, dbIndex, (Int32)value); } - else if (value is double) + else { - return Write(DataType.DataBlock, mDB, dbIndex, value); + objValue = Convert.ChangeType(value, typeof(UInt32)); } - - objValue = Convert.ChangeType(value, typeof(UInt32)); return Write(DataType.DataBlock, mDB, dbIndex, (UInt32)objValue); case "DBX": mByte = dbIndex; @@ -1071,12 +1047,13 @@ namespace S7.Net _mSocket.Send(package.array, package.array.Length, SocketFlags.None); - var s7data = COTP.TSDU.Read(_mSocket); - if (s7data[14] != 0xff) + byte[] bReceive = new byte[512]; + int numReceived = _mSocket.Receive(bReceive, 512, SocketFlags.None); + if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); for (int cnt = 0; cnt < count; cnt++) - bytes[cnt] = s7data[cnt + 25]; + bytes[cnt] = bReceive[cnt + 25]; return bytes; } @@ -1136,8 +1113,8 @@ namespace S7.Net _mSocket.Send(package.array, package.array.Length, SocketFlags.None); - var s7data = COTP.TSDU.Read(_mSocket); - if (s7data[14] != 0xff) + int numReceived = _mSocket.Receive(bReceive, 512, SocketFlags.None); + if (bReceive[21] != 0xff) { throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); } @@ -1186,9 +1163,11 @@ namespace S7.Net _mSocket.Send(package.array, package.array.Length, SocketFlags.None); - var s7data = COTP.TSDU.Read(_mSocket); - if (bReceive[14] != 0xff) + int numReceived = _mSocket.Receive(bReceive, 512, SocketFlags.None); + if (bReceive[21] != 0xff) + { throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString()); + } return ErrorCode.NoError; } diff --git a/S7.Net/S7.Net.csproj b/S7.Net/S7.Net.csproj index bb2abab..ac2ac19 100644 --- a/S7.Net/S7.Net.csproj +++ b/S7.Net/S7.Net.csproj @@ -77,11 +77,9 @@ - - diff --git a/S7.Net/TPKT.cs b/S7.Net/TPKT.cs deleted file mode 100644 index f5a4aab..0000000 --- a/S7.Net/TPKT.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Net.Sockets; - -namespace S7.Net -{ - - /// - /// Describes a TPKT Packet - /// - internal class TPKT - { - public byte Version; - public byte Reserved1; - public int Length; - public byte[] Data; - - /// - /// Reds a TPKT from the socket - /// - /// The socket to read from - /// TPKT Instace - public static TPKT Read(Socket socket) - { - var buf = new byte[4]; - socket.Receive(buf, 4, SocketFlags.None); - var pkt = new TPKT - { - Version = buf[0], - Reserved1 = buf[1], - Length = buf[2] * 256 + buf[3] //BigEndian - }; - pkt.Data = new byte[pkt.Length - 4]; - socket.Receive(pkt.Data, pkt.Length - 4, SocketFlags.None); - return pkt; - } - - public override string ToString() - { - return string.Format("Version: {0} Length: {1} Data: {2}", - Version, - Length, - BitConverter.ToString(Data) - ); - } - } -}