/*=============================================================================||PROJECTSharp71.0.7||==============================================================================||Copyright(C)2016DavideNardella||Allrightsreserved.||==============================================================================||Sharp7isfreesoftware:youcanredistributeitand/ormodify||itunderthetermsoftheLesserGNUGeneralPublicLicenseaspublishedby||theFreeSoftwareFoundation,eitherversion3oftheLicense,or||(atyouroption)anylaterversion.||||Itmeansthatyoucandistributeyourcommercialsoftwarewhichincludes||Sharp7withouttherequirementtodistributethesourcecodeofyour||applicationandwithouttherequirementthatyourapplicationbeitself||distributedunderLGPL.||||Sharp7isdistributedinthehopethatitwillbeuseful,||butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof||MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe||LesserGNUGeneralPublicLicenseformoredetails.||||YoushouldhavereceivedacopyoftheGNUGeneralPublicLicenseanda||copyofLesserGNUGeneralPublicLicensealongwithSharp7.||Ifnot,seehttp://www.gnu.org/licenses/||==============================================================================|History:*1.0.02016/10/09FirstRelease*1.0.12016/10/22AddedCoreCLRcompatibility(CORE_CLRsymbolmustbedefinedinBuildoptions).ThankstoDirk-JanWassink.*1.0.22016/11/13FixedabuginCLRcompatibility*1.0.32017/01/25FixedabuginS7.GetIntAt().Thankstolupal1AddedS7TimerRead/Write.ThankstoLukasPalkovic*1.0.42018/06/12FixedthelastbuginS7.GetIntAt().ThankstoJérémyHAURAYGet/SetLTime.ThankstoJérémyHAURAYGet/Set1500WString.ThankstoJérémyHAURAYGet/Set1500ArrayofWChar.ThankstoJérémyHAURAY*1.0.52018/11/21ImplementedListBlocksandListBlocksOfType(byJosKoenis,TEBEngineering)*1.0.62019/05/25ImplementedForceJobsbyBartSwister*1.0.72019/10/05BugfixinListinListBlocksOfType.ThankstoCosimoLadiana*/usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Text;usingSystem.Threading;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.IO;//------------------------------------------------------------------------------//IfyouarecompilingforUWPverifythatWINDOWS_UWPorNETFX_COREare//definedintoProjectProperties->Build->Conditionalcompilationsymbols//------------------------------------------------------------------------------#ifWINDOWS_UWP||NETFX_COREusingSystem.Threading.Tasks;usingWindows.Networking;usingWindows.Networking.Sockets;usingWindows.Storage.Streams;#else//<--IncludingMONOusingSystem.Net.Sockets;#endifnamespaceSharp7{#region[AsyncSocketsUWP(W10,IoT,Phone)/Windows8/Windows8Phone]#ifWINDOWS_UWP||NETFX_COREclassMsgSocket{privateDataReaderReader=null;privateDataWriterWriter=null;privateStreamSocketTCPSocket;privatebool_Connected;privateint_ReadTimeout=2000;privateint_WriteTimeout=2000;privateint_ConnectTimeout=1000;publicstaticintLastError=0;privatevoidCreateSocket(){TCPSocket=newStreamSocket();TCPSocket.Control.NoDelay=true;_Connected=false;}publicMsgSocket(){}publicvoidClose(){if(Reader!=null){Reader.Dispose();Reader=null;}if(Writer!=null){Writer.Dispose();Writer=null;}if(TCPSocket!=null){TCPSocket.Dispose();TCPSocket=null;}_Connected=false;}privateasyncTaskAsConnect(stringHost,stringport,CancellationTokenSourcects){HostNameServerHost=newHostName(Host);try{awaitTCPSocket.ConnectAsync(ServerHost,port).AsTask(cts.Token);_Connected=true;}catch(TaskCanceledException){LastError=S7Consts.errTCPConnectionTimeout;}catch{LastError=S7Consts.errTCPConnectionFailed;//Maybeunreachablepeer}}publicintConnect(stringHost,intPort){LastError=0;if(!Connected){CreateSocket();CancellationTokenSourcects=newCancellationTokenSource();try{try{cts.CancelAfter(_ConnectTimeout);Task.WaitAny(Task.Run(async()=>awaitAsConnect(Host,Port.ToString(),cts)));}catch{LastError=S7Consts.errTCPConnectionFailed;}}finally{if(cts!=null){try{cts.Cancel();cts.Dispose();cts=null;}catch{}}}if(LastError==0){Reader=newDataReader(TCPSocket.InputStream);Reader.InputStreamOptions=InputStreamOptions.Partial;Writer=newDataWriter(TCPSocket.OutputStream);_Connected=true;}elseClose();}returnLastError;}privateasyncTaskAsReadBuffer(byte[]Buffer,intSize,CancellationTokenSourcects){try{awaitReader.LoadAsync((uint)Size).AsTask(cts.Token);Reader.ReadBytes(Buffer);}catch{LastError=S7Consts.errTCPDataReceive;}}publicintReceive(byte[]Buffer,intStart,intSize){byte[]InBuffer=newbyte[Size];CancellationTokenSourcects=newCancellationTokenSource();LastError=0;try{try{cts.CancelAfter(_ReadTimeout);Task.WaitAny(Task.Run(async()=>awaitAsReadBuffer(InBuffer,Size,cts)));}catch{LastError=S7Consts.errTCPDataReceive;}}finally{if(cts!=null){try{cts.Cancel();cts.Dispose();cts=null;}catch{}}}if(LastError==0)Array.Copy(InBuffer,0,Buffer,Start,Size);elseClose();returnLastError;}privateasyncTaskWriteBuffer(byte[]Buffer,CancellationTokenSourcects){try{Writer.WriteBytes(Buffer);awaitWriter.StoreAsync().AsTask(cts.Token);}catch{LastError=S7Consts.errTCPDataSend;}}publicintSend(byte[]Buffer,intSize){byte[]OutBuffer=newbyte[Size];CancellationTokenSourcects=newCancellationTokenSource();Array.Copy(Buffer,0,OutBuffer,0,Size);LastError=0;try{try{cts.CancelAfter(_WriteTimeout);Task.WaitAny(Task.Run(async()=>awaitWriteBuffer(OutBuffer,cts)));}catch{LastError=S7Consts.errTCPDataSend;}}finally{if(cts!=null){try{cts.Cancel();cts.Dispose();cts=null;}catch{}}}if(LastError!=0)Close();returnLastError;}~MsgSocket(){Close();}publicboolConnected{get{return(TCPSocket!=null)&&_Connected;}}publicintReadTimeout{get{return_ReadTimeout;}set{_ReadTimeout=value;}}publicintWriteTimeout{get{return_WriteTimeout;}set{_WriteTimeout=value;}}publicintConnectTimeout{get{return_ConnectTimeout;}set{_ConnectTimeout=value;}}}#endif#endregion#region[SyncSocketsWin32/Win64DesktopApplication]#if!WINDOWS_UWP&&!NETFX_COREclassMsgSocket{privateSocketTCPSocket;privateint_ReadTimeout=2000;privateint_WriteTimeout=2000;privateint_ConnectTimeout=1000;publicintLastError=0;publicMsgSocket(){}~MsgSocket(){Close();}publicvoidClose(){if(TCPSocket!=null){TCPSocket.Dispose();TCPSocket=null;}}privatevoidCreateSocket(){TCPSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);TCPSocket.NoDelay=true;}privatevoidTCPPing(stringHost,intPort){//ToPingthePLCanAsynchronoussocketisusedratherthenanICMPpacket.//ThisallowstheusealsoacrossInternetandFirewalls(obviouslytheportmustbeopened)LastError=0;SocketPingSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);try{#ifCORE_CLRvartask=PingSocket.ConnectAsync(Host,Port);task.Wait(_ConnectTimeout);boolsuccess=task.IsCompleted;#elseIAsyncResultresult=PingSocket.BeginConnect(Host,Port,null,null);boolsuccess=result.AsyncWaitHandle.WaitOne(_ConnectTimeout,true);#endifif(!success){LastError=S7Consts.errTCPConnectionFailed;}}catch{LastError=S7Consts.errTCPConnectionFailed;};#ifCORE_CLRPingSocket.Dispose();#elsePingSocket.Close();#endif}publicintConnect(stringHost,intPort){LastError=0;if(!Connected){TCPPing(Host,Port);if(LastError==0)try{CreateSocket();TCPSocket.Connect(Host,Port);}catch{LastError=S7Consts.errTCPConnectionFailed;}}returnLastError;}privateintWaitForData(intSize,intTimeout){boolExpired=false;intSizeAvail;intElapsed=Environment.TickCount;LastError=0;try{SizeAvail=TCPSocket.Available;while((SizeAvail<Size)&&(!Expired)){Thread.Sleep(2);SizeAvail=TCPSocket.Available;Expired=Environment.TickCount-Elapsed>Timeout;//Iftimeoutwecleanthebufferif(Expired&&(SizeAvail>0))try{byte[]Flush=newbyte[SizeAvail];TCPSocket.Receive(Flush,0,SizeAvail,SocketFlags.None);}catch{}}}catch{LastError=S7Consts.errTCPDataReceive;}if(Expired){LastError=S7Consts.errTCPDataReceive;}returnLastError;}publicintReceive(byte[]Buffer,intStart,intSize){intBytesRead=0;LastError=WaitForData(Size,_ReadTimeout);if(LastError==0){try{BytesRead=TCPSocket.Receive(Buffer,Start,Size,SocketFlags.None);}catch{LastError=S7Consts.errTCPDataReceive;}if(BytesRead==0)//ConnectionResetbythepeer{LastError=S7Consts.errTCPDataReceive;Close();}}returnLastError;}publicintSend(byte[]Buffer,intSize){LastError=0;try{intBytesSent=TCPSocket.Send(Buffer,Size,SocketFlags.None);}catch{LastError=S7Consts.errTCPDataSend;Close();}returnLastError;}publicboolConnected{get{return(TCPSocket!=null)&&(TCPSocket.Connected);}}publicintReadTimeout{get{return_ReadTimeout;}set{_ReadTimeout=value;}}publicintWriteTimeout{get{return_WriteTimeout;}set{_WriteTimeout=value;}}publicintConnectTimeout{get{return_ConnectTimeout;}set{_ConnectTimeout=value;}}}#endif#endregionpublicstaticclassS7Consts{#region[ExportedConsts]//Errorcodes//------------------------------------------------------------------------------//ERRORS//------------------------------------------------------------------------------publicconstinterrTCPSocketCreation=0x00000001;publicconstinterrTCPConnectionTimeout=0x00000002;publicconstinterrTCPConnectionFailed=0x00000003;publicconstinterrTCPReceiveTimeout=0x00000004;publicconstinterrTCPDataReceive=0x00000005;publicconstinterrTCPSendTimeout=0x00000006;publicconstinterrTCPDataSend=0x00000007;publicconstinterrTCPConnectionReset=0x00000008;publicconstinterrTCPNotConnected=0x00000009;publicconstinterrTCPUnreachableHost=0x00002751;publicconstinterrIsoConnect=0x00010000;//ConnectionerrorpublicconstinterrIsoInvalidPDU=0x00030000;//BadformatpublicconstinterrIsoInvalidDataSize=0x00040000;//BadDatasizepassedtosend/recv:bufferisinvalidpublicconstinterrCliNegotiatingPDU=0x00100000;publicconstinterrCliInvalidParams=0x00200000;publicconstinterrCliJobPending=0x00300000;publicconstinterrCliTooManyItems=0x00400000;publicconstinterrCliInvalidWordLen=0x00500000;publicconstinterrCliPartialDataWritten=0x00600000;publicconstinterrCliSizeOverPDU=0x00700000;publicconstinterrCliInvalidPlcAnswer=0x00800000;publicconstinterrCliAddressOutOfRange=0x00900000;publicconstinterrCliInvalidTransportSize=0x00A00000;publicconstinterrCliWriteDataSizeMismatch=0x00B00000;publicconstinterrCliItemNotAvailable=0x00C00000;publicconstinterrCliInvalidValue=0x00D00000;publicconstinterrCliCannotStartPLC=0x00E00000;publicconstinterrCliAlreadyRun=0x00F00000;publicconstinterrCliCannotStopPLC=0x01000000;publicconstinterrCliCannotCopyRamToRom=0x01100000;publicconstinterrCliCannotCompress=0x01200000;publicconstinterrCliAlreadyStop=0x01300000;publicconstinterrCliFunNotAvailable=0x01400000;publicconstinterrCliUploadSequenceFailed=0x01500000;publicconstinterrCliInvalidDataSizeRecvd=0x01600000;publicconstinterrCliInvalidBlockType=0x01700000;publicconstinterrCliInvalidBlockNumber=0x01800000;publicconstinterrCliInvalidBlockSize=0x01900000;publicconstinterrCliNeedPassword=0x01D00000;publicconstinterrCliInvalidPassword=0x01E00000;publicconstinterrCliNoPasswordToSetOrClear=0x01F00000;publicconstinterrCliJobTimeout=0x02000000;publicconstinterrCliPartialDataRead=0x02100000;publicconstinterrCliBufferTooSmall=0x02200000;publicconstinterrCliFunctionRefused=0x02300000;publicconstinterrCliDestroying=0x02400000;publicconstinterrCliInvalidParamNumber=0x02500000;publicconstinterrCliCannotChangeParam=0x02600000;publicconstinterrCliFunctionNotImplemented=0x02700000;//------------------------------------------------------------------------------//PARAMSLISTFORCOMPATIBILITYWITHSnap7.net.cs//------------------------------------------------------------------------------publicconstInt32p_u16_LocalPort=1;//NotapplicableherepublicconstInt32p_u16_RemotePort=2;publicconstInt32p_i32_PingTimeout=3;publicconstInt32p_i32_SendTimeout=4;publicconstInt32p_i32_RecvTimeout=5;publicconstInt32p_i32_WorkInterval=6;//NotapplicableherepublicconstInt32p_u16_SrcRef=7;//NotapplicableherepublicconstInt32p_u16_DstRef=8;//NotapplicableherepublicconstInt32p_u16_SrcTSap=9;//NotapplicableherepublicconstInt32p_i32_PDURequest=10;publicconstInt32p_i32_MaxClients=11;//NotapplicableherepublicconstInt32p_i32_BSendTimeout=12;//NotapplicableherepublicconstInt32p_i32_BRecvTimeout=13;//NotapplicableherepublicconstInt32p_u32_RecoveryTime=14;//NotapplicableherepublicconstInt32p_u32_KeepAliveTime=15;//Notapplicablehere//AreaIDpublicconstbyteS7AreaPE=0x81;publicconstbyteS7AreaPA=0x82;publicconstbyteS7AreaMK=0x83;publicconstbyteS7AreaDB=0x84;publicconstbyteS7AreaCT=0x1C;publicconstbyteS7AreaTM=0x1D;//WordLengthpublicconstintS7WLBit=0x01;publicconstintS7WLByte=0x02;publicconstintS7WLChar=0x03;publicconstintS7WLWord=0x04;publicconstintS7WLInt=0x05;publicconstintS7WLDWord=0x06;publicconstintS7WLDInt=0x07;publicconstintS7WLReal=0x08;publicconstintS7WLCounter=0x1C;publicconstintS7WLTimer=0x1D;//PLCStatuspublicconstintS7CpuStatusUnknown=0x00;publicconstintS7CpuStatusRun=0x08;publicconstintS7CpuStatusStop=0x04;[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructS7Tag{publicInt32Area;publicInt32DBNumber;publicInt32Start;publicInt32Elements;publicInt32WordLen;}#endregion}publicclassS7Timer{#regionS7TimerTimeSpanpt;TimeSpanet;boolinput=false;boolq=false;publicS7Timer(byte[]buff,intposition){if(position+12<buff.Length){return;}else{SetTimer(newList<byte>(buff).GetRange(position,16).ToArray());}}publicS7Timer(byte[]buff){SetTimer(buff);}privatevoidSetTimer(byte[]buff){if(buff.Length!=12){this.pt=newTimeSpan(0);this.et=newTimeSpan(0);}else{Int32resPT;resPT=buff[0];resPT<<=8;resPT+=buff[1];resPT<<=8;resPT+=buff[2];resPT<<=8;resPT+=buff[3];this.pt=newTimeSpan(0,0,0,0,resPT);Int32resET;resET=buff[4];resET<<=8;resET+=buff[5];resET<<=8;resET+=buff[6];resET<<=8;resET+=buff[7];this.et=newTimeSpan(0,0,0,0,resET);this.input=(buff[8]&0x01)==0x01;this.q=(buff[8]&0x02)==0x02;}}publicTimeSpanPT{get{returnpt;}}publicTimeSpanET{get{returnet;}}publicboolIN{get{returninput;}}publicboolQ{get{returnq;}}#endregion}publicstaticclassS7{#region[HelpFunctions]privatestaticInt64bias=621355968000000000;//"decimicros"between0001-01-0100:00:00and1970-01-0100:00:00privatestaticintBCDtoByte(byteB){return((B>>4)*10)+(B&0x0F);}privatestaticbyteByteToBCD(intValue){return(byte)(((Value/10)<<4)|(Value%10));}privatestaticbyte[]CopyFrom(byte[]Buffer,intPos,intSize){byte[]Result=newbyte[Size];Array.Copy(Buffer,Pos,Result,0,Size);returnResult;}publicstaticintDataSizeByte(intWordLength){switch(WordLength){caseS7Consts.S7WLBit:return1;//S7sends1byteperbitcaseS7Consts.S7WLByte:return1;caseS7Consts.S7WLChar:return1;caseS7Consts.S7WLWord:return2;caseS7Consts.S7WLDWord:return4;caseS7Consts.S7WLInt:return2;caseS7Consts.S7WLDInt:return4;caseS7Consts.S7WLReal:return4;caseS7Consts.S7WLCounter:return2;caseS7Consts.S7WLTimer:return2;default:return0;}}#regionGet/SetthebitatPos.BitpublicstaticboolGetBitAt(byte[]Buffer,intPos,intBit){byte[]Mask={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};if(Bit<0)Bit=0;if(Bit>7)Bit=7;return(Buffer[Pos]&Mask[Bit])!=0;}publicstaticvoidSetBitAt(refbyte[]Buffer,intPos,intBit,boolValue){byte[]Mask={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};if(Bit<0)Bit=0;if(Bit>7)Bit=7;if(Value)Buffer[Pos]=(byte)(Buffer[Pos]|Mask[Bit]);elseBuffer[Pos]=(byte)(Buffer[Pos]&~Mask[Bit]);}#endregion#regionGet/Set8bitsignedvalue(S7SInt)-128..127publicstaticintGetSIntAt(byte[]Buffer,intPos){intValue=Buffer[Pos];if(Value<128)returnValue;elsereturn(int)(Value-256);}publicstaticvoidSetSIntAt(byte[]Buffer,intPos,intValue){if(Value<-128)Value=-128;if(Value>127)Value=127;Buffer[Pos]=(byte)Value;}#endregion#regionGet/Set16bitsignedvalue(S7int)-32768..32767publicstaticshortGetIntAt(byte[]Buffer,intPos){return(short)((Buffer[Pos]<<8)|Buffer[Pos+1]);}publicstaticvoidSetIntAt(byte[]Buffer,intPos,Int16Value){Buffer[Pos]=(byte)(Value>>8);Buffer[Pos+1]=(byte)(Value&0x00FF);}#endregion#regionGet/Set32bitsignedvalue(S7DInt)-2147483648..2147483647publicstaticintGetDIntAt(byte[]Buffer,intPos){intResult;Result=Buffer[Pos];Result<<=8;Result+=Buffer[Pos+1];Result<<=8;Result+=Buffer[Pos+2];Result<<=8;Result+=Buffer[Pos+3];returnResult;}publicstaticvoidSetDIntAt(byte[]Buffer,intPos,intValue){Buffer[Pos+3]=(byte)(Value&0xFF);Buffer[Pos+2]=(byte)((Value>>8)&0xFF);Buffer[Pos+1]=(byte)((Value>>16)&0xFF);Buffer[Pos]=(byte)((Value>>24)&0xFF);}#endregion#regionGet/Set64bitsignedvalue(S7LInt)-9223372036854775808..9223372036854775807publicstaticInt64GetLIntAt(byte[]Buffer,intPos){Int64Result;Result=Buffer[Pos];Result<<=8;Result+=Buffer[Pos+1];Result<<=8;Result+=Buffer[Pos+2];Result<<=8;Result+=Buffer[Pos+3];Result<<=8;Result+=Buffer[Pos+4];Result<<=8;Result+=Buffer[Pos+5];Result<<=8;Result+=Buffer[Pos+6];Result<<=8;Result+=Buffer[Pos+7];returnResult;}publicstaticvoidSetLIntAt(byte[]Buffer,intPos,Int64Value){Buffer[Pos+7]=(byte)(Value&0xFF);Buffer[Pos+6]=(byte)((Value>>8)&0xFF);Buffer[Pos+5]=(byte)((Value>>16)&0xFF);Buffer[Pos+4]=(byte)((Value>>24)&0xFF);Buffer[Pos+3]=(byte)((Value>>32)&0xFF);Buffer[Pos+2]=(byte)((Value>>40)&0xFF);Buffer[Pos+1]=(byte)((Value>>48)&0xFF);Buffer[Pos]=(byte)((Value>>56)&0xFF);}#endregion#regionGet/Set8bitunsignedvalue(S7USInt)0..255publicstaticbyteGetUSIntAt(byte[]Buffer,intPos){returnBuffer[Pos];}publicstaticvoidSetUSIntAt(byte[]Buffer,intPos,byteValue){Buffer[Pos]=Value;}#endregion#regionGet/Set16bitunsignedvalue(S7UInt)0..65535publicstaticUInt16GetUIntAt(byte[]Buffer,intPos){return(UInt16)((Buffer[Pos]<<8)|Buffer[Pos+1]);}publicstaticvoidSetUIntAt(byte[]Buffer,intPos,UInt16Value){Buffer[Pos]=(byte)(Value>>8);Buffer[Pos+1]=(byte)(Value&0x00FF);}#endregion#regionGet/Set32bitunsignedvalue(S7UDInt)0..4294967296publicstaticUInt32GetUDIntAt(byte[]Buffer,intPos){UInt32Result;Result=Buffer[Pos];Result<<=8;Result|=Buffer[Pos+1];Result<<=8;Result|=Buffer[Pos+2];Result<<=8;Result|=Buffer[Pos+3];returnResult;}publicstaticvoidSetUDIntAt(byte[]Buffer,intPos,UInt32Value){Buffer[Pos+3]=(byte)(Value&0xFF);Buffer[Pos+2]=(byte)((Value>>8)&0xFF);Buffer[Pos+1]=(byte)((Value>>16)&0xFF);Buffer[Pos]=(byte)((Value>>24)&0xFF);}#endregion#regionGet/Set64bitunsignedvalue(S7ULint)0..18446744073709551616publicstaticUInt64GetULIntAt(byte[]Buffer,intPos){UInt64Result;Result=Buffer[Pos];Result<<=8;Result|=Buffer[Pos+1];Result<<=8;Result|=Buffer[Pos+2];Result<<=8;Result|=Buffer[Pos+3];Result<<=8;Result|=Buffer[Pos+4];Result<<=8;Result|=Buffer[Pos+5];Result<<=8;Result|=Buffer[Pos+6];Result<<=8;Result|=Buffer[Pos+7];returnResult;}publicstaticvoidSetULintAt(byte[]Buffer,intPos,UInt64Value){Buffer[Pos+7]=(byte)(Value&0xFF);Buffer[Pos+6]=(byte)((Value>>8)&0xFF);Buffer[Pos+5]=(byte)((Value>>16)&0xFF);Buffer[Pos+4]=(byte)((Value>>24)&0xFF);Buffer[Pos+3]=(byte)((Value>>32)&0xFF);Buffer[Pos+2]=(byte)((Value>>40)&0xFF);Buffer[Pos+1]=(byte)((Value>>48)&0xFF);Buffer[Pos]=(byte)((Value>>56)&0xFF);}#endregion#regionGet/Set8bitword(S7Byte)16#00..16#FFpublicstaticbyteGetByteAt(byte[]Buffer,intPos){returnBuffer[Pos];}publicstaticvoidSetByteAt(byte[]Buffer,intPos,byteValue){Buffer[Pos]=Value;}#endregion#regionGet/Set16bitword(S7Word)16#0000..16#FFFFpublicstaticUInt16GetWordAt(byte[]Buffer,intPos){returnGetUIntAt(Buffer,Pos);}publicstaticvoidSetWordAt(byte[]Buffer,intPos,UInt16Value){SetUIntAt(Buffer,Pos,Value);}#endregion#regionGet/Set32bitword(S7DWord)16#00000000..16#FFFFFFFFpublicstaticUInt32GetDWordAt(byte[]Buffer,intPos){returnGetUDIntAt(Buffer,Pos);}publicstaticvoidSetDWordAt(byte[]Buffer,intPos,UInt32Value){SetUDIntAt(Buffer,Pos,Value);}#endregion#regionGet/Set64bitword(S7LWord)16#0000000000000000..16#FFFFFFFFFFFFFFFFpublicstaticUInt64GetLWordAt(byte[]Buffer,intPos){returnGetULIntAt(Buffer,Pos);}publicstaticvoidSetLWordAt(byte[]Buffer,intPos,UInt64Value){SetULintAt(Buffer,Pos,Value);}#endregion#regionGet/Set32bitfloatingpointnumber(S7Real)(RangeofSingle)publicstaticSingleGetRealAt(byte[]Buffer,intPos){UInt32Value=GetUDIntAt(Buffer,Pos);byte[]bytes=BitConverter.GetBytes(Value);returnBitConverter.ToSingle(bytes,0);}publicstaticvoidSetRealAt(byte[]Buffer,intPos,SingleValue){byte[]FloatArray=BitConverter.GetBytes(Value);Buffer[Pos]=FloatArray[3];Buffer[Pos+1]=FloatArray[2];Buffer[Pos+2]=FloatArray[1];Buffer[Pos+3]=FloatArray[0];}#endregion#regionGet/Set64bitfloatingpointnumber(S7LReal)(RangeofDouble)publicstaticDoubleGetLRealAt(byte[]Buffer,intPos){UInt64Value=GetULIntAt(Buffer,Pos);byte[]bytes=BitConverter.GetBytes(Value);returnBitConverter.ToDouble(bytes,0);}publicstaticvoidSetLRealAt(byte[]Buffer,intPos,DoubleValue){byte[]FloatArray=BitConverter.GetBytes(Value);Buffer[Pos]=FloatArray[7];Buffer[Pos+1]=FloatArray[6];Buffer[Pos+2]=FloatArray[5];Buffer[Pos+3]=FloatArray[4];Buffer[Pos+4]=FloatArray[3];Buffer[Pos+5]=FloatArray[2];Buffer[Pos+6]=FloatArray[1];Buffer[Pos+7]=FloatArray[0];}#endregion#regionGet/SetDateTime(S7DATE_AND_TIME)publicstaticDateTimeGetDateTimeAt(byte[]Buffer,intPos){intYear,Month,Day,Hour,Min,Sec,MSec;Year=BCDtoByte(Buffer[Pos]);if(Year<90)Year+=2000;elseYear+=1900;Month=BCDtoByte(Buffer[Pos+1]);Day=BCDtoByte(Buffer[Pos+2]);Hour=BCDtoByte(Buffer[Pos+3]);Min=BCDtoByte(Buffer[Pos+4]);Sec=BCDtoByte(Buffer[Pos+5]);MSec=(BCDtoByte(Buffer[Pos+6])*10)+(BCDtoByte(Buffer[Pos+7])/10);try{returnnewDateTime(Year,Month,Day,Hour,Min,Sec,MSec);}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetDateTimeAt(byte[]Buffer,intPos,DateTimeValue){intYear=Value.Year;intMonth=Value.Month;intDay=Value.Day;intHour=Value.Hour;intMin=Value.Minute;intSec=Value.Second;intDow=(int)Value.DayOfWeek+1;//MSecH=FirsttwodigitsofmilisecondsintMsecH=Value.Millisecond/10;//MSecL=LastdigitofmilisecondsintMsecL=Value.Millisecond%10;if(Year>1999)Year-=2000;Buffer[Pos]=ByteToBCD(Year);Buffer[Pos+1]=ByteToBCD(Month);Buffer[Pos+2]=ByteToBCD(Day);Buffer[Pos+3]=ByteToBCD(Hour);Buffer[Pos+4]=ByteToBCD(Min);Buffer[Pos+5]=ByteToBCD(Sec);Buffer[Pos+6]=ByteToBCD(MsecH);Buffer[Pos+7]=ByteToBCD(MsecL*10+Dow);}#endregion#regionGet/SetDATE(S7DATE)publicstaticDateTimeGetDateAt(byte[]Buffer,intPos){try{returnnewDateTime(1990,1,1).AddDays(GetIntAt(Buffer,Pos));}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetDateAt(byte[]Buffer,intPos,DateTimeValue){SetIntAt(Buffer,Pos,(Int16)(Value-newDateTime(1990,1,1)).Days);}#endregion#regionGet/SetTOD(S7TIME_OF_DAY)publicstaticDateTimeGetTODAt(byte[]Buffer,intPos){try{returnnewDateTime(0).AddMilliseconds(S7.GetDIntAt(Buffer,Pos));}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetTODAt(byte[]Buffer,intPos,DateTimeValue){TimeSpanTime=Value.TimeOfDay;SetDIntAt(Buffer,Pos,(Int32)Math.Round(Time.TotalMilliseconds));}#endregion#regionGet/SetLTOD(S71500LONGTIME_OF_DAY)publicstaticDateTimeGetLTODAt(byte[]Buffer,intPos){//.NETTick=100ns,S71500Tick=1nstry{returnnewDateTime(Math.Abs(GetLIntAt(Buffer,Pos)/100));}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetLTODAt(byte[]Buffer,intPos,DateTimeValue){TimeSpanTime=Value.TimeOfDay;SetLIntAt(Buffer,Pos,(Int64)Time.Ticks*100);}#endregion#regionGET/SETLDT(S71500LongDateandTime)publicstaticDateTimeGetLDTAt(byte[]Buffer,intPos){try{returnnewDateTime((GetLIntAt(Buffer,Pos)/100)+bias);}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetLDTAt(byte[]Buffer,intPos,DateTimeValue){SetLIntAt(Buffer,Pos,(Value.Ticks-bias)*100);}#endregion#regionGet/SetDTL(S71200/1500DateandTime)//ThankstoJohanCardoenforGetDTLAtpublicstaticDateTimeGetDTLAt(byte[]Buffer,intPos){intYear,Month,Day,Hour,Min,Sec,MSec;Year=Buffer[Pos]*256+Buffer[Pos+1];Month=Buffer[Pos+2];Day=Buffer[Pos+3];Hour=Buffer[Pos+5];Min=Buffer[Pos+6];Sec=Buffer[Pos+7];MSec=(int)GetUDIntAt(Buffer,Pos+8)/1000000;try{returnnewDateTime(Year,Month,Day,Hour,Min,Sec,MSec);}catch(System.ArgumentOutOfRangeException){returnnewDateTime(0);}}publicstaticvoidSetDTLAt(byte[]Buffer,intPos,DateTimeValue){shortYear=(short)Value.Year;byteMonth=(byte)Value.Month;byteDay=(byte)Value.Day;byteHour=(byte)Value.Hour;byteMin=(byte)Value.Minute;byteSec=(byte)Value.Second;byteDow=(byte)(Value.DayOfWeek+1);Int32NanoSecs=Value.Millisecond*1000000;varbytes_short=BitConverter.GetBytes(Year);Buffer[Pos]=bytes_short[1];Buffer[Pos+1]=bytes_short[0];Buffer[Pos+2]=Month;Buffer[Pos+3]=Day;Buffer[Pos+4]=Dow;Buffer[Pos+5]=Hour;Buffer[Pos+6]=Min;Buffer[Pos+7]=Sec;SetDIntAt(Buffer,Pos+8,NanoSecs);}#endregion#regionGet/SetString(S7String)//ThankstoPabloAgirrepublicstaticstringGetStringAt(byte[]Buffer,intPos){intsize=(int)Buffer[Pos+1];returnEncoding.UTF8.GetString(Buffer,Pos+2,size);}publicstaticvoidSetStringAt(byte[]Buffer,intPos,intMaxLen,stringValue){intsize=Value.Length;Buffer[Pos]=(byte)MaxLen;Buffer[Pos+1]=(byte)size;Encoding.UTF8.GetBytes(Value,0,size,Buffer,Pos+2);}#endregion#regionGet/SetWString(S7-1500String)publicstaticstringGetWStringAt(byte[]Buffer,intPos){//WStringsize=ncharacters+2Words(firstformaxlength,secondforreallength)//GetthereallengthinWordsintsize=GetIntAt(Buffer,Pos+2);//ExtractstringinUTF-16unicodeBigEndian.returnEncoding.BigEndianUnicode.GetString(Buffer,Pos+4,size*2);}publicstaticvoidSetWStringAt(byte[]Buffer,intPos,intMaxCharNb,stringValue){//Getthelengthinwordsfromnumberofcharactersintsize=Value.Length;//SettheMaxlengthinWordsSetIntAt(Buffer,Pos,(short)MaxCharNb);//SetthereallengthinwordsSetIntAt(Buffer,Pos+2,(short)size);//SettheUTF-16unicodeBigendianString(aftermaxlengthandlength)Encoding.BigEndianUnicode.GetBytes(Value,0,size,Buffer,Pos+4);}#endregion#regionGet/SetArrayofchar(S7ARRAYOFCHARS)publicstaticstringGetCharsAt(byte[]Buffer,intPos,intSize){returnEncoding.UTF8.GetString(Buffer,Pos,Size);}publicstaticvoidSetCharsAt(byte[]Buffer,intPos,stringValue){intMaxLen=Buffer.Length-Pos;//Truncsthestringifthere'snoroomenoughif(MaxLen>Value.Length)MaxLen=Value.Length;Encoding.UTF8.GetBytes(Value,0,MaxLen,Buffer,Pos);}#endregion#regionGet/SetArrayofWChar(S7-1500ARRAYOFCHARS)publicstaticStringGetWCharsAt(byte[]Buffer,intPos,intSizeInCharNb){//ExtractUnicodeUTF-16Big-Endiancharacterfromthebuffer.TousewithWCharDatatype.//Sizetoreadisinbyte.Becareful,1char=2bytesreturnEncoding.BigEndianUnicode.GetString(Buffer,Pos,SizeInCharNb*2);}publicstaticvoidSetWCharsAt(byte[]Buffer,intPos,stringValue){//ComputeMaxlengthincharnumberintMaxLen=(Buffer.Length-Pos)/2;//Truncsthestringifthere'snoroomenoughif(MaxLen>Value.Length)MaxLen=Value.Length;Encoding.BigEndianUnicode.GetBytes(Value,0,MaxLen,Buffer,Pos);}#endregion#regionGet/SetCounterpublicstaticintGetCounter(ushortValue){returnBCDtoByte((byte)Value)*100+BCDtoByte((byte)(Value>>8));}publicstaticintGetCounterAt(ushort[]Buffer,intIndex){returnGetCounter(Buffer[Index]);}publicstaticushortToCounter(intValue){return(ushort)(ByteToBCD(Value/100)+(ByteToBCD(Value%100)<<8));}publicstaticvoidSetCounterAt(ushort[]Buffer,intPos,intValue){Buffer[Pos]=ToCounter(Value);}#endregion#regionGet/SetTimerpublicstaticS7TimerGetS7TimerAt(byte[]Buffer,intPos){returnnewS7Timer(newList<byte>(Buffer).GetRange(Pos,12).ToArray());}publicstaticvoidSetS7TimespanAt(byte[]Buffer,intPos,TimeSpanValue){SetDIntAt(Buffer,Pos,(Int32)Value.TotalMilliseconds);}publicstaticTimeSpanGetS7TimespanAt(byte[]Buffer,intpos){if(Buffer.Length<pos+4){returnnewTimeSpan();}Int32a;a=Buffer[pos+0];a<<=8;a+=Buffer[pos+1];a<<=8;a+=Buffer[pos+2];a<<=8;a+=Buffer[pos+3];TimeSpansp=newTimeSpan(0,0,0,0,a);returnsp;}publicstaticTimeSpanGetLTimeAt(byte[]Buffer,intpos){//LTimesize:64bits(8octets)//Caseifthebufferistoosmallif(Buffer.Length<pos+8)returnnewTimeSpan();try{//ExtractandConvertnumberofnanosecondstotick(1tick=100nanoseconds)returnTimeSpan.FromTicks(GetLIntAt(Buffer,pos)/100);}catch(Exception){returnnewTimeSpan();}}publicstaticvoidSetLTimeAt(byte[]Buffer,intPos,TimeSpanValue){SetLIntAt(Buffer,Pos,(long)(Value.Ticks*100));}#endregion#endregion[HelpFunctions]}publicclassS7MultiVar{#region[MultiRead/WriteHelper]privateS7ClientFClient;privateGCHandle[]Handles=newGCHandle[S7Client.MaxVars];privateintCount=0;privateS7Client.S7DataItem[]Items=newS7Client.S7DataItem[S7Client.MaxVars];publicint[]Results=newint[S7Client.MaxVars];privateboolAdjustWordLength(intArea,refintWordLen,refintAmount,refintStart){//CalcWordsizeintWordSize=S7.DataSizeByte(WordLen);if(WordSize==0)returnfalse;if(Area==S7Consts.S7AreaCT)WordLen=S7Consts.S7WLCounter;if(Area==S7Consts.S7AreaTM)WordLen=S7Consts.S7WLTimer;if(WordLen==S7Consts.S7WLBit)Amount=1;//Only1bitcanbetransferredattimeelse{if((WordLen!=S7Consts.S7WLCounter)&&(WordLen!=S7Consts.S7WLTimer)){Amount=Amount*WordSize;Start=Start*8;WordLen=S7Consts.S7WLByte;}}returntrue;}publicS7MultiVar(S7ClientClient){FClient=Client;for(intc=0;c<S7Client.MaxVars;c++)Results[c]=(int)S7Consts.errCliItemNotAvailable;}~S7MultiVar(){Clear();}publicboolAdd<T>(S7Consts.S7TagTag,refT[]Buffer,intOffset){returnAdd(Tag.Area,Tag.WordLen,Tag.DBNumber,Tag.Start,Tag.Elements,refBuffer,Offset);}publicboolAdd<T>(S7Consts.S7TagTag,refT[]Buffer){returnAdd(Tag.Area,Tag.WordLen,Tag.DBNumber,Tag.Start,Tag.Elements,refBuffer);}publicboolAdd<T>(Int32Area,Int32WordLen,Int32DBNumber,Int32Start,Int32Amount,refT[]Buffer){returnAdd(Area,WordLen,DBNumber,Start,Amount,refBuffer,0);}publicboolAdd<T>(Int32Area,Int32WordLen,Int32DBNumber,Int32Start,Int32Amount,refT[]Buffer,intOffset){if(Count<S7Client.MaxVars){if(AdjustWordLength(Area,refWordLen,refAmount,refStart)){Items[Count].Area=Area;Items[Count].WordLen=WordLen;Items[Count].Result=(int)S7Consts.errCliItemNotAvailable;Items[Count].DBNumber=DBNumber;Items[Count].Start=Start;Items[Count].Amount=Amount;GCHandlehandle=GCHandle.Alloc(Buffer,GCHandleType.Pinned);#ifWINDOWS_UWP||NETFX_COREif(IntPtr.Size==4)Items[Count].pData=(IntPtr)(handle.AddrOfPinnedObject().ToInt32()+Offset*Marshal.SizeOf<T>());elseItems[Count].pData=(IntPtr)(handle.AddrOfPinnedObject().ToInt64()+Offset*Marshal.SizeOf<T>());#elseif(IntPtr.Size==4)Items[Count].pData=(IntPtr)(handle.AddrOfPinnedObject().ToInt32()+Offset*Marshal.SizeOf(typeof(T)));elseItems[Count].pData=(IntPtr)(handle.AddrOfPinnedObject().ToInt64()+Offset*Marshal.SizeOf(typeof(T)));#endifHandles[Count]=handle;Count++;returntrue;}elsereturnfalse;}elsereturnfalse;}publicintRead(){intFunctionResult;intGlobalResult=(int)S7Consts.errCliFunctionRefused;try{if(Count>0){FunctionResult=FClient.ReadMultiVars(Items,Count);if(FunctionResult==0)for(intc=0;c<S7Client.MaxVars;c++)Results[c]=Items[c].Result;GlobalResult=FunctionResult;}elseGlobalResult=(int)S7Consts.errCliFunctionRefused;}finally{Clear();//handlesarenomoreneededandMUSTbefreed}returnGlobalResult;}publicintWrite(){intFunctionResult;intGlobalResult=(int)S7Consts.errCliFunctionRefused;try{if(Count>0){FunctionResult=FClient.WriteMultiVars(Items,Count);if(FunctionResult==0)for(intc=0;c<S7Client.MaxVars;c++)Results[c]=Items[c].Result;GlobalResult=FunctionResult;}elseGlobalResult=(int)S7Consts.errCliFunctionRefused;}finally{Clear();//handlesarenomoreneededandMUSTbefreed}returnGlobalResult;}publicvoidClear(){for(intc=0;c<Count;c++){if(Handles[c]!=null)Handles[c].Free();}Count=0;}#endregion}publicclassS7Client{#region[ConstantsandTypeDefs]//BlocktypepublicconstintBlock_OB=0x38;publicconstintBlock_DB=0x41;publicconstintBlock_SDB=0x42;publicconstintBlock_FC=0x43;publicconstintBlock_SFC=0x44;publicconstintBlock_FB=0x45;publicconstintBlock_SFB=0x46;//SubBlockTypepublicconstbyteSubBlk_OB=0x08;publicconstbyteSubBlk_DB=0x0A;publicconstbyteSubBlk_SDB=0x0B;publicconstbyteSubBlk_FC=0x0C;publicconstbyteSubBlk_SFC=0x0D;publicconstbyteSubBlk_FB=0x0E;publicconstbyteSubBlk_SFB=0x0F;//BlocklanguagespublicconstbyteBlockLangAWL=0x01;publicconstbyteBlockLangKOP=0x02;publicconstbyteBlockLangFUP=0x03;publicconstbyteBlockLangSCL=0x04;publicconstbyteBlockLangDB=0x05;publicconstbyteBlockLangGRAPH=0x06;//Maxnumberofvars(multiread/write)publicstaticreadonlyintMaxVars=20;//ResulttransportsizeconstbyteTS_ResBit=0x03;constbyteTS_ResByte=0x04;constbyteTS_ResInt=0x05;constbyteTS_ResReal=0x07;constbyteTS_ResOctet=0x09;constushortCode7Ok=0x0000;constushortCode7AddressOutOfRange=0x0005;constushortCode7InvalidTransportSize=0x0006;constushortCode7WriteDataSizeMismatch=0x0007;constushortCode7ResItemNotAvailable=0x000A;constushortCode7ResItemNotAvailable1=0xD209;constushortCode7InvalidValue=0xDC01;constushortCode7NeedPassword=0xD241;constushortCode7InvalidPassword=0xD602;constushortCode7NoPasswordToClear=0xD604;constushortCode7NoPasswordToSet=0xD605;constushortCode7FunNotAvailable=0x8104;constushortCode7DataOverPDU=0x8500;//ClientConnectionTypepublicstaticreadonlyUInt16CONNTYPE_PG=0x01;//ConnecttothePLCasaPGpublicstaticreadonlyUInt16CONNTYPE_OP=0x02;//ConnecttothePLCasanOPpublicstaticreadonlyUInt16CONNTYPE_BASIC=0x03;//Basicconnectionpublicint_LastError=0;publicstructS7DataItem{publicintArea;publicintWordLen;publicintResult;publicintDBNumber;publicintStart;publicintAmount;publicIntPtrpData;}//OrderCode+VersionpublicstructS7OrderCode{publicstringCode;//suchas"6ES7 151-8AB01-0AB0"publicbyteV1;//Version1stdigitpublicbyteV2;//Version2nddigitpublicbyteV3;//Version3thdigit};//CPUInfopublicstructS7CpuInfo{publicstringModuleTypeName;publicstringSerialNumber;publicstringASName;publicstringCopyright;publicstringModuleName;}publicstructS7CpInfo{publicintMaxPduLength;publicintMaxConnections;publicintMaxMpiRate;publicintMaxBusRate;};//BlockList[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructS7BlocksList{publicInt32OBCount;publicInt32FBCount;publicInt32FCCount;publicInt32SFBCount;publicInt32SFCCount;publicInt32DBCount;publicInt32SDBCount;};//ManagedBlockInfopublicstructS7BlockInfo{publicintBlkType;publicintBlkNumber;publicintBlkLang;publicintBlkFlags;publicintMC7Size;//TherealsizeinbytespublicintLoadSize;publicintLocalData;publicintSBBLength;publicintCheckSum;publicintVersion;//CharsinfopublicstringCodeDate;publicstringIntfDate;publicstringAuthor;publicstringFamily;publicstringHeader;};//See§33.1of"System Software for S7-300/400 System and Standard Functions"//andseeSFC51descriptiontoo[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructSZL_HEADER{publicUInt16LENTHDR;publicUInt16N_DR;};[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructS7SZL{publicSZL_HEADERHeader;[MarshalAs(UnmanagedType.ByValArray)]publicbyte[]Data;};//SZLListofavailableSZLIDs:sameasSZLbutListitemsarebig-endianadjusted[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructS7SZLList{publicSZL_HEADERHeader;[MarshalAs(UnmanagedType.ByValArray,SizeConst=0x2000-2)]publicUInt16[]Data;};//S7Protection//See§33.19of"System Software for S7-300/400 System and Standard Functions"publicstructS7Protection{publicushortsch_schal;publicushortsch_par;publicushortsch_rel;publicushortbart_sch;publicushortanl_sch;};#endregion#region[S7Telegrams]//ISOConnectionRequesttelegram(containsalsoISOHeaderandCOTPHeader)byte[]ISO_CR={//TPKT(RFC1006Header)0x03,//RFC1006ID(3)0x00,//Reserved,always00x00,//Highpartofpacketlenght(entireframe,payloadandTPDUincluded)0x16,//Lowpartofpacketlenght(entireframe,payloadandTPDUincluded)//COTP(ISO8073Header)0x11,//PDUSizeLength0xE0,//CR-ConnectionRequestID0x00,//DstReferenceHI0x00,//DstReferenceLO0x00,//SrcReferenceHI0x01,//SrcReferenceLO0x00,//Class+OptionsFlags0xC0,//PDUMaxLengthID0x01,//PDUMaxLengthHI0x0A,//PDUMaxLengthLO0xC1,//SrcTSAPIdentifier0x02,//SrcTSAPLength(2bytes)0x01,//SrcTSAPHI(willbeoverwritten)0x00,//SrcTSAPLO(willbeoverwritten)0xC2,//DstTSAPIdentifier0x02,//DstTSAPLength(2bytes)0x01,//DstTSAPHI(willbeoverwritten)0x02//DstTSAPLO(willbeoverwritten)};//TPKT+ISOCOTPHeader(ConnectionOrientedTransportProtocol)byte[]TPKT_ISO={//7bytes0x03,0x00,0x00,0x1f,//TelegramLength(DataSize+31or35)0x02,0xf0,0x80//COTP(seeaboveforinfo)};//S7PDUNegotiationTelegram(containsalsoISOHeaderandCOTPHeader)byte[]S7_PN={0x03,0x00,0x00,0x19,0x02,0xf0,0x80,//TPKT+COTP(seeaboveforinfo)0x32,0x01,0x00,0x00,0x04,0x00,0x00,0x08,0x00,0x00,0xf0,0x00,0x00,0x01,0x00,0x01,0x00,0x1e//PDULengthRequested=HI-LOHereDefault480bytes};//S7Read/WriteRequestHeader(containsalsoISOHeaderandCOTPHeader)byte[]S7_RW={//31-35bytes0x03,0x00,0x00,0x1f,//TelegramLength(DataSize+31or35)0x02,0xf0,0x80,//COTP(seeaboveforinfo)0x32,//S7ProtocolID0x01,//JobType0x00,0x00,//Redundancyidentification0x05,0x00,//PDUReference0x00,0x0e,//ParametersLength0x00,0x00,//DataLength=Size(bytes)+40x04,//Function4ReadVar,5WriteVar0x01,//Itemscount0x12,//Varspec.0x0a,//Lengthofremainingbytes0x10,//SyntaxID(byte)S7Consts.S7WLByte,//TransportSizeidx=220x00,0x00,//NumElements0x00,0x00,//DBNumber(ifany,else0)0x84,//AreaType0x00,0x00,0x00,//AreaOffset//WRarea0x00,//Reserved0x04,//Transportsize0x00,0x00,//DataLength*8(ifnotbitortimerorcounter)};privatestaticintSize_RD=31;//HeaderSizewhenReadingprivatestaticintSize_WR=35;//HeaderSizewhenWriting//S7VariableMultiReadHeaderbyte[]S7_MRD_HEADER={0x03,0x00,0x00,0x1f,//TelegramLength0x02,0xf0,0x80,//COTP(seeaboveforinfo)0x32,//S7ProtocolID0x01,//JobType0x00,0x00,//Redundancyidentification0x05,0x00,//PDUReference0x00,0x0e,//ParametersLength0x00,0x00,//DataLength=Size(bytes)+40x04,//Function4ReadVar,5WriteVar0x01//Itemscount(idx18)};//S7VariableMultiReadItembyte[]S7_MRD_ITEM={0x12,//Varspec.0x0a,//Lengthofremainingbytes0x10,//SyntaxID(byte)S7Consts.S7WLByte,//TransportSizeidx=30x00,0x00,//NumElements0x00,0x00,//DBNumber(ifany,else0)0x84,//AreaType0x00,0x00,0x00//AreaOffset};//S7VariableMultiWriteHeaderbyte[]S7_MWR_HEADER={0x03,0x00,0x00,0x1f,//TelegramLength0x02,0xf0,0x80,//COTP(seeaboveforinfo)0x32,//S7ProtocolID0x01,//JobType0x00,0x00,//Redundancyidentification0x05,0x00,//PDUReference0x00,0x0e,//ParametersLength(idx13)0x00,0x00,//DataLength=Size(bytes)+4(idx15)0x05,//Function5WriteVar0x01//Itemscount(idx18)};//S7VariableMultiWriteItem(Param)byte[]S7_MWR_PARAM={0x12,//Varspec.0x0a,//Lengthofremainingbytes0x10,//SyntaxID(byte)S7Consts.S7WLByte,//TransportSizeidx=30x00,0x00,//NumElements0x00,0x00,//DBNumber(ifany,else0)0x84,//AreaType0x00,0x00,0x00,//AreaOffset};//SZLFirsttelegramrequestbyte[]S7_SZL_FIRST={0x03,0x00,0x00,0x21,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x05,0x00,//Sequenceout0x00,0x08,0x00,0x08,0x00,0x01,0x12,0x04,0x11,0x44,0x01,0x00,0xff,0x09,0x00,0x04,0x00,0x00,//ID(29)0x00,0x00//Index(31)};//SZLNexttelegramrequestbyte[]S7_SZL_NEXT={0x03,0x00,0x00,0x21,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x06,0x00,0x00,0x0c,0x00,0x04,0x00,0x01,0x12,0x08,0x12,0x44,0x01,0x01,//Sequence0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00};//GetDate/Timerequestbyte[]S7_GET_DT={0x03,0x00,0x00,0x1d,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x38,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x12,0x04,0x11,0x47,0x01,0x00,0x0a,0x00,0x00,0x00};//SetDate/Timecommandbyte[]S7_SET_DT={0x03,0x00,0x00,0x27,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x89,0x03,0x00,0x08,0x00,0x0e,0x00,0x01,0x12,0x04,0x11,0x47,0x02,0x00,0xff,0x09,0x00,0x0a,0x00,0x19,//HipartofYear(idx=30)0x13,//LopartofYear0x12,//Month0x06,//Day0x17,//Hour0x37,//Min0x13,//Sec0x00,0x01//ms+Dayofweek};//S7SetSessionPasswordbyte[]S7_SET_PWD={0x03,0x00,0x00,0x25,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x27,0x00,0x00,0x08,0x00,0x0c,0x00,0x01,0x12,0x04,0x11,0x45,0x01,0x00,0xff,0x09,0x00,0x08,//8CharEncodedPassword0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//S7ClearSessionPasswordbyte[]S7_CLR_PWD={0x03,0x00,0x00,0x1d,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x29,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x12,0x04,0x11,0x45,0x02,0x00,0x0a,0x00,0x00,0x00};//S7STOPrequestbyte[]S7_STOP={0x03,0x00,0x00,0x21,0x02,0xf0,0x80,0x32,0x01,0x00,0x00,0x0e,0x00,0x00,0x10,0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x09,0x50,0x5f,0x50,0x52,0x4f,0x47,0x52,0x41,0x4d};//S7HOTStartrequestbyte[]S7_HOT_START={0x03,0x00,0x00,0x25,0x02,0xf0,0x80,0x32,0x01,0x00,0x00,0x0c,0x00,0x00,0x14,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0x00,0x00,0x09,0x50,0x5f,0x50,0x52,0x4f,0x47,0x52,0x41,0x4d};//S7COLDStartrequestbyte[]S7_COLD_START={0x03,0x00,0x00,0x27,0x02,0xf0,0x80,0x32,0x01,0x00,0x00,0x0f,0x00,0x00,0x16,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0x00,0x02,0x43,0x20,0x09,0x50,0x5f,0x50,0x52,0x4f,0x47,0x52,0x41,0x4d};constbytepduStart=0x28;//CPUstartconstbytepduStop=0x29;//CPUstopconstbytepduAlreadyStarted=0x02;//CPUalreadyinrunmodeconstbytepduAlreadyStopped=0x07;//CPUalreadyinstopmode//S7GetPLCStatusbyte[]S7_GET_STAT={0x03,0x00,0x00,0x21,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x2c,0x00,0x00,0x08,0x00,0x08,0x00,0x01,0x12,0x04,0x11,0x44,0x01,0x00,0xff,0x09,0x00,0x04,0x04,0x24,0x00,0x00};//S7GetBlockInfoRequestHeader(containsalsoISOHeaderandCOTPHeader)byte[]S7_BI={0x03,0x00,0x00,0x25,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x05,0x00,0x00,0x08,0x00,0x0c,0x00,0x01,0x12,0x04,0x11,0x43,0x03,0x00,0xff,0x09,0x00,0x08,0x30,0x41,//BlockType0x30,0x30,0x30,0x30,0x30,//ASCIIBlockNumber0x41};//S7ListBlocksRequestHeaderbyte[]S7_LIST_BLOCKS={0x03,0x00,0x00,0x1d,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x12,0x04,0x11,0x43,0x01,//0x430x01=ListBlocks0x00,0x0a,0x00,0x00,0x00};//S7ListBlocksOfTypeRequestHeaderbyte[]S7_LIST_BLOCKS_OF_TYPE={0x03,0x00,0x00,0x1f,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x06,0x00,0x01,0x12,0x04,0x11,0x43,0x02,//0x430x02=ListBlocksOfType0x00//...appendReqData};#endregion#region[Internals]//DefaultsprivatestaticintISOTCP=102;//ISOTCPPortprivatestaticintMinPduSize=16;privatestaticintMinPduSizeToRequest=240;privatestaticintMaxPduSizeToRequest=960;privatestaticintDefaultTimeout=2000;privatestaticintIsoHSize=7;//TPKT+COTPHeaderSize//Propertiesprivateint_PDULength=0;privateint_PduSizeRequested=480;privateint_PLCPort=ISOTCP;privateint_RecvTimeout=DefaultTimeout;privateint_SendTimeout=DefaultTimeout;privateint_ConnTimeout=DefaultTimeout;//PrivatesprivatestringIPAddress;privatebyteLocalTSAP_HI;privatebyteLocalTSAP_LO;privatebyteRemoteTSAP_HI;privatebyteRemoteTSAP_LO;privatebyteLastPDUType;privateushortConnType=CONNTYPE_PG;privatebyte[]PDU=newbyte[2048];privateMsgSocketSocket=null;privateintTime_ms=0;privateushortcntword=0;privatevoidCreateSocket(){try{Socket=newMsgSocket();Socket.ConnectTimeout=_ConnTimeout;Socket.ReadTimeout=_RecvTimeout;Socket.WriteTimeout=_SendTimeout;}catch{}}privateintTCPConnect(){if(_LastError==0)try{_LastError=Socket.Connect(IPAddress,_PLCPort);}catch{_LastError=S7Consts.errTCPConnectionFailed;}return_LastError;}privatevoidRecvPacket(byte[]Buffer,intStart,intSize){if(Connected)_LastError=Socket.Receive(Buffer,Start,Size);else_LastError=S7Consts.errTCPNotConnected;}privatevoidSendPacket(byte[]Buffer,intLen){_LastError=Socket.Send(Buffer,Len);}privatevoidSendPacket(byte[]Buffer){if(Connected)SendPacket(Buffer,Buffer.Length);else_LastError=S7Consts.errTCPNotConnected;}privateintRecvIsoPacket(){BooleanDone=false;intSize=0;while((_LastError==0)&&!Done){//GetTPKT(4bytes)RecvPacket(PDU,0,4);if(_LastError==0){Size=S7.GetWordAt(PDU,2);//Check0bytesDataPacket(onlyTPKT+COTP=7bytes)if(Size==IsoHSize)RecvPacket(PDU,4,3);//Skipremaining3bytesandDoneisstillfalseelse{if((Size>_PduSizeRequested+IsoHSize)||(Size<MinPduSize))_LastError=S7Consts.errIsoInvalidPDU;elseDone=true;//avalidLength!=7&&>16&&<247}}}if(_LastError==0){RecvPacket(PDU,4,3);//Skipremaining3COTPbytesLastPDUType=PDU[5];//StoresPDUType,weneedit//ReceivestheS7PayloadRecvPacket(PDU,7,Size-IsoHSize);}if(_LastError==0)returnSize;elsereturn0;}privateintISOConnect(){intSize;ISO_CR[16]=LocalTSAP_HI;ISO_CR[17]=LocalTSAP_LO;ISO_CR[20]=RemoteTSAP_HI;ISO_CR[21]=RemoteTSAP_LO;//SendstheconnectionrequesttelegramSendPacket(ISO_CR);if(_LastError==0){//Getsthereply(ifany)Size=RecvIsoPacket();if(_LastError==0){if(Size==22){if(LastPDUType!=(byte)0xD0)//0xD0=CCConnectionconfirm_LastError=S7Consts.errIsoConnect;}else_LastError=S7Consts.errIsoInvalidPDU;}}return_LastError;}privateintNegotiatePduLength(){intLength;//SetPDUSizeRequestedS7.SetWordAt(S7_PN,23,(ushort)_PduSizeRequested);//SendstheconnectionrequesttelegramSendPacket(S7_PN);if(_LastError==0){Length=RecvIsoPacket();if(_LastError==0){//checkS7Errorif((Length==27)&&(PDU[17]==0)&&(PDU[18]==0))//20=sizeofNegotiateAnswer{//GetPDUSizeNegotiated_PDULength=S7.GetWordAt(PDU,25);if(_PDULength<=0)_LastError=S7Consts.errCliNegotiatingPDU;}else_LastError=S7Consts.errCliNegotiatingPDU;}}return_LastError;}privateintCpuError(ushortError){switch(Error){case0:return0;caseCode7AddressOutOfRange:returnS7Consts.errCliAddressOutOfRange;caseCode7InvalidTransportSize:returnS7Consts.errCliInvalidTransportSize;caseCode7WriteDataSizeMismatch:returnS7Consts.errCliWriteDataSizeMismatch;caseCode7ResItemNotAvailable:caseCode7ResItemNotAvailable1:returnS7Consts.errCliItemNotAvailable;caseCode7DataOverPDU:returnS7Consts.errCliSizeOverPDU;caseCode7InvalidValue:returnS7Consts.errCliInvalidValue;caseCode7FunNotAvailable:returnS7Consts.errCliFunNotAvailable;caseCode7NeedPassword:returnS7Consts.errCliNeedPassword;caseCode7InvalidPassword:returnS7Consts.errCliInvalidPassword;caseCode7NoPasswordToSet:caseCode7NoPasswordToClear:returnS7Consts.errCliNoPasswordToSetOrClear;default:returnS7Consts.errCliFunctionRefused;};}privateushortGetNextWord(){returncntword++;}#endregion#region[ClassControl]publicS7Client(){CreateSocket();}~S7Client(){Disconnect();}publicintConnect(){_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;if(!Connected){TCPConnect();//Firststage:TCPConnectionif(_LastError==0){ISOConnect();//Secondstage:ISOTCP(ISO8073)Connectionif(_LastError==0){_LastError=NegotiatePduLength();//Thirdstage:S7PDUnegotiation}}}if(_LastError!=0)Disconnect();elseTime_ms=Environment.TickCount-Elapsed;return_LastError;}publicintConnectTo(stringAddress,intRack,intSlot){UInt16RemoteTSAP=(UInt16)((ConnType<<8)+(Rack*0x20)+Slot);SetConnectionParams(Address,0x0100,RemoteTSAP);returnConnect();}publicintSetConnectionParams(stringAddress,ushortLocalTSAP,ushortRemoteTSAP){intLocTSAP=LocalTSAP&0x0000FFFF;intRemTSAP=RemoteTSAP&0x0000FFFF;IPAddress=Address;LocalTSAP_HI=(byte)(LocTSAP>>8);LocalTSAP_LO=(byte)(LocTSAP&0x00FF);RemoteTSAP_HI=(byte)(RemTSAP>>8);RemoteTSAP_LO=(byte)(RemTSAP&0x00FF);return0;}publicintSetConnectionType(ushortConnectionType){ConnType=ConnectionType;return0;}publicintDisconnect(){Socket.Close();return0;}publicintGetParam(Int32ParamNumber,refintValue){intResult=0;switch(ParamNumber){caseS7Consts.p_u16_RemotePort:{Value=PLCPort;break;}caseS7Consts.p_i32_PingTimeout:{Value=ConnTimeout;break;}caseS7Consts.p_i32_SendTimeout:{Value=SendTimeout;break;}caseS7Consts.p_i32_RecvTimeout:{Value=RecvTimeout;break;}caseS7Consts.p_i32_PDURequest:{Value=PduSizeRequested;break;}default:{Result=S7Consts.errCliInvalidParamNumber;break;}}returnResult;}//SetPropertiesforcompatibilitywithSnap7.net.cspublicintSetParam(Int32ParamNumber,refintValue){intResult=0;switch(ParamNumber){caseS7Consts.p_u16_RemotePort:{PLCPort=Value;break;}caseS7Consts.p_i32_PingTimeout:{ConnTimeout=Value;break;}caseS7Consts.p_i32_SendTimeout:{SendTimeout=Value;break;}caseS7Consts.p_i32_RecvTimeout:{RecvTimeout=Value;break;}caseS7Consts.p_i32_PDURequest:{PduSizeRequested=Value;break;}default:{Result=S7Consts.errCliInvalidParamNumber;break;}}returnResult;}publicdelegatevoidS7CliCompletion(IntPtrusrPtr,intopCode,intopResult);publicintSetAsCallBack(S7CliCompletionCompletion,IntPtrusrPtr){returnS7Consts.errCliFunctionNotImplemented;}#endregion#region[DataI/Omainfunctions]publicintReadArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer){intBytesRead=0;returnReadArea(Area,DBNumber,Start,Amount,WordLen,Buffer,refBytesRead);}publicintReadArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer,refintBytesRead){intAddress;intNumElements;intMaxElements;intTotElements;intSizeRequested;intLength;intOffset=0;intWordSize=1;_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;//Someadjustmentif(Area==S7Consts.S7AreaCT)WordLen=S7Consts.S7WLCounter;if(Area==S7Consts.S7AreaTM)WordLen=S7Consts.S7WLTimer;//CalcWordsizeWordSize=S7.DataSizeByte(WordLen);if(WordSize==0)returnS7Consts.errCliInvalidWordLen;if(WordLen==S7Consts.S7WLBit)Amount=1;//Only1bitcanbetransferredattimeelse{if((WordLen!=S7Consts.S7WLCounter)&&(WordLen!=S7Consts.S7WLTimer)){Amount=Amount*WordSize;WordSize=1;WordLen=S7Consts.S7WLByte;}}MaxElements=(_PDULength-18)/WordSize;//18=ReplytelegramheaderTotElements=Amount;while((TotElements>0)&&(_LastError==0)){NumElements=TotElements;if(NumElements>MaxElements)NumElements=MaxElements;SizeRequested=NumElements*WordSize;//SetupthetelegramArray.Copy(S7_RW,0,PDU,0,Size_RD);//SetDBNumberPDU[27]=(byte)Area;//SetAreaif(Area==S7Consts.S7AreaDB)S7.SetWordAt(PDU,25,(ushort)DBNumber);//AdjustsStartandwordlengthif((WordLen==S7Consts.S7WLBit)||(WordLen==S7Consts.S7WLCounter)||(WordLen==S7Consts.S7WLTimer)){Address=Start;PDU[22]=(byte)WordLen;}elseAddress=Start<<3;//NumelementsS7.SetWordAt(PDU,23,(ushort)NumElements);//AddressintothePLC(only3bytes)PDU[30]=(byte)(Address&0x0FF);Address=Address>>8;PDU[29]=(byte)(Address&0x0FF);Address=Address>>8;PDU[28]=(byte)(Address&0x0FF);SendPacket(PDU,Size_RD);if(_LastError==0){Length=RecvIsoPacket();if(_LastError==0){if(Length<25)_LastError=S7Consts.errIsoInvalidDataSize;else{if(PDU[21]!=0xFF)_LastError=CpuError(PDU[21]);else{Array.Copy(PDU,25,Buffer,Offset,SizeRequested);Offset+=SizeRequested;}}}}TotElements-=NumElements;Start+=NumElements*WordSize;}if(_LastError==0){BytesRead=Offset;Time_ms=Environment.TickCount-Elapsed;}elseBytesRead=0;return_LastError;}publicintWriteArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer){intBytesWritten=0;returnWriteArea(Area,DBNumber,Start,Amount,WordLen,Buffer,refBytesWritten);}publicintWriteArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer,refintBytesWritten){intAddress;intNumElements;intMaxElements;intTotElements;intDataSize;intIsoSize;intLength;intOffset=0;intWordSize=1;_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;//Someadjustmentif(Area==S7Consts.S7AreaCT)WordLen=S7Consts.S7WLCounter;if(Area==S7Consts.S7AreaTM)WordLen=S7Consts.S7WLTimer;//CalcWordsizeWordSize=S7.DataSizeByte(WordLen);if(WordSize==0)returnS7Consts.errCliInvalidWordLen;if(WordLen==S7Consts.S7WLBit)//Only1bitcanbetransferredattimeAmount=1;else{if((WordLen!=S7Consts.S7WLCounter)&&(WordLen!=S7Consts.S7WLTimer)){Amount=Amount*WordSize;WordSize=1;WordLen=S7Consts.S7WLByte;}}MaxElements=(_PDULength-35)/WordSize;//35=ReplytelegramheaderTotElements=Amount;while((TotElements>0)&&(_LastError==0)){NumElements=TotElements;if(NumElements>MaxElements)NumElements=MaxElements;DataSize=NumElements*WordSize;IsoSize=Size_WR+DataSize;//SetupthetelegramArray.Copy(S7_RW,0,PDU,0,Size_WR);//WholetelegramSizeS7.SetWordAt(PDU,2,(ushort)IsoSize);//DataLengthLength=DataSize+4;S7.SetWordAt(PDU,15,(ushort)Length);//FunctionPDU[17]=(byte)0x05;//SetDBNumberPDU[27]=(byte)Area;if(Area==S7Consts.S7AreaDB)S7.SetWordAt(PDU,25,(ushort)DBNumber);//AdjustsStartandwordlengthif((WordLen==S7Consts.S7WLBit)||(WordLen==S7Consts.S7WLCounter)||(WordLen==S7Consts.S7WLTimer)){Address=Start;Length=DataSize;PDU[22]=(byte)WordLen;}else{Address=Start<<3;Length=DataSize<<3;}//NumelementsS7.SetWordAt(PDU,23,(ushort)NumElements);//AddressintothePLCPDU[30]=(byte)(Address&0x0FF);Address=Address>>8;PDU[29]=(byte)(Address&0x0FF);Address=Address>>8;PDU[28]=(byte)(Address&0x0FF);//TransportSizeswitch(WordLen){caseS7Consts.S7WLBit:PDU[32]=TS_ResBit;break;caseS7Consts.S7WLCounter:caseS7Consts.S7WLTimer:PDU[32]=TS_ResOctet;break;default:PDU[32]=TS_ResByte;//byte/word/dwordetc.break;};//LengthS7.SetWordAt(PDU,33,(ushort)Length);//CopiestheDataArray.Copy(Buffer,Offset,PDU,35,DataSize);SendPacket(PDU,IsoSize);if(_LastError==0){Length=RecvIsoPacket();if(_LastError==0){if(Length==22){if(PDU[21]!=(byte)0xFF)_LastError=CpuError(PDU[21]);}else_LastError=S7Consts.errIsoInvalidPDU;}}Offset+=DataSize;TotElements-=NumElements;Start+=NumElements*WordSize;}if(_LastError==0){BytesWritten=Offset;Time_ms=Environment.TickCount-Elapsed;}elseBytesWritten=0;return_LastError;}publicintReadMultiVars(S7DataItem[]Items,intItemsCount){intOffset;intLength;intItemSize;byte[]S7Item=newbyte[12];byte[]S7ItemRead=newbyte[1024];_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;//Checksitemsif(ItemsCount>MaxVars)returnS7Consts.errCliTooManyItems;//FillsHeaderArray.Copy(S7_MRD_HEADER,0,PDU,0,S7_MRD_HEADER.Length);S7.SetWordAt(PDU,13,(ushort)(ItemsCount*S7Item.Length+2));PDU[18]=(byte)ItemsCount;//FillstheItemsOffset=19;for(intc=0;c<ItemsCount;c++){Array.Copy(S7_MRD_ITEM,S7Item,S7Item.Length);S7Item[3]=(byte)Items[c].WordLen;S7.SetWordAt(S7Item,4,(ushort)Items[c].Amount);if(Items[c].Area==S7Consts.S7AreaDB)S7.SetWordAt(S7Item,6,(ushort)Items[c].DBNumber);S7Item[8]=(byte)Items[c].Area;//AddressintothePLCintAddress=Items[c].Start;S7Item[11]=(byte)(Address&0x0FF);Address=Address>>8;S7Item[10]=(byte)(Address&0x0FF);Address=Address>>8;S7Item[09]=(byte)(Address&0x0FF);Array.Copy(S7Item,0,PDU,Offset,S7Item.Length);Offset+=S7Item.Length;}if(Offset>_PDULength)returnS7Consts.errCliSizeOverPDU;S7.SetWordAt(PDU,2,(ushort)Offset);//WholesizeSendPacket(PDU,Offset);if(_LastError!=0)return_LastError;//GetAnswerLength=RecvIsoPacket();if(_LastError!=0)return_LastError;//CheckISOLengthif(Length<22){_LastError=S7Consts.errIsoInvalidPDU;//PDUtooSmallreturn_LastError;}//CheckGlobalOperationResult_LastError=CpuError(S7.GetWordAt(PDU,17));if(_LastError!=0)return_LastError;//GettrueItemsCountintItemsRead=S7.GetByteAt(PDU,20);if((ItemsRead!=ItemsCount)||(ItemsRead>MaxVars)){_LastError=S7Consts.errCliInvalidPlcAnswer;return_LastError;}//GetDataOffset=21;for(intc=0;c<ItemsCount;c++){//GettheItemArray.Copy(PDU,Offset,S7ItemRead,0,Length-Offset);if(S7ItemRead[0]==0xff){ItemSize=(int)S7.GetWordAt(S7ItemRead,2);if((S7ItemRead[1]!=TS_ResOctet)&&(S7ItemRead[1]!=TS_ResReal)&&(S7ItemRead[1]!=TS_ResBit))ItemSize=ItemSize>>3;Marshal.Copy(S7ItemRead,4,Items[c].pData,ItemSize);Items[c].Result=0;if(ItemSize%2!=0)ItemSize++;//OddsizeareroundedOffset=Offset+4+ItemSize;}else{Items[c].Result=CpuError(S7ItemRead[0]);Offset+=4;//SkiptheItemheader}}Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintWriteMultiVars(S7DataItem[]Items,intItemsCount){intOffset;intParLength;intDataLength;intItemDataSize;byte[]S7ParItem=newbyte[S7_MWR_PARAM.Length];byte[]S7DataItem=newbyte[1024];_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;//Checksitemsif(ItemsCount>MaxVars)returnS7Consts.errCliTooManyItems;//FillsHeaderArray.Copy(S7_MWR_HEADER,0,PDU,0,S7_MWR_HEADER.Length);ParLength=ItemsCount*S7_MWR_PARAM.Length+2;S7.SetWordAt(PDU,13,(ushort)ParLength);PDU[18]=(byte)ItemsCount;//FillsParamsOffset=S7_MWR_HEADER.Length;for(intc=0;c<ItemsCount;c++){Array.Copy(S7_MWR_PARAM,0,S7ParItem,0,S7_MWR_PARAM.Length);S7ParItem[3]=(byte)Items[c].WordLen;S7ParItem[8]=(byte)Items[c].Area;S7.SetWordAt(S7ParItem,4,(ushort)Items[c].Amount);S7.SetWordAt(S7ParItem,6,(ushort)Items[c].DBNumber);//AddressintothePLCintAddress=Items[c].Start;S7ParItem[11]=(byte)(Address&0x0FF);Address=Address>>8;S7ParItem[10]=(byte)(Address&0x0FF);Address=Address>>8;S7ParItem[09]=(byte)(Address&0x0FF);Array.Copy(S7ParItem,0,PDU,Offset,S7ParItem.Length);Offset+=S7_MWR_PARAM.Length;}//FillsDataDataLength=0;for(intc=0;c<ItemsCount;c++){S7DataItem[0]=0x00;switch(Items[c].WordLen){caseS7Consts.S7WLBit:S7DataItem[1]=TS_ResBit;break;caseS7Consts.S7WLCounter:caseS7Consts.S7WLTimer:S7DataItem[1]=TS_ResOctet;break;default:S7DataItem[1]=TS_ResByte;//byte/word/dwordetc.break;};if((Items[c].WordLen==S7Consts.S7WLTimer)||(Items[c].WordLen==S7Consts.S7WLCounter))ItemDataSize=Items[c].Amount*2;elseItemDataSize=Items[c].Amount;if((S7DataItem[1]!=TS_ResOctet)&&(S7DataItem[1]!=TS_ResBit))S7.SetWordAt(S7DataItem,2,(ushort)(ItemDataSize*8));elseS7.SetWordAt(S7DataItem,2,(ushort)ItemDataSize);Marshal.Copy(Items[c].pData,S7DataItem,4,ItemDataSize);if(ItemDataSize%2!=0){S7DataItem[ItemDataSize+4]=0x00;ItemDataSize++;}Array.Copy(S7DataItem,0,PDU,Offset,ItemDataSize+4);Offset=Offset+ItemDataSize+4;DataLength=DataLength+ItemDataSize+4;}//Checksthesizeif(Offset>_PDULength)returnS7Consts.errCliSizeOverPDU;S7.SetWordAt(PDU,2,(ushort)Offset);//WholesizeS7.SetWordAt(PDU,15,(ushort)DataLength);//WholesizeSendPacket(PDU,Offset);RecvIsoPacket();if(_LastError==0){//CheckGlobalOperationResult_LastError=CpuError(S7.GetWordAt(PDU,17));if(_LastError!=0)return_LastError;//GettrueItemsCountintItemsWritten=S7.GetByteAt(PDU,20);if((ItemsWritten!=ItemsCount)||(ItemsWritten>MaxVars)){_LastError=S7Consts.errCliInvalidPlcAnswer;return_LastError;}for(intc=0;c<ItemsCount;c++){if(PDU[c+21]==0xFF)Items[c].Result=0;elseItems[c].Result=CpuError((ushort)PDU[c+21]);}Time_ms=Environment.TickCount-Elapsed;}return_LastError;}#endregion#region[DataI/Oleanfunctions]publicintDBRead(intDBNumber,intStart,intSize,byte[]Buffer){returnReadArea(S7Consts.S7AreaDB,DBNumber,Start,Size,S7Consts.S7WLByte,Buffer);}publicintDBWrite(intDBNumber,intStart,intSize,byte[]Buffer){returnWriteArea(S7Consts.S7AreaDB,DBNumber,Start,Size,S7Consts.S7WLByte,Buffer);}publicintMBRead(intStart,intSize,byte[]Buffer){returnReadArea(S7Consts.S7AreaMK,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintMBWrite(intStart,intSize,byte[]Buffer){returnWriteArea(S7Consts.S7AreaMK,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintEBRead(intStart,intSize,byte[]Buffer){returnReadArea(S7Consts.S7AreaPE,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintEBWrite(intStart,intSize,byte[]Buffer){returnWriteArea(S7Consts.S7AreaPE,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintABRead(intStart,intSize,byte[]Buffer){returnReadArea(S7Consts.S7AreaPA,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintABWrite(intStart,intSize,byte[]Buffer){returnWriteArea(S7Consts.S7AreaPA,0,Start,Size,S7Consts.S7WLByte,Buffer);}publicintTMRead(intStart,intAmount,ushort[]Buffer){byte[]sBuffer=newbyte[Amount*2];intResult=ReadArea(S7Consts.S7AreaTM,0,Start,Amount,S7Consts.S7WLTimer,sBuffer);if(Result==0){for(intc=0;c<Amount;c++){Buffer[c]=(ushort)((sBuffer[c*2+1]<<8)+(sBuffer[c*2]));}}returnResult;}publicintTMWrite(intStart,intAmount,ushort[]Buffer){byte[]sBuffer=newbyte[Amount*2];for(intc=0;c<Amount;c++){sBuffer[c*2+1]=(byte)((Buffer[c]&0xFF00)>>8);sBuffer[c*2]=(byte)(Buffer[c]&0x00FF);}returnWriteArea(S7Consts.S7AreaTM,0,Start,Amount,S7Consts.S7WLTimer,sBuffer);}publicintCTRead(intStart,intAmount,ushort[]Buffer){byte[]sBuffer=newbyte[Amount*2];intResult=ReadArea(S7Consts.S7AreaCT,0,Start,Amount,S7Consts.S7WLCounter,sBuffer);if(Result==0){for(intc=0;c<Amount;c++){Buffer[c]=(ushort)((sBuffer[c*2+1]<<8)+(sBuffer[c*2]));}}returnResult;}publicintCTWrite(intStart,intAmount,ushort[]Buffer){byte[]sBuffer=newbyte[Amount*2];for(intc=0;c<Amount;c++){sBuffer[c*2+1]=(byte)((Buffer[c]&0xFF00)>>8);sBuffer[c*2]=(byte)(Buffer[c]&0x00FF);}returnWriteArea(S7Consts.S7AreaCT,0,Start,Amount,S7Consts.S7WLCounter,sBuffer);}#endregion#region[Directoryfunctions]publicintListBlocks(refS7BlocksListList){_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;ushortSequence=GetNextWord();Array.Copy(S7_LIST_BLOCKS,0,PDU,0,S7_LIST_BLOCKS.Length);PDU[0x0b]=(byte)(Sequence&0xff);PDU[0x0c]=(byte)(Sequence>>8);SendPacket(PDU,S7_LIST_BLOCKS.Length);if(_LastError!=0)return_LastError;intLength=RecvIsoPacket();if(Length<=32)//theminimumexpected{_LastError=S7Consts.errIsoInvalidPDU;return_LastError;}ushortResult=S7.GetWordAt(PDU,27);if(Result!=0){_LastError=CpuError(Result);return_LastError;}List=default(S7BlocksList);intBlocksSize=S7.GetWordAt(PDU,31);if(Length<=32+BlocksSize){_LastError=S7Consts.errIsoInvalidPDU;return_LastError;}intBlocksCount=BlocksSize>>2;for(intblockNum=0;blockNum<BlocksCount;blockNum++){intCount=S7.GetWordAt(PDU,(blockNum<<2)+35);switch(S7.GetByteAt(PDU,(blockNum<<2)+34))//BlockType{caseBlock_OB:List.OBCount=Count;break;caseBlock_DB:List.DBCount=Count;break;caseBlock_SDB:List.SDBCount=Count;break;caseBlock_FC:List.FCCount=Count;break;caseBlock_SFC:List.SFCCount=Count;break;caseBlock_FB:List.FBCount=Count;break;caseBlock_SFB:List.SFBCount=Count;break;default://Unknownblocktype.Ignorebreak;}}Time_ms=Environment.TickCount-Elapsed;return_LastError;//0}privatestringSiemensTimestamp(longEncodedDate){DateTimeDT=newDateTime(1984,1,1).AddSeconds(EncodedDate*86400);#ifWINDOWS_UWP||NETFX_CORE||CORE_CLRreturnDT.ToString(System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern);#elsereturnDT.ToShortDateString();//returnDT.ToString();#endif}publicintGetAgBlockInfo(intBlockType,intBlockNum,refS7BlockInfoInfo){_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;S7_BI[30]=(byte)BlockType;//BlockNumberS7_BI[31]=(byte)((BlockNum/10000)+0x30);BlockNum=BlockNum%10000;S7_BI[32]=(byte)((BlockNum/1000)+0x30);BlockNum=BlockNum%1000;S7_BI[33]=(byte)((BlockNum/100)+0x30);BlockNum=BlockNum%100;S7_BI[34]=(byte)((BlockNum/10)+0x30);BlockNum=BlockNum%10;S7_BI[35]=(byte)((BlockNum/1)+0x30);SendPacket(S7_BI);if(_LastError==0){intLength=RecvIsoPacket();if(Length>32)//theminimumexpected{ushortResult=S7.GetWordAt(PDU,27);if(Result==0){Info.BlkFlags=PDU[42];Info.BlkLang=PDU[43];Info.BlkType=PDU[44];Info.BlkNumber=S7.GetWordAt(PDU,45);Info.LoadSize=S7.GetDIntAt(PDU,47);Info.CodeDate=SiemensTimestamp(S7.GetWordAt(PDU,59));Info.IntfDate=SiemensTimestamp(S7.GetWordAt(PDU,65));Info.SBBLength=S7.GetWordAt(PDU,67);Info.LocalData=S7.GetWordAt(PDU,71);Info.MC7Size=S7.GetWordAt(PDU,73);Info.Author=S7.GetCharsAt(PDU,75,8).Trim(newchar[]{(char)0});Info.Family=S7.GetCharsAt(PDU,83,8).Trim(newchar[]{(char)0});Info.Header=S7.GetCharsAt(PDU,91,8).Trim(newchar[]{(char)0});Info.Version=PDU[99];Info.CheckSum=S7.GetWordAt(PDU,101);}else_LastError=CpuError(Result);}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintGetPgBlockInfo(refS7BlockInfoInfo,byte[]Buffer,intSize){returnS7Consts.errCliFunctionNotImplemented;}publicintListBlocksOfType(intBlockType,ushort[]List,refintItemsCount){varFirst=true;boolDone=false;byteIn_Seq=0;intCount=0;//Block1...nintPduLength;intElapsed=Environment.TickCount;//ConsequentpacketshaveadifferentReqDatabyte[]ReqData=newbyte[]{0xff,0x09,0x00,0x02,0x30,(byte)BlockType};byte[]ReqDataContinue=newbyte[]{0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00};_LastError=0;Time_ms=0;do{PduLength=S7_LIST_BLOCKS_OF_TYPE.Length+ReqData.Length;ushortSequence=GetNextWord();Array.Copy(S7_LIST_BLOCKS_OF_TYPE,0,PDU,0,S7_LIST_BLOCKS_OF_TYPE.Length);S7.SetWordAt(PDU,0x02,(ushort)PduLength);PDU[0x0b]=(byte)(Sequence&0xff);PDU[0x0c]=(byte)(Sequence>>8);if(!First){S7.SetWordAt(PDU,0x0d,12);//ParLenS7.SetWordAt(PDU,0x0f,4);//DataLenPDU[0x14]=8;//PLenPDU[0x15]=0x12;//Uk}PDU[0x17]=0x02;PDU[0x18]=In_Seq;Array.Copy(ReqData,0,PDU,0x19,ReqData.Length);SendPacket(PDU,PduLength);if(_LastError!=0)return_LastError;PduLength=RecvIsoPacket();if(_LastError!=0)return_LastError;if(PduLength<=32)//theminimumexpected{_LastError=S7Consts.errIsoInvalidPDU;return_LastError;}ushortResult=S7.GetWordAt(PDU,0x1b);if(Result!=0){_LastError=CpuError(Result);return_LastError;}if(PDU[0x1d]!=0xFF){_LastError=S7Consts.errCliItemNotAvailable;return_LastError;}Done=PDU[0x1a]==0;In_Seq=PDU[0x18];intCThis=S7.GetWordAt(PDU,0x1f)>>2;//Amountofblocksinthismessagefor(intc=0;c<CThis;c++){if(Count>=ItemsCount)//RoomError{_LastError=S7Consts.errCliPartialDataRead;return_LastError;}List[Count++]=S7.GetWordAt(PDU,0x21+4*c);Done|=Count==0x8000;//butwhy?}if(First){ReqData=ReqDataContinue;First=false;}}while(_LastError==0&&!Done);if(_LastError==0)ItemsCount=Count;Time_ms=Environment.TickCount-Elapsed;return_LastError;//0}#endregion#region[Blocksfunctions]publicintUpload(intBlockType,intBlockNum,byte[]UsrData,refintSize){returnS7Consts.errCliFunctionNotImplemented;}publicintFullUpload(intBlockType,intBlockNum,byte[]UsrData,refintSize){returnS7Consts.errCliFunctionNotImplemented;}publicintDownload(intBlockNum,byte[]UsrData,intSize){returnS7Consts.errCliFunctionNotImplemented;}publicintDelete(intBlockType,intBlockNum){returnS7Consts.errCliFunctionNotImplemented;}publicintDBGet(intDBNumber,byte[]UsrData,refintSize){S7BlockInfoBI=newS7BlockInfo();intElapsed=Environment.TickCount;Time_ms=0;_LastError=GetAgBlockInfo(Block_DB,DBNumber,refBI);if(_LastError==0){intDBSize=BI.MC7Size;if(DBSize<=UsrData.Length){Size=DBSize;_LastError=DBRead(DBNumber,0,DBSize,UsrData);if(_LastError==0)Size=DBSize;}else_LastError=S7Consts.errCliBufferTooSmall;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintDBFill(intDBNumber,intFillChar){S7BlockInfoBI=newS7BlockInfo();intElapsed=Environment.TickCount;Time_ms=0;_LastError=GetAgBlockInfo(Block_DB,DBNumber,refBI);if(_LastError==0){byte[]Buffer=newbyte[BI.MC7Size];for(intc=0;c<BI.MC7Size;c++)Buffer[c]=(byte)FillChar;_LastError=DBWrite(DBNumber,0,BI.MC7Size,Buffer);}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}#endregion#region[Date/Timefunctions]publicintGetPlcDateTime(refDateTimeDT){intLength;_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;SendPacket(S7_GET_DT);if(_LastError==0){Length=RecvIsoPacket();if(Length>30)//theminimumexpected{if((S7.GetWordAt(PDU,27)==0)&&(PDU[29]==0xFF)){DT=S7.GetDateTimeAt(PDU,35);}else_LastError=S7Consts.errCliInvalidPlcAnswer;}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintSetPlcDateTime(DateTimeDT){intLength;_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;S7.SetDateTimeAt(S7_SET_DT,31,DT);SendPacket(S7_SET_DT);if(_LastError==0){Length=RecvIsoPacket();if(Length>30)//theminimumexpected{if(S7.GetWordAt(PDU,27)!=0)_LastError=S7Consts.errCliInvalidPlcAnswer;}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintSetPlcSystemDateTime(){returnSetPlcDateTime(DateTime.Now);}#endregion#region[SystemInfofunctions]publicintGetOrderCode(refS7OrderCodeInfo){S7SZLSZL=newS7SZL();intSize=1024;SZL.Data=newbyte[Size];intElapsed=Environment.TickCount;_LastError=ReadSZL(0x0011,0x000,refSZL,refSize);if(_LastError==0){Info.Code=S7.GetCharsAt(SZL.Data,2,20);Info.V1=SZL.Data[Size-3];Info.V2=SZL.Data[Size-2];Info.V3=SZL.Data[Size-1];}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintGetCpuInfo(refS7CpuInfoInfo){S7SZLSZL=newS7SZL();intSize=1024;SZL.Data=newbyte[Size];intElapsed=Environment.TickCount;_LastError=ReadSZL(0x001C,0x000,refSZL,refSize);if(_LastError==0){Info.ModuleTypeName=S7.GetCharsAt(SZL.Data,172,32);Info.SerialNumber=S7.GetCharsAt(SZL.Data,138,24);Info.ASName=S7.GetCharsAt(SZL.Data,2,24);Info.Copyright=S7.GetCharsAt(SZL.Data,104,26);Info.ModuleName=S7.GetCharsAt(SZL.Data,36,24);}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintGetCpInfo(refS7CpInfoInfo){S7SZLSZL=newS7SZL();intSize=1024;SZL.Data=newbyte[Size];intElapsed=Environment.TickCount;_LastError=ReadSZL(0x0131,0x001,refSZL,refSize);if(_LastError==0){Info.MaxPduLength=S7.GetIntAt(PDU,2);Info.MaxConnections=S7.GetIntAt(PDU,4);Info.MaxMpiRate=S7.GetDIntAt(PDU,6);Info.MaxBusRate=S7.GetDIntAt(PDU,10);}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintReadSZL(intID,intIndex,refS7SZLSZL,refintSize){intLength;intDataSZL;intOffset=0;boolDone=false;boolFirst=true;byteSeq_in=0x00;ushortSeq_out=0x0000;_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;SZL.Header.LENTHDR=0;do{if(First){S7.SetWordAt(S7_SZL_FIRST,11,++Seq_out);S7.SetWordAt(S7_SZL_FIRST,29,(ushort)ID);S7.SetWordAt(S7_SZL_FIRST,31,(ushort)Index);SendPacket(S7_SZL_FIRST);}else{S7.SetWordAt(S7_SZL_NEXT,11,++Seq_out);PDU[24]=(byte)Seq_in;SendPacket(S7_SZL_NEXT);}if(_LastError!=0)return_LastError;Length=RecvIsoPacket();if(_LastError==0){if(First){if(Length>32)//theminimumexpected{if((S7.GetWordAt(PDU,27)==0)&&(PDU[29]==(byte)0xFF)){//GetsAmountofthissliceDataSZL=S7.GetWordAt(PDU,31)-8;//Skipsextraparams(ID,Index...)Done=PDU[26]==0x00;Seq_in=(byte)PDU[24];//SlicesequenceSZL.Header.LENTHDR=S7.GetWordAt(PDU,37);SZL.Header.N_DR=S7.GetWordAt(PDU,39);Array.Copy(PDU,41,SZL.Data,Offset,DataSZL);//SZL.Copy(PDU,41,Offset,DataSZL);Offset+=DataSZL;SZL.Header.LENTHDR+=SZL.Header.LENTHDR;}else_LastError=S7Consts.errCliInvalidPlcAnswer;}else_LastError=S7Consts.errIsoInvalidPDU;}else{if(Length>32)//theminimumexpected{if((S7.GetWordAt(PDU,27)==0)&&(PDU[29]==(byte)0xFF)){//GetsAmountofthissliceDataSZL=S7.GetWordAt(PDU,31);Done=PDU[26]==0x00;Seq_in=(byte)PDU[24];//SlicesequenceArray.Copy(PDU,37,SZL.Data,Offset,DataSZL);Offset+=DataSZL;SZL.Header.LENTHDR+=SZL.Header.LENTHDR;}else_LastError=S7Consts.errCliInvalidPlcAnswer;}else_LastError=S7Consts.errIsoInvalidPDU;}}First=false;}while(!Done&&(_LastError==0));if(_LastError==0){Size=SZL.Header.LENTHDR;Time_ms=Environment.TickCount-Elapsed;}return_LastError;}publicintReadSZLList(refS7SZLListList,refInt32ItemsCount){returnS7Consts.errCliFunctionNotImplemented;}#endregion#region[Controlfunctions]publicintPlcHotStart(){_LastError=0;intElapsed=Environment.TickCount;SendPacket(S7_HOT_START);if(_LastError==0){intLength=RecvIsoPacket();if(Length>18)//18istheminimumexpected{if(PDU[19]!=pduStart)_LastError=S7Consts.errCliCannotStartPLC;else{if(PDU[20]==pduAlreadyStarted)_LastError=S7Consts.errCliAlreadyRun;else_LastError=S7Consts.errCliCannotStartPLC;}}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintPlcColdStart(){_LastError=0;intElapsed=Environment.TickCount;SendPacket(S7_COLD_START);if(_LastError==0){intLength=RecvIsoPacket();if(Length>18)//18istheminimumexpected{if(PDU[19]!=pduStart)_LastError=S7Consts.errCliCannotStartPLC;else{if(PDU[20]==pduAlreadyStarted)_LastError=S7Consts.errCliAlreadyRun;else_LastError=S7Consts.errCliCannotStartPLC;}}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintPlcStop(){_LastError=0;intElapsed=Environment.TickCount;SendPacket(S7_STOP);if(_LastError==0){intLength=RecvIsoPacket();if(Length>18)//18istheminimumexpected{if(PDU[19]!=pduStop)_LastError=S7Consts.errCliCannotStopPLC;else{if(PDU[20]==pduAlreadyStopped)_LastError=S7Consts.errCliAlreadyStop;else_LastError=S7Consts.errCliCannotStopPLC;}}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintPlcCopyRamToRom(UInt32Timeout){returnS7Consts.errCliFunctionNotImplemented;}publicintPlcCompress(UInt32Timeout){returnS7Consts.errCliFunctionNotImplemented;}publicintPlcGetStatus(refInt32Status){_LastError=0;intElapsed=Environment.TickCount;SendPacket(S7_GET_STAT);if(_LastError==0){intLength=RecvIsoPacket();if(Length>30)//theminimumexpected{ushortResult=S7.GetWordAt(PDU,27);if(Result==0){switch(PDU[44]){caseS7Consts.S7CpuStatusUnknown:caseS7Consts.S7CpuStatusRun:caseS7Consts.S7CpuStatusStop:{Status=PDU[44];break;}default:{//SinceRUNstatusisalways0x08forallCPUsandCPs,STOPstatus//sometimecanbecodedas0x03(especiallyforoldcpu...)Status=S7Consts.S7CpuStatusStop;break;}}}else_LastError=CpuError(Result);}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}#endregion#region[Securityfunctions]publicintSetSessionPassword(stringPassword){byte[]pwd={0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};intLength;_LastError=0;intElapsed=Environment.TickCount;//EncodesthePasswordS7.SetCharsAt(pwd,0,Password);pwd[0]=(byte)(pwd[0]^0x55);pwd[1]=(byte)(pwd[1]^0x55);for(intc=2;c<8;c++){pwd[c]=(byte)(pwd[c]^0x55^pwd[c-2]);}Array.Copy(pwd,0,S7_SET_PWD,29,8);//SendsthetelegremSendPacket(S7_SET_PWD);if(_LastError==0){Length=RecvIsoPacket();if(Length>32)//theminimumexpected{ushortResult=S7.GetWordAt(PDU,27);if(Result!=0)_LastError=CpuError(Result);}else_LastError=S7Consts.errIsoInvalidPDU;}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintClearSessionPassword(){intLength;_LastError=0;intElapsed=Environment.TickCount;SendPacket(S7_CLR_PWD);if(_LastError==0){Length=RecvIsoPacket();if(Length>30)//theminimumexpected{ushortResult=S7.GetWordAt(PDU,27);if(Result!=0)_LastError=CpuError(Result);}else_LastError=S7Consts.errIsoInvalidPDU;}return_LastError;}publicintGetProtection(refS7ProtectionProtection){S7Client.S7SZLSZL=newS7Client.S7SZL();intSize=256;SZL.Data=newbyte[Size];_LastError=ReadSZL(0x0232,0x0004,refSZL,refSize);if(_LastError==0){Protection.sch_schal=S7.GetWordAt(SZL.Data,2);Protection.sch_par=S7.GetWordAt(SZL.Data,4);Protection.sch_rel=S7.GetWordAt(SZL.Data,6);Protection.bart_sch=S7.GetWordAt(SZL.Data,8);Protection.anl_sch=S7.GetWordAt(SZL.Data,10);}return_LastError;}#endregion#region[LowLevel]publicintIsoExchangeBuffer(byte[]Buffer,refInt32Size){_LastError=0;Time_ms=0;intElapsed=Environment.TickCount;Array.Copy(TPKT_ISO,0,PDU,0,TPKT_ISO.Length);S7.SetWordAt(PDU,2,(ushort)(Size+TPKT_ISO.Length));try{Array.Copy(Buffer,0,PDU,TPKT_ISO.Length,Size);}catch{returnS7Consts.errIsoInvalidPDU;}SendPacket(PDU,TPKT_ISO.Length+Size);if(_LastError==0){intLength=RecvIsoPacket();if(_LastError==0){Array.Copy(PDU,TPKT_ISO.Length,Buffer,0,Length-TPKT_ISO.Length);Size=Length-TPKT_ISO.Length;}}if(_LastError==0)Time_ms=Environment.TickCount-Elapsed;elseSize=0;return_LastError;}#endregion#region[Asyncfunctions(notimplemented)]publicintAsReadArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsWriteArea(intArea,intDBNumber,intStart,intAmount,intWordLen,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsDBRead(intDBNumber,intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsDBWrite(intDBNumber,intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsMBRead(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsMBWrite(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsEBRead(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsEBWrite(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsABRead(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsABWrite(intStart,intSize,byte[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsTMRead(intStart,intAmount,ushort[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsTMWrite(intStart,intAmount,ushort[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsCTRead(intStart,intAmount,ushort[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsCTWrite(intStart,intAmount,ushort[]Buffer){returnS7Consts.errCliFunctionNotImplemented;}publicintAsListBlocksOfType(intBlockType,ushort[]List){returnS7Consts.errCliFunctionNotImplemented;}publicintAsReadSZL(intID,intIndex,refS7SZLData,refInt32Size){returnS7Consts.errCliFunctionNotImplemented;}publicintAsReadSZLList(refS7SZLListList,refInt32ItemsCount){returnS7Consts.errCliFunctionNotImplemented;}publicintAsUpload(intBlockType,intBlockNum,byte[]UsrData,refintSize){returnS7Consts.errCliFunctionNotImplemented;}publicintAsFullUpload(intBlockType,intBlockNum,byte[]UsrData,refintSize){returnS7Consts.errCliFunctionNotImplemented;}publicintASDownload(intBlockNum,byte[]UsrData,intSize){returnS7Consts.errCliFunctionNotImplemented;}publicintAsPlcCopyRamToRom(UInt32Timeout){returnS7Consts.errCliFunctionNotImplemented;}publicintAsPlcCompress(UInt32Timeout){returnS7Consts.errCliFunctionNotImplemented;}publicintAsDBGet(intDBNumber,byte[]UsrData,refintSize){returnS7Consts.errCliFunctionNotImplemented;}publicintAsDBFill(intDBNumber,intFillChar){returnS7Consts.errCliFunctionNotImplemented;}publicboolCheckAsCompletion(refintopResult){opResult=0;returnfalse;}publicintWaitAsCompletion(intTimeout){returnS7Consts.errCliFunctionNotImplemented;}#endregion#region[InfoFunctions/Properties]publicstringErrorText(intError){switch(Error){case0:return"OK";caseS7Consts.errTCPSocketCreation:return"SYS : Error creating the Socket";caseS7Consts.errTCPConnectionTimeout:return"TCP : Connection Timeout";caseS7Consts.errTCPConnectionFailed:return"TCP : Connection Error";caseS7Consts.errTCPReceiveTimeout:return"TCP : Data receive Timeout";caseS7Consts.errTCPDataReceive:return"TCP : Error receiving Data";caseS7Consts.errTCPSendTimeout:return"TCP : Data send Timeout";caseS7Consts.errTCPDataSend:return"TCP : Error sending Data";caseS7Consts.errTCPConnectionReset:return"TCP : Connection reset by the Peer";caseS7Consts.errTCPNotConnected:return"CLI : Client not connected";caseS7Consts.errTCPUnreachableHost:return"TCP : Unreachable host";caseS7Consts.errIsoConnect:return"ISO : Connection Error";caseS7Consts.errIsoInvalidPDU:return"ISO : Invalid PDU received";caseS7Consts.errIsoInvalidDataSize:return"ISO : Invalid Buffer passed to Send/Receive";caseS7Consts.errCliNegotiatingPDU:return"CLI : Error in PDU negotiation";caseS7Consts.errCliInvalidParams:return"CLI : invalid param(s) supplied";caseS7Consts.errCliJobPending:return"CLI : Job pending";caseS7Consts.errCliTooManyItems:return"CLI : too may items (>20) in multi read/write";caseS7Consts.errCliInvalidWordLen:return"CLI : invalid WordLength";caseS7Consts.errCliPartialDataWritten:return"CLI : Partial data written";caseS7Consts.errCliSizeOverPDU:return"CPU : total data exceeds the PDU size";caseS7Consts.errCliInvalidPlcAnswer:return"CLI : invalid CPU answer";caseS7Consts.errCliAddressOutOfRange:return"CPU : Address out of range";caseS7Consts.errCliInvalidTransportSize:return"CPU : Invalid Transport size";caseS7Consts.errCliWriteDataSizeMismatch:return"CPU : Data size mismatch";caseS7Consts.errCliItemNotAvailable:return"CPU : Item not available";caseS7Consts.errCliInvalidValue:return"CPU : Invalid value supplied";caseS7Consts.errCliCannotStartPLC:return"CPU : Cannot start PLC";caseS7Consts.errCliAlreadyRun:return"CPU : PLC already RUN";caseS7Consts.errCliCannotStopPLC:return"CPU : Cannot stop PLC";caseS7Consts.errCliCannotCopyRamToRom:return"CPU : Cannot copy RAM to ROM";caseS7Consts.errCliCannotCompress:return"CPU : Cannot compress";caseS7Consts.errCliAlreadyStop:return"CPU : PLC already STOP";caseS7Consts.errCliFunNotAvailable:return"CPU : Function not available";caseS7Consts.errCliUploadSequenceFailed:return"CPU : Upload sequence failed";caseS7Consts.errCliInvalidDataSizeRecvd:return"CLI : Invalid data size received";caseS7Consts.errCliInvalidBlockType:return"CLI : Invalid block type";caseS7Consts.errCliInvalidBlockNumber:return"CLI : Invalid block number";caseS7Consts.errCliInvalidBlockSize:return"CLI : Invalid block size";caseS7Consts.errCliNeedPassword:return"CPU : Function not authorized for current protection level";caseS7Consts.errCliInvalidPassword:return"CPU : Invalid password";caseS7Consts.errCliNoPasswordToSetOrClear:return"CPU : No password to set or clear";caseS7Consts.errCliJobTimeout:return"CLI : Job Timeout";caseS7Consts.errCliFunctionRefused:return"CLI : function refused by CPU (Unknown error)";caseS7Consts.errCliPartialDataRead:return"CLI : Partial data read";caseS7Consts.errCliBufferTooSmall:return"CLI : The buffer supplied is too small to accomplish the operation";caseS7Consts.errCliDestroying:return"CLI : Cannot perform (destroying)";caseS7Consts.errCliInvalidParamNumber:return"CLI : Invalid Param Number";caseS7Consts.errCliCannotChangeParam:return"CLI : Cannot change this param now";caseS7Consts.errCliFunctionNotImplemented:return"CLI : Function not implemented";default:return"CLI : Unknown error (0x"+Convert.ToString(Error,16)+")";};}publicintLastError(){return_LastError;}publicintRequestedPduLength(){return_PduSizeRequested;}publicintNegotiatedPduLength(){return_PDULength;}publicintExecTime(){returnTime_ms;}publicintExecutionTime{get{returnTime_ms;}}publicintPduSizeNegotiated{get{return_PDULength;}}publicintPduSizeRequested{get{return_PduSizeRequested;}set{if(value<MinPduSizeToRequest)value=MinPduSizeToRequest;if(value>MaxPduSizeToRequest)value=MaxPduSizeToRequest;_PduSizeRequested=value;}}publicintPLCPort{get{return_PLCPort;}set{_PLCPort=value;}}publicintConnTimeout{get{return_ConnTimeout;}set{_ConnTimeout=value;}}publicintRecvTimeout{get{return_RecvTimeout;}set{_RecvTimeout=value;}}publicintSendTimeout{get{return_SendTimeout;}set{_SendTimeout=value;}}publicboolConnected{get{return(Socket!=null)&&(Socket.Connected);}}#endregion#regionforcejobpublicclassS7Forces{publicList<ForceJob>Forces;}internalintGetActiveForces(List<ForceJob>forces,byte[]forceframe){//sendingsecondpackageonlyifthereareforcejobsactiveSendPacket(forceframe);varlength=RecvIsoPacket();switch(WordFromByteArr(PDU,27)){default:_LastError=S7Consts.errTCPDataReceive;break;case0x000://creatingbyte[]withlengthofusefuldata(first67bytesaren'tusefuldata)byte[]forceData=newbyte[length-67];//copypdutootherbyte[]andremovetheunuseddataArray.Copy(PDU,67,forceData,0,length-67);//checkarraytransitiondefinition>value'sbyte[]splitDefData=newbyte[]{0x00,0x09,0x00};intSplitposition=0;for(intx=0;x<forceData.Length-3;x=x+6){//checkingwhenthedefinitionsgotodata(thedatastartswithsplitdefinitiondataandtheamountofbytesbeforeshouldalwaysbeapluralof6)if(forceData[x]==splitDefData[0]&&forceData[x+1]==splitDefData[1]&&forceData[x+2]==splitDefData[2]&&x%6==0){Splitposition=x;break;}}//calculatingamountofforcesintamountForces=Splitposition/6;//settingfirstbytefromdataintdataposition=Splitposition;for(intx=0;x<amountForces;x++){ForceJobforce=newForceJob{//bitvalueBitAdress=(forceData[(1+(6*x))]),//bytevalueByteAdress=((forceData[(4+(6*x))])*256)+(forceData[(5+(6*x))])};//foceidentityswitch(forceData[0+(6*x)]){case0x0:force.ForceType="M";break;case0x1:force.ForceType="MB";force.BitAdress=null;break;case0x2:force.ForceType="MW";force.BitAdress=null;break;case0x3:force.ForceType="MD";force.BitAdress=null;break;case0x10:force.ForceType="I";break;case0x11:force.ForceType="IB";force.BitAdress=null;break;case0x12:force.ForceType="IW";force.BitAdress=null;break;case0x13:force.ForceType="ID";force.BitAdress=null;break;case0x20:force.ForceType="Q";break;case0x21:force.ForceType="QB";force.BitAdress=null;break;case0x22:force.ForceType="QW";force.BitAdress=null;break;case0x23:force.ForceType="QD";force.BitAdress=null;break;//ifyougetthiscodeYoucanadditinthelistabove.default:force.ForceType=forceData[0+(6*x)].ToString()+" unknown";break;}//settingforcevaluedependingonthedatalengthswitch(forceData[dataposition+3])//Datalengthfromforce{case0x01:force.ForceValue=forceData[dataposition+4];break;case0x02:force.ForceValue=WordFromByteArr(forceData,dataposition+4);break;case0x04:force.ForceValue=DoubleFromByteArr(forceData,dataposition+4);break;default:break;}//calculatingwhenthenextforcestartvarnextForce=0x04+(forceData[dataposition+3]);if(nextForce<6){nextForce=6;}dataposition+=nextForce;//addingforcetolistforces.Add(force);}break;}return_LastError;}publicintGetForceValues300(refS7Forcesforces){_LastError=00;intElapsed=Environment.TickCount;List<ForceJob>forcedValues=newList<ForceJob>();SendPacket(S7_FORCE_VAL1);varLength=RecvIsoPacket();//whenresponseis45therearenoforcejobsactiveornocorrectresponsefromplcswitch(WordFromByteArr(PDU,27)){case0x0000://noerrorcodeif(WordFromByteArr(PDU,31)>=16){_LastError=GetActiveForces(forcedValues,S7_FORCE_VAL300);}break;default:_LastError=S7Consts.errTCPDataReceive;break;}forces.Forces=forcedValues;Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintGetForceValues400(refS7Forcesforces){_LastError=00;intElapsed=Environment.TickCount;List<ForceJob>forcedValues=newList<ForceJob>();SendPacket(S7_FORCE_VAL1);varLength=RecvIsoPacket();//whenresponseis45therearenoforcejobsactiveornocorrectresponsefromPLCswitch(WordFromByteArr(PDU,27)){case0x0000:if(WordFromByteArr(PDU,31)>=12){_LastError=GetActiveForces(forcedValues,S7_FORCE_VAL400);}break;default:_LastError=S7Consts.errTCPDataReceive;break;}forces.Forces=forcedValues;Time_ms=Environment.TickCount-Elapsed;return_LastError;}publicintWordFromByteArr(byte[]data,intposition){intresult=Convert.ToInt32((data[position]<<8)+data[position+1]);returnresult;}publicintDoubleFromByteArr(byte[]data,intposition){intresult=Convert.ToInt32((data[position]<<24)+(data[position+1]<<16)+(data[position+2]<<8)+(data[position+3]));returnresult;}//S7GetForceValuesframe1byte[]S7_FORCE_VAL1={0x03,0x00,0x00,0x3d,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x07,0x00,0x00,0x0c,0x00,0x20,0x00,0x01,0x12,0x08,0x12,0x41,0x10,0x00,0x00,0x00,0x00,0x00,0xff,0x09,0x00,0x1c,0x00,0x14,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00};//S7GetForceValuesframe2(300series)byte[]S7_FORCE_VAL300={0x03,0x00,0x00,0x3b,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x0c,0x00,0x00,0x0c,0x00,0x1e,0x00,0x01,0x12,0x08,0x12,0x41,0x11,0x00,0x00,0x00,0x00,0x00,0xff,0x09,0x00,0x1a,0x00,0x14,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x09,0x03};//S7GetForceValuesframe2(400series)byte[]S7_FORCE_VAL400={0x03,0x00,0x00,0x3b,0x02,0xf0,0x80,0x32,0x07,0x00,0x00,0x0c,0x00,0x00,0x0c,0x00,0x1e,0x00,0x01,0x12,0x08,0x12,0x41,0x11,0x00,0x00,0x00,0x00,0x00,0xff,0x09,0x00,0x1a,0x00,0x14,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x09,0x05};}publicclassForceJob{publicstringFullAdress{get{if(BitAdress==null){return$"{ForceType} {ByteAdress}";}else{return$"{ForceType} {ByteAdress}.{BitAdress}";}}}publicintForceValue{get;set;}publicstringForceType{get;set;}publicintByteAdress{get;set;}publicint?BitAdress{get;set;}publicstringSymbol{get;set;}publicstringComment{get;set;}}#regionCommentedForcepublicclassCommentForces{//Onlysymboltable'swith.seqextensionpublicList<ForceJob>AddForceComments(stringfilepath,List<ForceJob>actualForces){if(Path.GetExtension(filepath).ToLower()==".seq"){varSymbolTableDataText=ReadSymbolTable(filepath);if(SymbolTableDataText.Length>=1){varSymbolTableDataList=ConvertDataArrToList(SymbolTableDataText);varCommentedForceList=AddCommentToForce(actualForces,SymbolTableDataList);returnCommentedForceList;}}returnErrorSymbTableProces(actualForces);}privateList<ForceJob>AddCommentToForce(List<ForceJob>forceringen,List<SymbolTableRecord>symbolTable){List<ForceJob>commentedforces=newList<ForceJob>();foreach(ForceJobforceinforceringen){varfound=symbolTable.Where(s=>s.Address==force.FullAdress).FirstOrDefault();ForceJobcommentedforce=newForceJob();commentedforce=force;if(found!=null){commentedforce.Symbol=found.Symbol;commentedforce.Comment=found.Comment;}else{commentedforce.Symbol="NOT SET";commentedforce.Comment="not in variable table";}commentedforces.Add(commentedforce);}returncommentedforces;}privateList<SymbolTableRecord>ConvertDataArrToList(string[]text){List<SymbolTableRecord>Symbollist=newList<SymbolTableRecord>();foreach(varlineintext){SymbolTableRecordtemp=newSymbolTableRecord();string[]splited=newstring[10];splited=line.Split('\t');temp.Address=splited[1];temp.Symbol=splited[2];temp.Comment=splited[3];Symbollist.Add(temp);}returnSymbollist;}privatestring[]ReadSymbolTable(stringFilepath){string[]lines=System.IO.File.ReadAllLines(Filepath);returnlines;}privateList<ForceJob>ErrorSymbTableProces(List<ForceJob>actualForces){varerrorForceTable=actualForces;foreach(varforcerecordinerrorForceTable){forcerecord.Comment="Force Table could not be processed";forcerecord.Symbol="ERROR";}returnerrorForceTable;}}publicclassSymbolTableRecord{publicstringSymbol{get;set;}publicstringAddress{get;set;}publicstringComment{get;set;}}#endregion#endregion}