using Cksoft.Data; using Cksoft.Data.Repository; using Cksoft.Unity; using DllEapDal; using DllEapDal.OFILM; using DllEapEntity; using DllHsms; using Microsoft.Extensions.Logging; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; namespace DllBusinessServer { public class BusinessServer:IBusinessServer { private ILogger loger = null; public BusinessServer(ILogger loger) { this.loger = loger; CurrMaxBlock = long.Parse(AppConfigurtaionServices.Configuration["MaxBlock"]); CurrShareFileDir = AppConfigurtaionServices.Configuration["ShareFileDir"]; } private long CurrCount = 0; private IModel CurrQueueChannel = null; private string CurrRecQueueName = "hello";//接收队列名称 hsmsreceive+机台编号 private DataSet CurrDs = null; private DateTime CurrSTime = DateTime.Now;//开始时间 private int CurrDbTime = 30;//提交数据到数据库的间接时间,以秒为单位 //private DataSet CurrSecMstDs = null; private List CurrReportDetail = null; private List CurrInfo = new List();//记录错误信息 private int CurrStatus = -1;//未启动状态 private string CurrShareFileDir = ""; private long CurrMaxBlock = 0; //开始接收队列线程 public int StartRecQueue(ref string errorinfo) { try { //注册通道 CurrQueueChannel = RegeditChannel(ref errorinfo); if (CurrQueueChannel == null) { errorinfo = "注册队列通道发生错误,错误信息为:" + errorinfo; return -1; } //清空接收队列 //int result = ClearRecQueue(ref errorinfo); //if (result < 0) //{ // errorinfo = "清空接收队列发生错误,错误信息为:" + errorinfo; // return -1; //} CurrQueueChannel.QueueDeclare(CurrRecQueueName, false, false, false, null); //BasicQos函数是针对通道的,必须放在注册消费者前执行,否则注册的消费者会接受多条信息 CurrQueueChannel.BasicQos(0, 1, false); var consumer = new EventingBasicConsumer(CurrQueueChannel); CurrQueueChannel.BasicConsume(queue: CurrRecQueueName, autoAck: false, //是否不要手动应答(no manual Ack),ture自动应答,自动删除处理消息;false手动应答,服务器的消息会等待应答结果才消除 consumer: consumer); consumer.Received += QueueReceive; CurrSTime = DateTime.Now; return 1; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return -1; } } //注册通道 private IModel RegeditChannel(ref string errorinfo) { try { var factory = new ConnectionFactory(); factory.HostName = AppConfigurtaionServices.Configuration["rabbitmq:IPAddress"]; factory.UserName = AppConfigurtaionServices.Configuration["rabbitmq:UserName"]; factory.Password = AppConfigurtaionServices.Configuration["rabbitmq:Password"]; CurrDbTime = int.Parse(AppConfigurtaionServices.Configuration["rabbitmq:dbtime"]); var connection = factory.CreateConnection(); var channel = connection.CreateModel(); return channel; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return null; } } private int ClearRecQueue(ref string errorinfo) { try { CurrQueueChannel.QueueDelete(CurrRecQueueName, true, false); return 1; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return -1; } } private void QueueReceive(object model, BasicDeliverEventArgs ea) { CurrCount++; //textBox2.Text = CurrCount.ToString(); //SetText2(CurrCount.ToString()); CurrCount++; string errorinfo = ""; string maccode = ""; int result = IMcaSecVMst01(ea.Body,ref maccode, ref errorinfo); if (result <= 0) { SetText(maccode,errorinfo); CurrQueueChannel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: true); } else { CurrQueueChannel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); } } //判断事件是否与最后事件相同,返回值为该机台最后事件记录ID值 public int JudgeEventSame(DataSet orgds, McaSecVMst mst, List lists, ref string errorinfo) { try { //说明不是事件,直接返回 if (mst.FType <= 0) { if (mst.FType == int.Parse(orgds.Tables["McaSecVMst"].Rows[0]["FType"].ToString()) && mst.FStatus == int.Parse(orgds.Tables["McaSecVMst"].Rows[0]["FStatus"].ToString())) return 1; return 0; } string mcacode = mst.McaCode;// mainrow["McaCode"].ToString(); string eventcode = orgds.Tables["McaSecVMst"].Rows[0]["eventcode"].ToString(); if (eventcode != mst.EventCode) return 0; //DataRow[] orgrows = ds.Tables["oab"].Select("", "参数代码"); if (lists.Count != orgds.Tables["McaSecVDetail"].Rows.Count) return 0; DataRow[] orgrows = orgds.Tables["McaSecVDetail"].Select("", "fnum"); for (int i = 0; i < orgrows.Length; i++) { if (orgrows[i]["fcode"].ToString() != lists[i].FCode) return 0; if (orgrows[i]["fval"].ToString() != lists[i].FVal) return 0; } return 1; } catch (Exception ex) { errorinfo = "JudgeEventSame" + ex.Message.ToString(); return -1; } } private Guid AddRowToCurrDs(DataRow desrow, McaSecVMst orgrow, ref string errorinfo) { try { Guid id = Guid.NewGuid(); desrow["McaCode"] = orgrow.McaCode; desrow["ptime"] = orgrow.ptime; desrow["FType"] = orgrow.FType; desrow["FStatus"] = orgrow.FStatus; desrow["EventCode"] = orgrow.EventCode; desrow["EventID"] = orgrow.EventID; desrow["ID"] = id; if(orgrow.EventCode==StandardCode.CEID_EachFinish) { desrow["etime"] = orgrow.ptime; desrow["FCount"] = 0; } if (orgrow.FType<=0) { desrow["etime"] = orgrow.ptime; desrow["FCount"] = 0; } return id; } catch (Exception ex) { errorinfo = "AddRowToCurrDs" + ex.Message.ToString(); return Guid.Empty; } } /// /// 将取到的事件数据添加到数据集里,原数据集里保存了最后事件数据 /// /// /// /// private int AddDataToCurrDs01(McaSecVMst mst, List lists, UInt32 orgfnum, ref string errorinfo) { try { StringBuilder sqlstr = new StringBuilder(100); //sqlstr.AppendFormat($"McaCode='{mainrow["McaCode"].ToString()}' and EventID={mainrow["EventID"].ToString()} and FType={mainrow["FType"].ToString()}"); //sqlstr.AppendFormat($"FStatus={mainrow["FStatus"].ToString()} and eventcode={mainrow["eventcode"].ToString()} and islast=1"); sqlstr.AppendFormat($"McaCode='{mst.McaCode}' and islast=1"); DataRow[] rows = CurrDs.Tables["mcasecvmst"].Select(sqlstr.ToString()); int result = 0; DataRow addrow = null; Guid newid = Guid.Empty; if (rows.Length > 0) { DataSet tempds = CurrDs.Clone(); tempds.Tables["mcasecvmst"].ImportRow(rows[0]); sqlstr.Clear(); sqlstr.AppendFormat($"preid='{rows[0]["ID"]}'"); DataRow[] ttrows = CurrDs.Tables["McaSecVDetail"].Select(sqlstr.ToString()); foreach (DataRow temprow in ttrows) { tempds.Tables["McaSecVDetail"].ImportRow(temprow); } result = JudgeEventSame(tempds, mst, lists, ref errorinfo); if (result < 0) return -1; if (result == 0) { //说明要新增 addrow = CurrDs.Tables["mcasecvmst"].NewRow(); CurrDs.Tables["mcasecvmst"].Rows.Add(addrow); newid = AddRowToCurrDs(addrow, mst, ref errorinfo); if (newid == Guid.Empty) return -1; } else { addrow = rows[0]; } } else { addrow = CurrDs.Tables["mcasecvmst"].NewRow(); CurrDs.Tables["mcasecvmst"].Rows.Add(addrow); newid = AddRowToCurrDs(addrow, mst, ref errorinfo); if (newid == Guid.Empty) return -1; } if (newid != Guid.Empty && mst.FType > 0) { //说明新增了主档,需要复制明细 foreach (var temprow in lists) { DataRow ttaddrow = CurrDs.Tables["McaSecVDetail"].NewRow(); CurrDs.Tables["McaSecVDetail"].Rows.Add(ttaddrow); ttaddrow["fcode"] = temprow.FCode; ttaddrow["fval"] = temprow.FVal; ttaddrow["fnum"] = temprow.FNum; ttaddrow["preid"] = newid; } } //将该机台的所有 事件标记为不是最后事件 sqlstr.Clear(); sqlstr.AppendFormat($"McaCode='{mst.McaCode}'"); rows = CurrDs.Tables["mcasecvmst"].Select(sqlstr.ToString()); foreach (DataRow temprow in rows) temprow["islast"] = 0; //将新增的行置为最后行 addrow["islast"] = 1; //添加跟踪记录,不管是否新增,这条记录都是要添加的 DataRow detailrow = CurrDs.Tables["McaSecTime"].NewRow(); CurrDs.Tables["McaSecTime"].Rows.Add(detailrow); detailrow["preid"] = addrow["id"]; detailrow["ptime"] = mst.ptime; detailrow["OrgFNum"] = orgfnum;// mainrow["OrgFNum"]; return 1; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return -1; } } private List ComParams(OrderDetail order, List lists, ref string errorinfo) { try { int sval = order.SVal; int fval = order.FVal; List tempdt = null; if (sval == 6 && fval == 11) { tempdt = HsmsUnity.GetOrderS6F11Dt(lists, CurrReportDetail, ref errorinfo); if (tempdt == null) { errorinfo = "GetOrderS6F11Dt函数错误:" + errorinfo; return null; } } else if (sval == 5 && fval == 1) { tempdt = HsmsUnity.GetOrderS5F1Dt(lists, ref errorinfo); if (tempdt == null) { errorinfo = "GetOrderS5F1Dt函数错误:" + errorinfo; return null; } } else { errorinfo = "未知指令。"; return null; } return tempdt; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return null; } } //使用新的函数,将数据存入mysql private int IMcaSecVMst01(byte[] datas, ref string maccode, ref string errorinfo) { IDatabase db = null; try { OrderBlock entity = EntityHelper.DeSerializeBytes(datas); int result = entity.RecoverData(CurrShareFileDir, ref errorinfo); if (result <= 0) return -1; if(entity.MainMsg.McaCode=="DIBD0049") { int a = 100; } if (!(entity.CurrOrder.SVal == 5 && entity.CurrOrder.FVal == 1)) return 1; string eventcode = HsmsUnity.GetEventCode(DbFactory.Base(DllSqlCoreAcc.SqlCoreAcc.CurrMySqlCode), entity.MainMsg.McaCode, entity.CurrOrder, entity.Datalists, ref errorinfo); entity.MainMsg.EventCode = eventcode; //数据转换 maccode = entity.MainMsg.McaCode; int ftype = entity.MainMsg.FType;// int.Parse(orgds.Tables["McaSecVMst"].Rows[0]["FType"].ToString()); OrderDetail orderdetail = entity.CurrOrder; List lists = entity.Datalists; List details = null; UInt32 orgfnum = 0; if (ftype > 0) { //orderdetail = entity.blockdata.GetDataContext(lists, ref errorinfo); details = ComParams(orderdetail, lists, ref errorinfo); if (details == null) return -1; orgfnum = UInt32.Parse(orderdetail.Remark); } db = DbFactory.Base(DllSqlCoreAcc.SqlCoreAcc.CurrMySqlCode); db.BeginTrans(); McaSecVMstDal dal = new McaSecVMstDal(db); McaSecVMst mst = dal.BatMcaSecVMst(entity.MainMsg, details, orgfnum, "", ref errorinfo); if(eventcode== StandardCode.CEID_AlarmOccurred) { MtbacodeDal mtbacodeDal = new MtbacodeDal(db); mtbacodeDal.InsertMtabcode(entity.MainMsg, details, ref errorinfo); } if (mst == null) { db.Rollback(); return -1; } db.Commit(); return 1; } catch (Exception ex) { errorinfo = "IMcaSecVMst01" + ex.ToString(); return -1; } finally { if (db != null) db.Close(); } } //2019-10-28注销,改用新的方法,把数据存入mysql数据库 //private int IMcaSecVMst01(byte[] datas,ref string maccode, ref string errorinfo) //{ // try // { // OrderBlock entity = EntityHelper.DeSerializeBytes(datas); // //DataSet orgds = MsgPackage.MsgPackage.BytesToDataSet(datas, ref errorinfo); // //if (orgds == null) // // return -1; // //数据转换 // maccode = entity.MainMsg.McaCode; // int ftype = entity.MainMsg.FType;// int.Parse(orgds.Tables["McaSecVMst"].Rows[0]["FType"].ToString()); // OrderDetail orderdetail = entity.CurrOrder; // List lists = entity.Datalists; // List details = null; // UInt32 orgfnum = 0; // if (ftype > 0) // { // //orderdetail = entity.blockdata.GetDataContext(lists, ref errorinfo); // details = ComParams(orderdetail, lists, ref errorinfo); // if (details == null) // return -1; // orgfnum = UInt32.Parse(orderdetail.Remark); // } // //DataSet orgds = MsgPackage.MsgPackage.BytesToDataSet(datas, ref errorinfo); // //if (orgds == null) // // return -1; // ////数据转换 // //int ftype = int.Parse(orgds.Tables["McaSecVMst"].Rows[0]["FType"].ToString()); // //if (ftype > 0) // //{ // // int ttresult = ComParams(orgds, ref errorinfo); // // if (ttresult <= 0) // // return -1; // //} // //如果是机器状态变化,变成运行中的状态,则要判断是否符合开始生产条件 // //将数据添加到currds中 // int result = AddDataToCurrDs01(entity.MainMsg, details, orgfnum, ref errorinfo); // if (result <= 0) // { // return -1; // } // //如果是料盒装载或卸载事件,则提交数据 // switch(entity.MainMsg.EventCode) // { // case StandardCode.CEID_InBoxDown: // case StandardCode.CEID_InBoxLoad: // case StandardCode.CEID_OutBoxDown: // case StandardCode.CEID_OutBoxLoad: // result = SingleProcessCurrDs(ref errorinfo); // return result; // } // DateTime etime = DateTime.Now; // TimeSpan diff = etime - CurrSTime; // if ((diff.Minutes * 60 + diff.Seconds) > CurrDbTime) // { // //说明已经过了60秒没有提交数据库,需要提交 // //SqlAcc mysqlacc = new SqlAcc(); // result = SingleProcessCurrDs(ref errorinfo); // return result; // } // return 1; // } // catch (Exception ex) // { // errorinfo = "IMcaSecVMst01" + ex.Message.ToString(); // return -1; // } //} /// /// 处理CurrDs,针对单个芯片完成事件,累加 /// /// /// private int SingleProcessCurrDs(ref string errorinfo) { try { //处理单个芯片完成事件 DataRow[] finish = CurrDs.Tables["mcasecvmst"].Select($"EventCode='{StandardCode.CEID_EachFinish}'"); int vcount = 0; //object subcount = ""; DataRow[] subrows = null; foreach(var row in finish) { vcount = string.IsNullOrEmpty(row["FCount"].ToString()) ? 0 : int.Parse(row["FCount"].ToString()); //subcount=CurrDs.Tables["McaSecTime"].Compute("count(*)", $"PreID='{row["ID"].ToString()}'").ToString(); //vcount += string.IsNullOrEmpty(subcount) ? 0 : int.Parse(subcount); //subcount = CurrDs.Tables["McaSecTime"].Compute("max(ptime)", $"PreID='{row["ID"].ToString()}'").ToString(); //if(string.IsNullOrEmpty(subcount.ToString())) //{ // //说明是以前的数据 // row["etime"] = row["ptime"]; // row["FCount"] = 1; //} //else //{ // row["etime"] =subcount; //} //删除芯片完成操作明细 subrows = CurrDs.Tables["McaSecTime"].Select( $"PreID='{row["ID"].ToString()}'", "ptime"); //if(subrows.Length<=0) 这个地方不对,如果当前操作已经存在数量,而此次没有打的事件,那么就会把当前数量置为1, //{ // row["etime"] = row["ptime"]; // row["FCount"] = 1; //} //else //{ // row["etime"] = subrows[subrows.Length-1]["ptime"]; //} if(subrows.Length>0) { vcount += subrows.Length; row["FCount"] = vcount; row["etime"] = subrows[subrows.Length - 1]["ptime"]; } //删除芯片完成操作明细记录,机台WKB-076,WKB-075的明细继续保存,以便验证 if (row["McaCode"].ToString().ToLower() == "wkb-076" || row["McaCode"].ToString().ToLower() == "wkb-075") continue; foreach (DataRow ttrow in subrows) ttrow.Delete(); } //删除ftype的操作明细记录 DataRow[] FTyperows = CurrDs.Tables["mcasecvmst"].Select($"FType<=0"); foreach (var row in FTyperows) { vcount = string.IsNullOrEmpty(row["FCount"].ToString()) ? 0 : int.Parse(row["FCount"].ToString()); //删除芯片完成操作明细 subrows = CurrDs.Tables["McaSecTime"].Select($"PreID='{row["ID"].ToString()}'", "ptime"); if (subrows.Length > 0) { vcount += subrows.Length; row["FCount"] = vcount; row["etime"] = subrows[subrows.Length - 1]["ptime"]; } //删除芯片完成操作明细记录 foreach (DataRow ttrow in subrows) ttrow.Delete(); } DllSqlCoreAcc.SqlCoreAcc mysqlacc = new DllSqlCoreAcc.SqlCoreAcc(); int result = mysqlacc.BatIMcaSecVMst01(CurrDs, ref errorinfo); CurrSTime = DateTime.Now; if (result <= 0) { //需要将数据保存成文件,供以后处理 } //清空CurrDs DataRow[] temprows = CurrDs.Tables["mcasecvmst"].Select("islast=0"); foreach (DataRow temprow in temprows) { //删除McaSecVDetail表记录 DataRow[] ttrows = CurrDs.Tables["McaSecVDetail"].Select("preid='" + temprow["ID"].ToString() + "'"); foreach (DataRow ttrow in ttrows) ttrow.Delete(); temprow.Delete(); } CurrDs.Tables["McaSecTime"].Clear(); CurrDs.AcceptChanges(); CurrSTime = DateTime.Now; return 1; } catch(Exception ex) { errorinfo = ex.Message.ToString(); return -1; } } /// /// 如果是机器状态变化,变成运行中的状态,则要判断是否符合开始生产条件 /// /// /// /// private int MacIsRun(DataSet datads, ref string errorinfo) { try { //数据转换 int ftype = int.Parse(datads.Tables["McaSecVMst"].Rows[0]["FType"].ToString()); if (ftype <= 0) return 1; DataRow orderrow = datads.Tables["oaa"].Rows[0]; int sval = int.Parse(orderrow["S值"].ToString()); int fval = int.Parse(orderrow["F值"].ToString()); if (!(sval == 6 && fval == 11)) return 1; string eventcode = datads.Tables["McaSecVMst"].Rows[0]["eventcode"].ToString(); if (eventcode != "C00009") return 1; DataRow[] rows = datads.Tables["oab"].Select("参数代码='S00004'"); if (rows.Length <= 0) { errorinfo = "未找到当前状态参数信息。"; return -1; } int val = int.Parse(rows[0]["数据内容"].ToString()); if (val != 1) return 1; string maccode = datads.Tables["McaSecVMst"].Rows[0]["机台编号"].ToString(); //说明当前机台状态为开始生产状态,这时候需要判断程序名称是否正确 if (JudgeMacIsReady(maccode, ref errorinfo)) return 1; //说明机台不符合生产条件,则发送停机指令 return 1; } catch (Exception ex) { errorinfo = "MacIsRun" + ex.Message.ToString(); return -1; } } /// /// 判断机台是否已经准备好生产 /// /// /// /// private bool JudgeMacIsReady(string maccode, ref string errorinfo) { try { return true; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return false; } } public void SetText(string maccode,string str) { loger.LogError($"机台编号={maccode};{str}"); if (CurrInfo.Count > 100) CurrInfo.RemoveAt(0); int id = 1; if (CurrInfo.Count > 0) { id = CurrInfo.Max(t => t.ID); id++; } ServerInfo entity = new ServerInfo(); entity.ID = id; entity.Info = str; CurrInfo.Add(entity); ////写入日志 //string errorinfo = ""; //WriteLog.WriteServicesLogStr(maccode, DateTime.Now, str, ref errorinfo); } public int Start(ref string errorinfo) { IDatabase CurrDb = null; try { CurrStatus = -1; CurrRecQueueName = AppConfigurtaionServices.Configuration["rabbitmq:recmqname"]; //DllSqlCoreAcc.SqlCoreAcc mysqlacc = new DllSqlCoreAcc.SqlCoreAcc(); //CurrDs = mysqlacc.ReadLastMcaSecVMst(ref errorinfo); //if (CurrDs == null) //{ // //MessageBox.Show("读取数据失败:" + errorinfo, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); // errorinfo = $"读取数据失败,错误信息:{errorinfo}"; // SetText("",errorinfo); // return -1; //} CurrDb = DbFactory.Base(DllSqlCoreAcc.SqlCoreAcc.CurrMySqlCode); CurrReportDetail = CurrDb.FindListForCondition("", ref errorinfo).ToList(); if (CurrReportDetail == null) { errorinfo = $"读取数据失败,错误信息:{errorinfo}"; SetText("", errorinfo); return -1; } int result = StartRecQueue(ref errorinfo); if (result < 0) { //MessageBox.Show("启动接受失败!" + errorinfo, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); errorinfo = $"启动消息队列失败,错误信息:{errorinfo}"; SetText("", errorinfo); return -1; } CurrStatus = 1; SetText("","启动成功。"); return 1; } catch(Exception ex) { errorinfo = ex.Message.ToString(); SetText("", errorinfo); return -1; } } public long GetAccount() { return CurrCount; } public int GetStatus(ref string errorinfo) { if (CurrStatus <= 0 && CurrInfo.Count > 0) { errorinfo = CurrInfo.Last().Info; } return CurrStatus; } //public List GetInfo() //{ // return CurrInfo; //} public int Stop(ref string errorinfo) { try { CurrStatus = -1; if (CurrQueueChannel != null) CurrQueueChannel.Close(); SetText("","停止服务成功。"); return 1; } catch (Exception ex) { SetText("",ex.Message.ToString()); return -1; } } public List GetInfo() { if (CurrInfo.Count <= 100) return CurrInfo; List templist = new List(); for (int i = CurrInfo.Count - 100; i < CurrInfo.Count; i++) templist.Add(CurrInfo[i]); return templist; } public int ClearInfo(ref string errorinfo) { try { CurrInfo.Clear(); return 1; } catch (Exception ex) { SetText("",ex.Message.ToString()); return -1; } } } }