using PlcSiemens.Communication; using PlcSiemens.Protocol.Common; using PlcSiemens.Protocol.ReadData; using PlcSiemens.Protocol.Szl; using PlcSiemens.ProtocolHandle; using System.Text; namespace PlcSiemens.O { public class SimenssPlc { public ConnectionType ConnectionType { get; private set; } public ushort SrcRef { get; set; } public ushort DstRef { get; set; } public ushort SrcTSap { get; private set; } public ushort DstTSap { get; private set; } public ushort PduRequest { get; set; } public int RecvTimeout { get; set; } public int RemotePort { get; set; } public int IsoPduSize { get; set; } // ReSharper disable once InconsistentNaming public string IP { get; private set; } public bool Connected { get { if (_socket == null) return false; return _socket.Connected; } } private Action _onMessageEvent; private readonly IsoSocket _socket; public SimenssPlc() { _socket = new IsoSocket(); PduRequest = 480; IsoPduSize = 1024; RecvTimeout = 3000; RemotePort = 102; SrcRef = 0x0001; // RFC0983 states that SrcRef and DetRef should be 0 // and, in any case, they are ignored. // S7 instead requires a number != 0 // Libnodave uses 0x0100 // S7Manager uses 0x0D00 // TIA Portal V12 uses 0x1D00 // WinCC uses 0x0300 // Seems that every non zero value is good enough... DstRef = 0x0000; SrcTSap = 0x0100; DstTSap = 0x0000; // It's filled by connection functions ConnectionType = ConnectionType.PG; } public SimenssPlc(string ip, int rack, int slot) { _socket = new IsoSocket(); PduRequest = 480 * 2; IsoPduSize = 1024; RecvTimeout = 3000; RemotePort = 102; SrcRef = 0x0001; // RFC0983 states that SrcRef and DetRef should be 0 // and, in any case, they are ignored. // S7 instead requires a number != 0 // Libnodave uses 0x0100 // S7Manager uses 0x0D00 // TIA Portal V12 uses 0x1D00 // WinCC uses 0x0300 // Seems that every non zero value is good enough... DstRef = 0x0000; SrcTSap = 0x0100; DstTSap = 0x0000; // It's filled by connection functions ConnectionType = ConnectionType.PG; var remoteTsap = (ushort)(((ushort)ConnectionType << 8) + (rack * 0x20) + slot); SetConnectionParams(ip, SrcTSap, remoteTsap); } #region 连接 public void RegisterMessageEvent(Action messageAction) { if (messageAction == null) throw new ArgumentNullException("messageAction"); _onMessageEvent = messageAction; } private void OnMessage(string method, string message) { if (_onMessageEvent != null) _onMessageEvent.Invoke(new MessageEvent(method, message)); } public void SetConnectionType(ConnectionType connectionType) { ConnectionType = connectionType; } public void SetConnectionParams(string ip, ushort localTsap, ushort remoteTsap) { SrcTSap = localTsap; DstTSap = remoteTsap; IP = ip; } public bool ConnectTo(string ip, int rack, int slot) { var remoteTsap = (ushort)(((ushort)ConnectionType << 8) + (rack * 0x20) + slot); SetConnectionParams(ip, SrcTSap, remoteTsap); return Connect(); } //暂时用系统SOCKET测试 private int _connecting;//连接中 private int _processing;//处理中 private string _processMehtod; public bool Connect() { try { if (Interlocked.CompareExchange(ref _connecting, 1, 0) != 0) return false; OnMessage("Connect", "正在连接"); if (!_socket.Connect(IP, 102)) return false; IsoControlPduHandle pduHandle = new IsoControlPduHandle() { IsoPduSize = IsoPduSize, DstRef = DstRef, DstTSap = DstTSap, SrcRef = SrcRef, SrcTSap = SrcTSap }; pduHandle.Handle(_socket); if (pduHandle.ResultCode == ResultCode.OK) { NegotiateHandle negotiateHandle = new NegotiateHandle() { PduRequest = PduRequest }; negotiateHandle.Handle(_socket); if (negotiateHandle.ResultCode == ResultCode.OK) { PduRequest = negotiateHandle.Responses[0].Params.PduLength; return true; } else { OnMessage("Connect", "PDU握手失败"); } } else { OnMessage("Connect", "PDU握手失败"); } } catch (Exception ex) { OnMessage("Connect", ex.Message); } finally { Interlocked.CompareExchange(ref _connecting, 0, 1); } return false; } #endregion 连接 public bool GetLock(string method) { if (Interlocked.CompareExchange(ref _processing, 1, 0) != 0) { OnMessage(method, "执行失败,{_processMehtod}处理正在执行中"); return false; } _processMehtod = method; return true; } public bool ReleaseLock() { _processMehtod = ""; return Interlocked.CompareExchange(ref _processing, 0, 1) == 0; } #region [System Info functions] private SzlResponse ReadSzlHelper(SzlCmd szlcmd) { SzlHandle handle = new SzlHandle { SzlCmd = szlcmd }; handle.Handle(_socket); return handle.SzlResponseFirst; } public SzlResponse ReadSzl(SzlCmd szlcmd) { if (!GetLock("ReadSzl")) { return null; } try { SzlHandle handle = new SzlHandle { SzlCmd = szlcmd }; handle.Handle(_socket); OnMessage("ReadSzl", "{handle.ResultCode}"); return handle.SzlResponseFirst; } catch (Exception ex) { OnMessage("ReadSzl", ex.Message); } finally { ReleaseLock(); } return null; } public OrderInfo GetOrderCode() { OrderInfo orderCode = new OrderInfo(); if (!GetLock("GetOrderCode")) { return orderCode; } try { var aaaa = ReadSzlHelper(SzlInfo.OrderCode); OnMessage("GetOrderCode", aaaa.Params.Err.ToString()); if (aaaa.Params.Err != ResultCode.OK) return orderCode; orderCode.Code = Encoding.UTF8.GetString(aaaa.Data.Data, 2, 20); orderCode.V1 = aaaa.Data.Data[aaaa.Data.Data.Length - 3]; orderCode.V2 = aaaa.Data.Data[aaaa.Data.Data.Length - 2]; orderCode.V3 = aaaa.Data.Data[aaaa.Data.Data.Length - 1]; return orderCode; } catch (Exception ex) { OnMessage("GetOrderCode", ex.Message); return orderCode; } finally { ReleaseLock(); } } public CpuInfo GetCpuInfo() { CpuInfo cpuInfo = new CpuInfo(); if (!GetLock("GetCpuInfo")) return cpuInfo; try { var aaaa = ReadSzlHelper(SzlInfo.CpuInfo); OnMessage("GetCpuInfo", aaaa.Params.Err.ToString()); if (aaaa.Params.Err != ResultCode.OK) return cpuInfo; cpuInfo.ModuleTypeName = Encoding.UTF8.GetString(aaaa.Data.Data, 172, 32).TrimEnd('\0'); cpuInfo.SerialNumber = Encoding.UTF8.GetString(aaaa.Data.Data, 138, 24).TrimEnd('\0'); cpuInfo.AsName = Encoding.UTF8.GetString(aaaa.Data.Data, 2, 24).TrimEnd('\0'); cpuInfo.Copyright = Encoding.UTF8.GetString(aaaa.Data.Data, 104, 26).TrimEnd('\0'); cpuInfo.ModuleName = Encoding.UTF8.GetString(aaaa.Data.Data, 36, 24).TrimEnd('\0'); } catch (Exception ex) { OnMessage("GetCpuInfo", ex.Message); } finally { ReleaseLock(); } return cpuInfo; } public CpInfo GetCpInfo() { CpInfo info = new CpInfo(); if (!GetLock("GetCpuInfo")) return info; try { var aaaa = ReadSzlHelper(SzlInfo.CpInfo); OnMessage("GetCpInfo", aaaa.Params.Err.ToString()); if (aaaa.Params.Err != ResultCode.OK) return info; info.MaxPduLengt = DWordAt(aaaa.Data.Data, 2, 2); //aaaa.ResDataFirst.Data[2] * 256 + aaaa.ResDataFirst.Data[3]; info.MaxConnections = DWordAt(aaaa.Data.Data, 4, 2); // aaaa.ResDataFirst.Data[4] * 256 + aaaa.ResDataFirst.Data[5]; info.MaxMpiRate = DWordAt(aaaa.Data.Data, 6, 4); //aaaa.ResDataFirst.Data[6] * 256 + aaaa.ResDataFirst.Data[7]; info.MaxBusRate = DWordAt(aaaa.Data.Data, 10, 4); //aaaa.ResDataFirst.Data[10] * 256 + aaaa.ResDataFirst.Data[7]; } catch (Exception ex) { OnMessage("GetCpInfo", ex.Message); } finally { ReleaseLock(); } return info; } #endregion [System Info functions] private int DWordAt(byte[] buffer, int index, int length) { int value = 0; for (int i = 0; i < length; i++) { value = (value << 8) + buffer[index + i]; } return value; } #region [Date/Time functions] public DateTime GetS7DateTime() { if (!GetLock("GetS7DateTime")) return DateTime.MinValue; try { GetDateTimeHandle handle = new GetDateTimeHandle(); handle.Handle(_socket); OnMessage("GetS7DateTime", handle.ResultCode.ToString()); if (handle.ResultCode == ResultCode.OK) { return handle.Response.GetDateTime(); } else { return DateTime.MinValue; } } catch (Exception ex) { OnMessage("GetS7DateTime", ex.Message); return DateTime.MinValue; } finally { ReleaseLock(); } } public bool SetS7DateTime(DateTime curDateTime) { if (!GetLock("SetS7DateTime")) return false; try { SetDateTimeHandle handle = new SetDateTimeHandle { DateTime = curDateTime }; handle.Handle(_socket); OnMessage("SetS7DateTime", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OKFF; } catch (Exception ex) { OnMessage("SetS7DateTime", ex.Message); return false; } finally { ReleaseLock(); } } #endregion [Date/Time functions] #region [Control functions] public S7CpuStatus GetPlcStatus() { S7CpuStatus status = S7CpuStatus.Unknown; if (!GetLock("GetPlcStatus")) { return status; } try { SzlResponse first = ReadSzlHelper(SzlInfo.PlcStatus); OnMessage("GetPlcStatus", first.Params.Err.ToString()); if (first.Params.Err == ResultCode.OK) { status = (S7CpuStatus)first.Data.Data[3]; if (status != S7CpuStatus.Run) status = S7CpuStatus.Stop; } return status; } catch (Exception ex) { OnMessage("GetPlcStatus", ex.Message); return status; } finally { ReleaseLock(); } } public bool PlcStop() { if (!GetLock("PlcStop")) return false; try { var handle = new PlcStopHandle(); handle.Handle(_socket); OnMessage("PlcStop", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("PlcStop", ex.Message); return false; } finally { ReleaseLock(); } } public bool PlcHotStart() { if (!GetLock("PlcHotStart")) return false; try { var handle = new PlcHotStartHandle(); handle.Handle(_socket); OnMessage("PlcHotStart", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("PlcHotStart", ex.Message); return false; } finally { ReleaseLock(); } } public bool PlcColdStart() { if (!GetLock("PlcColdStart")) return false; try { var handle = new PlcColdStartHandle(); handle.Handle(_socket); OnMessage("PlcColdStart", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("PlcColdStart", ex.Message); return false; } finally { ReleaseLock(); } } public bool CopyRamToRom() { if (!GetLock("CopyRamToRom")) return false; try { var handle = new CopyRamToRomHandle(); handle.Handle(_socket); OnMessage("CopyRamToRom", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("CopyRamToRom", ex.Message); return false; } finally { ReleaseLock(); } } public bool Compress() { if (!GetLock("Compress")) return false; try { var handle = new CompressHandle(); handle.Handle(_socket); OnMessage("Compress", handle.Response.Header.Error.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("Compress", ex.Message); return false; } finally { ReleaseLock(); } } #endregion [Control functions] #region [Security functions] public ProtectionInfo GetProtection() { ProtectionInfo info = new ProtectionInfo(); if (!GetLock("GetProtection")) { return info; } try { var sss = ReadSzlHelper(SzlInfo.Protection); OnMessage("GetProtection", sss.Data.Ret.ToString()); if (sss.Params.Err != ResultCode.OK) return info; info.SchSchal = (RWLevel)DWordAt(sss.Data.Data, 2, 2); info.SchPar = (ProtectionLevel)DWordAt(sss.Data.Data, 4, 2); info.SchRel = (CpuLevel)DWordAt(sss.Data.Data, 6, 2); info.BartSch = (RunStatus)DWordAt(sss.Data.Data, 8, 2); info.AnlSch = (StartupSwitch)DWordAt(sss.Data.Data, 10, 2); return info; } catch (Exception ex) { OnMessage("GetProtection", ex.Message); return info; } finally { ReleaseLock(); } } public bool SetPwd(string password) { if (!GetLock("SetPwd")) return false; try { var handle = new SetPasswordHandle { Password = password }; handle.Handle(_socket); OnMessage("SetPwd", handle.Response.Params.Err.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("SetPwd", ex.Message); return false; } finally { ReleaseLock(); } } public bool ClearPwd() { if (!GetLock("ClearPwd")) return false; try { var handle = new SetPasswordHandle(); handle.Handle(_socket); OnMessage("ClearPwd", handle.ResultCode.ToString()); return handle.ResultCode == ResultCode.OK; } catch (Exception ex) { OnMessage("ClearPwd", ex.Message); return false; } finally { ReleaseLock(); } } #endregion [Security functions] #region [Blocks] public ListBlocksHandle ListBlocks() { if (!GetLock("ListBlocks")) return null; try { var handle = new ListBlocksHandle(); handle.Handle(_socket); OnMessage("ListBlocks", handle.ResultCode.ToString()); return handle; } catch (Exception ex) { OnMessage("ListBlocks", ex.Message); return null; } finally { ReleaseLock(); } } public DataBlockOfTypeHandle ListBlocksOfType(BlockType blockType) { if (!GetLock("ListBlocksOfType")) return null; try { var handle = new DataBlockOfTypeHandle(); handle.BlockType = blockType; handle.Handle(_socket); OnMessage("ListBlocksOfType", handle.ResultCode.ToString()); return handle; } catch (Exception ex) { OnMessage("ListBlocksOfType", ex.Message); return null; } finally { ReleaseLock(); } } public DataBlockInfoHandle BlockInfoGet(ushort db, BlockType blockType) { if (!GetLock("BlockInfoHandle")) return null; try { var handle = new DataBlockInfoHandle(); handle.BlockType = blockType; handle.DB = db; handle.Handle(_socket); OnMessage("BlockInfoHandle", handle.ResultCode.ToString()); return handle; } catch (Exception ex) { OnMessage("BlockInfoHandle", ex.Message); return null; } finally { ReleaseLock(); } } #endregion [Blocks] private object readlock = new object(); public DataItem ReadArea(AreaType area, ushort db, ushort start, ushort amount, DataType dataType) { lock (readlock) { if (!GetLock("ReadArea")) { return null; } else { } try { var handle = new ReadHandle { PduLength = PduRequest, DataItem = new DataItem() { AreaType = area, Db = db, Start = start, Length = amount, DataType = dataType } }; handle.Handle(_socket); OnMessage("ReadArea", handle.ResultCode.ToString()); if (handle.ResultCode != ResultCode.OK) { throw new Exception(handle.ResultCode.ToString()); } return handle.DataItem; } catch (Exception ex) { OnMessage("ReadArea", ex.Message); } finally { ReleaseLock(); } return null; } } public ReadMultiHandle ReadMulti(List items) { if (!GetLock("ReadMulti")) return null; try { var handle = new ReadMultiHandle { DataItem = items }; handle.Handle(_socket); OnMessage("ReadMulti", handle.ResultCode.ToString()); return handle; } catch (Exception ex) { OnMessage("ReadMulti", ex.Message); return null; } finally { ReleaseLock(); } } public bool WriteArea(AreaType area, ushort db, ushort start, ushort amount, DataType dataType, byte[] writeData) { if (IP == "192.168.0.120" && db == 520) { if (start % 36 == 16) { if (writeData.Max() == 0) { } } else if (start % 36 == 0) { if (writeData.Length > 16) { if (writeData.Skip(16).Take(2).Max() == 0) { } } else { } } } if (!GetLock("WriteArea")) return false; try { var handle = new WriteHandle() { PduLength = PduRequest, DataItem = new DataItem() { AreaType = area, Db = db, Start = start, Length = amount, DataType = dataType, Data = writeData } }; OnMessage("WriteArea", handle.ResultCode.ToString()); handle.Handle(_socket); return handle.ResultCode == ResultCode.OK || handle.ResultCode == ResultCode.OKFF; } catch (Exception ex) { OnMessage("WriteArea", ex.Message); return false; } finally { ReleaseLock(); } } public WriteMultiHandle WriteMulti(List items) { if (!GetLock("WriteMulti")) return null; try { var handle = new WriteMultiHandle { DataItem = items }; handle.Handle(_socket); OnMessage("WriteMulti", handle.ResultCode.ToString()); return handle; } catch (Exception ex) { OnMessage("WriteMulti", ex.Message); return null; } finally { ReleaseLock(); } } // ReSharper disable once InconsistentNaming public DataItem DBGet(ushort db) { //if (!GetLock("DBGet")) return null; try { var handle = new DataBlockInfoHandle(); handle.BlockType = BlockType.DB; handle.DB = db; handle.Handle(_socket); if (handle.ResultCode == ResultCode.OK) { var res = ReadArea(AreaType.DB, handle.DB, 0, handle.Response.Data.Mc7Len, DataType.Byte); if (res.Err == ResultCode.OKFF) { return res; } OnMessage("DBGet", "ReadArea:{handle.ResultCode}"); } else OnMessage("DBGet", "RequestBlock:{handle.ResultCode}"); } catch (Exception ex) { OnMessage("DBGet", ex.Message); } //finally //{ // ReleaseLock(); //} return null; } // ReSharper disable once InconsistentNaming public bool DBFill(ushort db, byte value) { try { var handle = new DataBlockInfoHandle(); handle.BlockType = BlockType.DB; handle.DB = db; handle.Handle(_socket); if (handle.ResultCode == ResultCode.OK) { byte[] datas = new byte[handle.Response.Data.Mc7Len]; for (int i = 0; i < handle.Response.Data.Mc7Len; i++) { datas[i] = value; } return WriteArea(AreaType.DB, handle.DB, 0, handle.Response.Data.Mc7Len, DataType.Byte, datas); } else OnMessage("DBFill", "RequestBlock:{handle.ResultCode}"); return false; } catch (Exception ex) { OnMessage("DBFill", ex.Message); return false; } //finally //{ // ReleaseLock(); //} } public bool UpLoad(BlockType blockType, ushort db, bool isFull) { UploadStartHandle handle = new UploadStartHandle(); handle.BlockType = blockType; handle.BlockNum = db; handle.Handle(_socket); if (handle.ResultCode != ResultCode.OK) return false; UploadHandle handle1 = new UploadHandle(); handle1.UploadID = handle.Response.Params.UploadID; handle1.Handle(_socket); return false; } } }