using Houdar.PLC.Driver.Simenss; using Houdar.PLC.Driver.Simenss.Protocol.Common; using Houdar.PLC.Driver.Simenss.Protocol.ReadData; using System; using WCS.Data; using WCS.Data.Utils; namespace WCS.PLC { public class PLC { private readonly object olock = new object(); private string _plc_name = string.Empty; private PlcErrorCount _plcErrorCount = new PlcErrorCount() { ErrorCount = 0, LastTime = DateTime.MinValue }; private Action StopPlcEvent; internal SimenssPlc _splc = null; public PLC() { _splc = new SimenssPlc(); } //slot 插槽,port 端口,rack 道轨 public bool Connect(string ip, int rack, int slot) { if (_splc.ConnectTo(ip, rack, slot)) return true; return false; } public bool Connect(string ip, int rack, int slot, string plc_name) { if (_splc.ConnectTo(ip, rack, slot)) { _plc_name = plc_name; _splc.RegisterMessageEvent(PrintMsg); return true; } return false; } #region 读取值; public object ReadSignal(ushort DBNumber, ushort start, ushort len) { object obj = 0; byte[] msg = new byte[len]; if (Read(DBNumber, start, len, ref msg)) { if (len == 1) { //obj = BitConverter.ToUInt16(bt,0); obj = msg[0]; } else if (len == 2) { //byte[] temp = new byte[2]; //temp[0] = bt[1]; //temp[1] = bt[0]; //obj = BitConverter.ToInt16(temp, 0); obj = Convert.ToUInt16(msg[0] * 256 + msg[1]); } else if (len == 4) { //byte[] temp = new byte[4]; //temp[0] = bt[3]; //temp[1] = bt[2]; //temp[2] = bt[1]; //temp[3] = bt[0]; //obj = BitConverter.ToInt16(temp, 0); obj = Convert.ToUInt32(msg[0] * 256 * 256 * 256 + msg[1] * 256 * 256 + msg[2] * 256 + msg[3]); } } else { obj = 0; } return obj; } public bool ReadBit(ushort DBNumber, ushort start) { if (_splc.Connected) { DataItem di = _splc.ReadArea(AreaType.DB, DBNumber, start, 1, DataType.Bit); if (di != null && di.Err == ResultCode.OKFF) { return Convert.ToBoolean(di.Data[0]); } else { if (di != null) Log4netHelper.Logger_Error.ErrorFormat(di.Err.ToString()); return false; } } Log4netHelper.Logger_Error.ErrorFormat("PLC未连接。"); return false; } public bool ReadBitArea(ushort DBNumber, ushort start, ushort len, ref byte[] msg) { if (_splc.Connected) { for (int i = 0; i < len; i++) { DataItem di = _splc.ReadArea(AreaType.DB, DBNumber, (ushort)i, 1, DataType.Bit); if (di != null && di.Err == ResultCode.OKFF) { msg[i] = di.Data[0]; //return true; } else { if (di != null) Log4netHelper.Logger_Error.ErrorFormat(di.Err.ToString()); return false; } } return true; } Log4netHelper.Logger_Error.ErrorFormat("PLC未连接。"); return false; } public bool Read(ushort DBNumber, ushort start, ushort len, ref byte[] msg) { if (_splc.Connected) { DataType dt; if (len == 1) dt = DataType.Byte; else if (len == 2) dt = DataType.Word; else if (len == 4) dt = DataType.DWord; else return false; DataItem di = _splc.ReadArea(AreaType.DB, DBNumber, start, len, dt); if (di != null && di.Err == ResultCode.OKFF) { msg = di.Data; return true; } else { if (di != null) Log4netHelper.Logger_Error.ErrorFormat(di.Err.ToString()); return false; } } Log4netHelper.Logger_Error.ErrorFormat("PLC未连接。"); return false; } public bool ReadByteArea(ushort DBNumber, ushort start, ushort len, ref byte[] msg) { lock (olock) { try { if (_splc.Connected) { DataItem di = _splc.ReadArea(AreaType.DB, DBNumber, start, len, DataType.Byte); if (di != null && di.Err == ResultCode.OKFF) { msg = di.Data; return true; } else { if (di == null) { Log4netHelper.Logger_Error.ErrorFormat(string.Format("DB[{0}]读取失败,未查询到读取失败原因。", DBNumber)); if (PlcErrorIsFull(DBNumber)) { StopPlc(); } } else Log4netHelper.Logger_Error.ErrorFormat(string.Format("DB[{0}]读取失败,原因:[{1}]", DBNumber, di.Err.ToString())); return false; } } else { LogMessageHelper.RecordLogMessage(string.Format("PLC[{0}]DB[{1}]读取失败,Connected为fasle,系统将重新连接plc。", _plc_name, DBNumber)); } } catch (Exception ex) { Log4netHelper.Logger_Error.ErrorFormat(ex.ToString()); } } return false; } private void PrintMsg(MessageEvent msg) { if (msg.Message.Trim() != "OK") { Log4netHelper.Logger_Info.Info(string.Format("PLC通信DLL消息:方法:[{0}]消息[{1}]", msg.Method, msg.Message)); } } private bool PlcErrorIsFull(ushort dbnumber) { bool result = false; int count = 18; if (dbnumber == 520 || dbnumber == 521) { if (_plcErrorCount.ErrorCount == 0) { Log4netHelper.Logger_Error.ErrorFormat(string.Format("PLC[{0}]第一次报错,次数+1", _plc_name)); _plcErrorCount.ErrorCount = 1; _plcErrorCount.LastTime = DateTime.Now; } else if (_plcErrorCount.ErrorCount < count) { if (_plcErrorCount.LastTime.AddSeconds(10) > DateTime.Now) { _plcErrorCount.ErrorCount += 1; _plcErrorCount.LastTime = DateTime.Now; Log4netHelper.Logger_Error.ErrorFormat(string.Format("PLC[{0}]次数+1 ,现有次数[{1}]", _plc_name, _plcErrorCount.ErrorCount)); } else { _plcErrorCount.ErrorCount = 0; _plcErrorCount.LastTime = DateTime.Now; Log4netHelper.Logger_Error.ErrorFormat(string.Format("PLC[{0}]10秒未报错,次数重置", _plc_name, _plcErrorCount.ErrorCount)); } } else if (_plcErrorCount.ErrorCount >= count) { _plcErrorCount.ErrorCount = 0; LogMessageHelper.RecordLogMessage(string.Format("PLC[{0}]读取DB频繁返回Null值达到[{1}]次,将停止PLC连接,次数清零,并重启PLC连接。", _plc_name, count)); result = true; } } return result; } //public bool ReadWordArea(ushort DBNumber, ushort start, ushort len, ref byte[] msg) //{ // if (_splc.Connected) // { // DataItem di = _splc.ReadArea(AreaType.DB, DBNumber, start, len, DataType.Word); // if (di != null && di.Err == ResultCode.OKFF) // { // msg = di.Data; // return true; // } // else // { // Current.Logger_Error.ErrorFormat(di.Err.ToString()); // return false; // } // } // Current.Logger_Error.ErrorFormat("PLC未连接。"); // return false; //} #endregion; #region 写入值 public bool WriteSignal(ushort DBNumber, ushort start, ushort len, object msg) { lock (olock) { bool result = false; byte[] bt = new byte[len]; if (len == 1) { bt[0] = Convert.ToByte(msg); } else if (len == 2) { byte[] from_wcs = System.BitConverter.GetBytes(Convert.ToUInt16(msg)); bt[0] = from_wcs[1];//地位值 bt[1] = from_wcs[0];//高位值 } else if (len == 4) { byte[] from_wcs = System.BitConverter.GetBytes(Convert.ToUInt32(msg)); bt[0] = from_wcs[3]; bt[1] = from_wcs[2]; bt[2] = from_wcs[1]; bt[3] = from_wcs[0]; } result = Write(DBNumber, start, bt); return result; } } public bool WriteBits(ushort DBNumber, uint start, bool status) { lock (olock) { bool result = false; if (_splc.Connected) { byte[] bt = new byte[1]; bt[0] = Convert.ToByte(status); if (_splc.WriteArea(AreaType.DB, DBNumber, start, 1, DataType.Bit, bt)) { result = true; } else { Log4netHelper.Logger_Error.ErrorFormat("写入DB信息失败,PLC可能未连接。(WriteBits)"); } } else { Log4netHelper.Logger_Error.ErrorFormat("写入DB信息失败,PLC未连接。(WriteBits)"); } return result; } } public bool Write(ushort DBNumber, ushort start, byte[] msg) { lock (olock) { bool result = false; if (_splc.Connected) { //DataType dt; //if (len == 1) dt = DataType.Byte; //else if (len == 2) dt = DataType.Word; //else if (len == 4) dt = DataType.DWord; //else return false; if (_splc.WriteArea(AreaType.DB, DBNumber, start, (ushort)msg.Length, DataType.Byte, msg)) { result = true; } else { Log4netHelper.Logger_Error.ErrorFormat("写入DB信息失败,PLC可能未连接。(Write)"); } } else { Log4netHelper.Logger_Error.ErrorFormat("写入DB信息失败,PLC未连接。(Write)"); } return result; } } #endregion; public void PlcStop() { _splc.PlcStop(); } public void RegisterStopPlcEvent(Action stopPlcAction) { if (stopPlcAction == null) throw new ArgumentNullException("stopPlcAction"); StopPlcEvent = stopPlcAction; } private void StopPlc() { if (StopPlcEvent != null) StopPlcEvent.Invoke(); } } public struct PlcErrorCount { public int ErrorCount; public DateTime LastTime; } }