using System; using System.Collections.Generic; using System.IO; using System.IO.Ports; using System.Linq; using System.Text; using System.Text.RegularExpressions; using UNI.MES.Core; using UNI.MES.Services; namespace UNI_IPC_MES.modules { /// <summary> /// 气密检查流程 /// </summary> public class AirtightnessWorkFlow : ModuleBaseFlow { //线程池,负责存取已扫条码到出库记录 private CoreThreadPool pool = new CoreThreadPool(); //检测通过的数据 private Queue<AirtghtnessResult> scanQueue = new Queue<AirtghtnessResult>(); private Regex codeRegex = new Regex(@"^Cd{8}$"); protected IModuleFlowFormService FlowFormService { get; private set; } /// <summary> /// Com端口的集合 /// </summary> protected Dictionary<string, object> ComPorts = new Dictionary<string, object>(); /// <summary> /// 缓存区集合,每个串口使用自己的缓冲区 /// </summary> protected Dictionary<string, List<byte>> revBuffer = new Dictionary<string, List<byte>>(); public AirtightnessWorkFlow(IModuleFlowFormService fromService) { FlowFormService = fromService; } /// <summary> /// 扫码条码处理 /// </summary> /// <param name="data"></param> public override void OnExecScanReceiving(string data) { var temp = data.Split("|".ToCharArray()); string flag = temp.LastOrDefault(); data = temp.FirstOrDefault(); if (data.IndexOf("NR") != -1) { string msg = string.Format("{0}道读取条码错误,NOREAD!", flag); RaiseException(this, msg, new object[] { data }); } if (codeRegex.IsMatch(data)) { RaiseInfo(this, string.Format("{0}道读取到条码[{1}]。", flag, data)); using (var db = new MESDb()) { string cmd = string.Format("select line from hkwsAll with(nolock) where code3='{0}'", data); string lineNo = db.Database.SqlQuery<string>(cmd).FirstOrDefault(); if (!lineNo.Equals(flowContext.LineNo)) { string msg = string.Format("{0}道校验条码错误,条码{1}上一站测试未通过,或者非本线产品!", flag, data); RaiseException(this, msg, new object[] { data }); } } if (flag.Equals("A")) { flowContext.L1Code = data; } if (flag.Equals("B")) { flowContext.L2Code = data; } RaiseCustomEvent("StartNewTest", "", flag, data); } else { string msg = string.Format("{0}道读取条码错误,编码规则错误!条码:{1}", flag, data); RaiseException(this, msg, new object[] { data }); } } /// <summary> /// 脚本初始化 /// </summary> protected override void BeforeWorkInit() { ComPorts.Clear(); revBuffer.Clear(); string path = AppDomain.CurrentDomain.BaseDirectory + "portname.txt"; using (var sr = new StreamReader(path, false)) { string str = ""; while ((str = sr.ReadLine()) != null) { #region 读取每一行 if (str.IndexOf("线体=") != -1) //找到txt中通道1的各行 { string[] mm = Regex.Split(str, "=", RegexOptions.IgnoreCase); //通过txt中_分隔符取出文件名信息,和超时信息 flowContext.LineNo = mm[1]; } else if (str.IndexOf("上层条码a=") != -1) //找到txt中通道1的各行 { string[] mm = Regex.Split(str, "=", RegexOptions.IgnoreCase); //通过txt中_分隔符取出文件名信息,和超时信息 ComPorts.Add("COM_Up_A", new SerialPort() { PortName = mm[1], BaudRate = 9600, DataBits = 8, StopBits = StopBits.One, //ParityReplace = 63, ReadBufferSize = 4096, WriteBufferSize = 2048 }); } else if (str.IndexOf("上层条码b=") != -1) //找到txt中通道1的各行 { string[] mm = Regex.Split(str, "=", RegexOptions.IgnoreCase); //通过txt中_分隔符取出文件名信息,和超时信息 ComPorts.Add("COM_Up_B", new SerialPort() { PortName = mm[1], BaudRate = 9600, DataBits = 8, StopBits = StopBits.One, //ParityReplace = 63, ReadBufferSize = 4096, WriteBufferSize = 2048 }); } else if (str.IndexOf("下层条码a=") != -1) //找到txt中通道1的各行 { string[] mm = Regex.Split(str, "=", RegexOptions.IgnoreCase); //通过txt中_分隔符取出文件名信息,和超时信息 ComPorts.Add("COM_Down_A", new SerialPort() { PortName = mm[1], BaudRate = 9600, DataBits = 8, StopBits = StopBits.One, //ParityReplace = 63, ReadBufferSize = 4096, WriteBufferSize = 2048 }); } else if (str.IndexOf("下层条码b=") != -1) //找到txt中通道1的各行 { string[] mm = Regex.Split(str, "=", RegexOptions.IgnoreCase); //通过txt中_分隔符取出文件名信息,和超时信息 ComPorts.Add("COM_Down_B", new SerialPort() { PortName = mm[1], BaudRate = 9600, DataBits = 8, StopBits = StopBits.One, //ParityReplace = 63, ReadBufferSize = 4096, WriteBufferSize = 2048 }); } #endregion } sr.Close(); } #region 启动参数检测 if (string.IsNullOrEmpty(flowContext.WorkStation)) { RaiseException(this, "请联系管理员设置工位或者线号!"); } if (string.IsNullOrEmpty(flowContext.Operator)) { RaiseException(this, "请点击'切换员工'进行身份验证!"); } #endregion #region 打开全部COM口 foreach (var com in ComPorts) { var sp = com.Value as SerialPort; try { sp.Open(); sp.DataReceived += Sp_DataReceived; revBuffer.Add(com.Key, new List<byte>(4096)); } catch (Exception ex) { RaiseException(this, ex.Message); } } #endregion pool.Exceute += Pool_Exceute; pool.Start(); flowContext.L1CountEx = 0; RaiseInfo(this, "程序初始化完成,准备就绪请开始作业!"); } /// <summary> /// 接收数据逻辑,是扫描枪的调用OnExecScanReceiving,是PLC的消息调用OnExecDataReceived /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { var sp = sender as SerialPort; var dict = ComPorts.SingleOrDefault(port => port.Value == sp); if (sp.BytesToRead == 0) { revBuffer[dict.Key].Clear(); return; } byte[] buffer = new byte[sp.BytesToRead]; int numofbyte = sp.Read(buffer, 0, buffer.Length); if (numofbyte > 0) { revBuffer[dict.Key].AddRange(buffer); } string revMessage = Encoding.UTF8.GetString(revBuffer[dict.Key].ToArray()).Trim(); if (dict.Key.IndexOf("Up") != -1 && revMessage.Length > 8) { string[] temp = revMessage.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); string message = temp.FirstOrDefault().Length > 9 ? temp.FirstOrDefault().Substring(0, 9) : temp.FirstOrDefault(); FrameAppContext.GetInstance().AppLogger.Info(string.Format("收到扫描枪数据:[{0}]", message)); OnExecScanReceiving(message + "|" + dict.Key.Split("_".ToCharArray()).LastOrDefault()); revBuffer[dict.Key].Clear(); } if (dict.Key.IndexOf("Down") != -1 && revMessage.Contains("OK")) { FrameAppContext.GetInstance().AppLogger.Info(string.Format("收到PLC数据:[{0}]", revMessage)); OnExecDataReceived(revMessage + "|" + dict.Key.Split("_".ToCharArray()).LastOrDefault()); revBuffer[dict.Key].Clear(); } //try //{ // if (sp.BytesToRead == 0) // { // revBuffer.Clear(); // return; // } // byte[] buffer = new byte[sp.BytesToRead]; // int numofbyte = sp.Read(buffer, 0, buffer.Length); // if (numofbyte > 0) // { // revBuffer.AddRange(buffer); // } // string line = Encoding.UTF8.GetString(revBuffer.ToArray()).Trim(); // if (line.Length > 8) // { // FrameAppContext.GetInstance().AppLogger.Info(string.Format("收到数据:[{0}]", line)); // } // 回车换行符是结束标志 // if (revBuffer) // { // var dict = ComPorts.SingleOrDefault(port => port.Value == sp); // if (dict.Key.IndexOf("Up") != -1) // { // if (line.Length < 11) // return; // string message = line.Substring(0, line.IndexOf(Environment.NewLine)); // FrameAppContext.GetInstance().AppLogger.Info(string.Format("收到扫描枪数据:[{0}]", message)); // OnExecScanReceiving(message + "|" + dict.Key.Split("_".ToCharArray()).LastOrDefault()); // } // if (dict.Key.IndexOf("Down") != -1) // { // string message = line.Substring(0, line.IndexOf(Environment.NewLine)); // FrameAppContext.GetInstance().AppLogger.Info(string.Format("收到PLC数据:[{0}]", message)); // OnExecDataReceived(message + "|" + dict.Key.Split("_".ToCharArray()).LastOrDefault()); // } // } //} //catch (Exception ex) //{ // FrameAppContext.GetInstance().AppLogger.Error(ex); //} } /// <summary> /// 执行数据库操作 /// </summary> /// <param name="obj"></param> private void Pool_Exceute(object obj) { if (obj is AirtghtnessResult && scanQueue.Contains(obj)) { AirtghtnessResult result = scanQueue.Peek(); using (var db = new MESDb()) { try { string cmd = string.Format(@"update hkwsAll set code4='{0}',name4='{1}',time4='{2}',fth=1,Res='成功' where code3='{3}'", result.Barcode, result.Oper, result.ResultTime, result.Barcode); db.Database.ExecuteSqlCommand(cmd); } finally { scanQueue.Dequeue(); } } } System.Threading.Thread.Sleep(100); } /// <summary> /// 接收到PLC返回的数据 /// </summary> /// <param name="data"></param> protected void OnExecDataReceived(string data) { var temp = data.Split("|".ToCharArray()); string flag = temp.LastOrDefault(); data = temp.FirstOrDefault(); string barcode = string.Empty; if (flag.Equals("A")) barcode = flowContext.L1Code; if (flag.Equals("B")) barcode = flowContext.L2Code; data.Replace("|" + flag, ""); #region 获取检测结果 byte[] buffer = Encoding.UTF8.GetBytes(data); int mol = 0; for (int i = 0; i < buffer.Length; i++) { if (buffer[i] == 0x6c) { mol = i; } } byte[] xlv = new byte[9]; xlv[0] = buffer[mol - 10]; xlv[1] = buffer[mol - 9]; xlv[2] = buffer[mol - 8]; xlv[3] = buffer[mol - 7]; xlv[4] = buffer[mol - 6]; xlv[5] = buffer[mol - 5]; xlv[6] = buffer[mol - 4]; xlv[7] = buffer[mol - 3]; xlv[8] = buffer[mol - 2]; if (flag.Equals("A")) flowContext.Parameter1 = Encoding.UTF8.GetString(xlv); if (flag.Equals("B")) flowContext.Parameter2 = Encoding.UTF8.GetString(xlv); #endregion AirtghtnessResult result = new AirtghtnessResult() { Barcode = barcode, LineNo = flowContext.LineNo, Oper = flowContext.Operator, ResultTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; data.Replace("NOK","NG"); //测试不通过 if (data.Contains("NG")) { if (flag.Equals("A")) flowContext.L1Code = string.Empty; if (flag.Equals("B")) flowContext.L2Code = string.Empty; RaiseCustomEvent("DataReceived", flag, "NG", string.Join("|", new string[] { barcode, data })); } else if (data.Contains("OK")) { scanQueue.Enqueue(result); pool.Post(result); RaiseCustomEvent("DataReceived", flag, "OK", string.Join("|", new string[] { barcode, data })); //计数加1 flowContext.L1CountEx++; } else { if (flag.Equals("A")) flowContext.L1Code = string.Empty; if (flag.Equals("B")) flowContext.L2Code = string.Empty; RaiseCustomEvent("DataReceived", flag, "NG", string.Join("|", new string[] { barcode, data })); } } /// <summary> /// 停止作业时的检查 /// </summary> protected override void StopWorkCheck() { if (scanQueue.Count > 0) { var list = scanQueue.ToArray(); if (list != null) { foreach (var dict in list) { pool.Post(dict); } } RaiseException(this, string.Format("还有已经检测的条码没有保存到数据库,请重试!")); } } /// <summary> /// 结束作业 /// </summary> public override void ExecEndWork() { pool.Stop(); foreach (var sp in ComPorts) { var com = sp.Value as SerialPort; com.Close(); } ComPorts.Clear(); base.ExecEndWork(); } /// <summary> /// 异常提醒方法 /// </summary> /// <param name="sender"></param> /// <param name="message"></param> /// <param name="args"></param> protected override void RaiseException(object sender, string message, params object[] args) { OnFeedInfo(sender, new Exception(message), message, MessageTipsLevel.Error); FlowFormService.ShowErrorAlertNotityForm(1000, 1888, message); } } }
虽然解决了别人老程序崩溃引起产线停线的事情,但是领导并没有高看我。哎!老程序是个菜鸟写的,他反反复复改了好几版还是像个DEMO。以前正常用了好久,刚开始产线工人还说我这个麻烦些。