using DataEntity.Rack; using DataEntity.Share; using DataRWDAL; using DriverLib.Engine; using HxEnum; using HxSocket; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Windows; using System.Windows.Media; using System.Xml; using XCommon; using XCommon.Log; using XCore; using XHandler.Controls.Run.Com; using XHandler.View; using XHandler.View.MethodProperty; using XImaging.Automation.Service.Interface; using XImagingXhandler.XDAL; using static HxEnum.OtherEnum; namespace XHandler.Controls { /// /// 涂布转板控制逻辑类 /// public class CoatingTransferControl { #region 变量 // 系统语言 private string m_currentCulture = string.Empty; private WellCalc wellCalc = new WellCalc(); #region 涂布用变量 public static MethodCoatingAndTransfer CoatingData = null; // 当前孔在所有有效孔中的排序 private static int m_curValidWellIndex = -1; // 全部有效孔位list:A1、B1、C1 private static List m_lstAllValidWells = new List(); // 涂布台面位置 private static string m_coatingLatticeName = string.Empty; // 涂布板位lattice_id private static int m_latticeid = -1; // 涂布耗材条码 private static string m_coatingLabwareBarcode = string.Empty; // 当前涂布板位的台面信息 private static XmlNode m_curCoatingLabNode = null; // 当前涂布的孔位:A1 private static string m_curValidWell = string.Empty; // 剩余有效孔位list:B1、C1 private static List m_lstResidueValidWells = new List(); // 主z轴默认安全坐标点距 private static float m_zAxisSafeVal = 0; #endregion #region BLL private static CoatingBll coatingBll = new CoatingBll(); private BacteriaBll bacteriaBll = new BacteriaBll(); #endregion // 运行界面 public static RunWnd LaunchView = null; public HxSocketClient socketTcpClientToRemote = null; #endregion /// /// 构造函数 /// public CoatingTransferControl() { m_currentCulture = Shared.SoftwareInformation.currentculture; } #region 执行涂布转板 /// /// 执行涂布转板 /// /// /// /// /// 0:异常结束, 1:正常继续(跳出for),2:正常结束 public int ExecuteCoatingTransfer(XmlNode xmlEnv, XmlNode methodNode, bool isSimulator) { int nResult = 2; var platformNodeList = xmlEnv.SelectNodes("platform"); string strMethodName = methodNode.SelectSingleNode("name").InnerText; #region 任务被取消 if (LaunchView._cancelSource.IsCancellationRequested) { nResult = 0; return nResult; } #endregion #region RunLog start if (m_currentCulture.Equals("zh-CN")) { LaunchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + strMethodName + "】" + Properties.MachineRunResource.strStart.ToString()); } else { LaunchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + strMethodName + "】start:"); } #endregion try { #region 数据准备 // 获取涂布信息 if (!GetInfo(methodNode, xmlEnv, isSimulator)) { nResult = 0; return nResult; } #endregion // 涂布板位的开盖 => 挑选节点已经执行 #region 涂布 // 获取板位坐标 Lattice latticeDes = LatticeDB.GetLatticeDataByIdFromdb(m_latticeid.ToString()); // 获取耗材信息 Labware labwareDes = LabwareDB.GetLabware(CoatingData.coatingLabwareAValue); // 获取板位孔的坐标数据 List lstTipsTable = ControlCom.GenerateWellCoordinate(labwareDes, latticeDes); // 获取耗材上指定孔位的坐标 TipsTable targetWellInfo = lstTipsTable.SingleOrDefault(t => t.lattice_id.Equals(m_latticeid.ToString()) && t.labware_id.Equals(CoatingData.coatingLabwareAValue) && t.wellname.Equals(m_curValidWell)); #region 涂布方式 1:回字型 2:Z字型;3:上下移动 if (CoatingData.coatingModeValue == EnumManagement.GetEnumValue(CoatingModeEnum.HuiziMode) || CoatingData.coatingModeValue == EnumManagement.GetEnumValue(CoatingModeEnum.ZMode) || CoatingData.coatingModeValue == EnumManagement.GetEnumValue(CoatingModeEnum.UpDownMode)) { #region 涂布 CoatingMParam coatingMParam = new CoatingMParam(); coatingMParam.xAxisVal = (float)Convert.ToDouble(targetWellInfo.axis_b_X.ToString()); coatingMParam.yAxisVal = (float)Convert.ToDouble(targetWellInfo.axis_b_Y.ToString()); coatingMParam.armId = Convert.ToInt32(CoatingData.armValue); coatingMParam.channelId = 1; float zVal = targetWellInfo.axis_b_Z; if (ChoiceTransferControl.BacteriaInfo != null) { // 涂布距离底部距离 zVal = zVal - float.Parse(ChoiceTransferControl.BacteriaInfo.coating_position_distance.ToString()); } coatingMParam.zAxisVal = zVal < 0 ? 0 : zVal; // 涂布主z轴移动坐标点距 coatingMParam.zChAxisVal = coatingMParam.zAxisVal; coatingMParam.coatingShape = CoatingData.coatingModeValue; // 涂布形状:1:回形;2:Z形;3:上下 // 涂布范围值:如果是圆形孔值为半径;如是方形孔值为边长一半 coatingMParam.rangeVal = labwareDes.well_shape == 1 ? ((float)labwareDes.well_mouth_radius) : ((float)(labwareDes.well_top_x / 2.0d)); coatingMParam.basezAxisVal = m_zAxisSafeVal; // 主z轴默认安全坐标点距 coatingMParam.coatingSpeed = float.Parse(ConfigurationManager.AppSettings["coatingSpeed"].ToString()); // 涂布电机速度 coatingMParam.coatingTipsOutWidth = ControlCom.OutWidthOfTip; // 涂布枪头头部外宽度 coatingMParam.coatingTipsInWidth = ControlCom.InWidthOfTip; // 涂布枪头头部内宽度 coatingMParam.enableSupersonic = false; coatingMParam.currentLengthOfTip = ControlCom.CurrentLengthOfTip; // 当前涂布安装枪头后,枪增加的长度 // 单孔板中心坐标x,y,z 字符串,逗号分割 coatingMParam.centerPointVal = ((float)latticeDes.lattice_X + ((float)latticeDes.lattice_length / 2)).ToString() + "," + ((float)latticeDes.lattice_Y + ((float)latticeDes.lattice_width / 2)).ToString() + "," + coatingMParam.zAxisVal.ToString(); coatingMParam.latticeName = m_coatingLatticeName; // 上下移动 if (coatingMParam.coatingShape == EnumManagement.GetEnumValue(CoatingModeEnum.UpDownMode)) { coatingMParam.zAxisVal -= CoatingData.distanceFromBottom; coatingMParam.zAxisOffsetVal = CoatingData.shakeDistanceValue; coatingMParam.zAxisOffsetCount = CoatingData.shakeCountValue; } // 执行涂布动作 bool bIsOk = ControlCom.RunCoating(LaunchView, strMethodName, coatingMParam, targetWellInfo, m_curValidWell, m_coatingLatticeName, m_coatingLabwareBarcode, isSimulator); if (!bIsOk) { return 0; } #endregion } #endregion #region 涂布方式 5:放液 else if (CoatingData.coatingModeValue == EnumManagement.GetEnumValue(CoatingModeEnum.DispenseMode)) { if (ChoiceTransferControl.ChoiceData == null) { LoggerRunHelper.ErrorLog(string.Format("[ExecuteCoatingTransfer]: ChoiceTransferControl.ChoiceData = null !!!")); return 0; } // 放液 bool bDispense = ControlCom.DoDispense(LaunchView, strMethodName, ChoiceTransferControl.ChoiceData.choiceAgoAspirateData, labwareDes, latticeDes, targetWellInfo, m_coatingLabwareBarcode, isSimulator); if (!bDispense) { return 0; } } #endregion #endregion #region 卸载Tip,丢在垃圾桶 UnloadTipsControl unloadTipsControl = new UnloadTipsControl(Shared.SoftwareInformation.currentculture); unloadTipsControl.launchView = LaunchView; unloadTipsControl.socketTcpClientToRemote = socketTcpClientToRemote; bool bUnloadResult = unloadTipsControl.ExecuteUnloadTipsInToTrash(platformNodeList, methodNode, isSimulator); LaunchView.currentIsLoadingTips = false; #endregion #region 自动关盖 // 获取挑菌类型所有效的孔 ResidueValidWells residueValidWells = ChoiceTransferControl.GetResidueValidWells(); bool isForceCloseClover = residueValidWells == null ? true : false; // 自动关闭挑选板盖 bool bResult = ChoiceTransferControl.CloseClover(xmlEnv, isSimulator, isForceCloseClover); if (!bResult) { return 0; } // 自动关闭涂布板盖 bResult = CloseClover(xmlEnv, isSimulator, isForceCloseClover); if (!bResult) { return 0; } #endregion // 删除当前涂布孔位 m_lstResidueValidWells.RemoveAt(0); // 更新剩余有效孔位 m_curCoatingLabNode.SelectSingleNode("residueValidWells").InnerText = string.Join(",", m_lstResidueValidWells); } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); #region Exception LaunchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】>Xhandler: 【" + strMethodName + "】error:source:" + ex.Source + ";error:" + ex.Message + ";"); nResult = 0; #region Del //MethodMsg methodMsg = new MethodMsg( // Guid.NewGuid().ToString(), // "ID202_Choice_machine", // 5, // "", // "ExecuteCoatingFile", // "1001", // "error source:" + ex.Source + ";error:" + ex.Message, // 6, // 0 //); //if (socketTcpClientToRemote != null) //{ // socketTcpClientToRemote.sendmessageError(socketTcpClientToRemote.CreateSendMsgContent(methodMsg, false), LaunchView.isRemotingOper); //} #endregion #endregion } return nResult; } #endregion #region 自动开挑选板盖 /// /// 自动开挑选板盖 /// /// /// /// /// public static bool OpenClover(XmlNode xmlEnv, XmlNode methodNode, bool isSimulator) { bool bResult = true; // 获取涂布信息 if (!GetInfo(methodNode, xmlEnv, isSimulator)) { bResult = false; return bResult; } // 自动开盖: 当前孔是第一个有效孔 if (CoatingData != null && CoatingData.autoOpenCloseCover == 1 && m_curValidWellIndex == 0) { // 挑菌的板放盖位号:P2,P3 List listCoatingCoverLatticeId = ComUtility.GetPlateCoverLatticeName(); // 转移板盖到放盖位方法 string strTransferPlateCoverMethodFileName = AppDomain.CurrentDomain.BaseDirectory + "\\" + ConfigurationManager.AppSettings["transferDesPlateCoverMethod"].ToString(); // 转移目标板的盖到放盖位:P13->P3 bResult = ControlCom.DoReadMethodFileAndActionTransfer(strTransferPlateCoverMethodFileName, xmlEnv, m_coatingLatticeName, PositonTypeEnum.Desktop, GripperModelEnum.Right, listCoatingCoverLatticeId[1], PositonTypeEnum.Desktop, GripperModelEnum.Right, isSimulator, LaunchView, TransferTypeEnum.Open); return bResult; } return bResult; } /// /// 自动关挑选板盖 /// /// /// /// 是否强制关盖 /// public static bool CloseClover(XmlNode xmlEnv, bool isSimulator, bool isForceCloseClover = false) { bool bResult = true; // 自动关盖: 当前孔是第最后一个有效孔 if (CoatingData != null && CoatingData.autoOpenCloseCover == 1 && ((m_curValidWellIndex == m_lstAllValidWells.Count() - 1) || isForceCloseClover)) { // 挑菌的板放盖位号:P2,P3 List listCoatingCoverLatticeId = ComUtility.GetPlateCoverLatticeName(); // 转移板盖到放盖位方法 string strTransferPlateCoverMethodFileName = AppDomain.CurrentDomain.BaseDirectory + "\\" + ConfigurationManager.AppSettings["transferDesPlateCoverMethod"].ToString(); // 转移目标板的盖到板上:P2->P10 bResult = ControlCom.DoReadMethodFileAndActionTransfer(strTransferPlateCoverMethodFileName, xmlEnv, listCoatingCoverLatticeId[1], PositonTypeEnum.Desktop, GripperModelEnum.Right, m_coatingLatticeName, PositonTypeEnum.Desktop, GripperModelEnum.Right, isSimulator, LaunchView, TransferTypeEnum.Close); return bResult; } return bResult; } #endregion /// /// 获取涂布信息 /// /// /// /// /// private static bool GetInfo(XmlNode methodNode, XmlNode xmlEnv, bool isSimulator) { #region 数据准备1 // 获取涂布转移数据 CoatingData = coatingBll.GenerateMethodCoatingAndTransferDataByXmlNode(methodNode); m_curCoatingLabNode = null; // 当前涂布板位的台面信息 m_curValidWell = string.Empty; // 当前涂布的孔位:A1 m_lstResidueValidWells = new List(); // 剩余有效孔位list:B1、C1 m_coatingLatticeName = string.Empty; // 涂布台面位置 m_coatingLabwareBarcode = string.Empty; // 涂布耗材条码 // Z轴安全位置 m_zAxisSafeVal = (float)Convert.ToDouble(ConfigurationManager.AppSettings["zAxisSafeVal"]); LoggerHelper.InfoLog($"[CoatingTransferControl]:Args: { JsonConvert.SerializeObject(CoatingData) }"); #endregion #region 获取涂布类型所有效的孔 // 生成和涂布耗材类型一致的条件 string strCoatingLabwareWhere = string.Format("platform[labware_id='{0}']", CoatingData.coatingLabwareAValue); // 获取满足涂布耗材类型的所有台面点位 XmlNodeList coatingLabwareNodeList = xmlEnv.SelectNodes(strCoatingLabwareWhere); // 循环台面耗材点位,查找涂布耗材剩余量 #region 补充耗材数据准备 DataTable dtCoatingFile = new DataTable(); dtCoatingFile.Columns.Add("TargetB", typeof(string)); dtCoatingFile.Columns.Add("TargetBarcode", typeof(string)); dtCoatingFile.Columns.Add("IsNewPlateBatch", typeof(string)); #endregion foreach (XmlNode coatingLabNode in coatingLabwareNodeList) { #region 补充耗材数据准备 DataRow dtRow = dtCoatingFile.NewRow(); dtRow["TargetB"] = coatingLabNode.SelectSingleNode("labware_sname").InnerText; dtRow["TargetBarcode"] = ""; dtRow["IsNewPlateBatch"] = "false"; dtCoatingFile.Rows.Add(dtRow); #endregion string residueValidWells = coatingLabNode.SelectSingleNode("residueValidWells").InnerText; // 有效孔字符串转换成List m_lstResidueValidWells = ComUtility.GetValidWells(residueValidWells); if (m_lstResidueValidWells.Count == 0) { continue; } m_curCoatingLabNode = coatingLabNode; break; } // 涂布无剩余有效的孔,显示补充耗材提示 if (m_lstResidueValidWells.Count == 0) { // 状态6 报错/急停 红闪/蜂鸣5S CommonBll.StatusLamp(6, isSimulator); SetBarcodeDlgForAddConsumables setBarcodeDlg = null; bool bIsBreak = false; Application.Current.Dispatcher.Invoke(new Action(() => { #region 条码赋值 string strMsg = string.Format(Properties.CoatingResource.strNoValidConsumables, Environment.NewLine); setBarcodeDlg = new SetBarcodeDlgForAddConsumables(strMsg); setBarcodeDlg.launchView = LaunchView; setBarcodeDlg.dtCoatingFile = dtCoatingFile; SolidColorBrush mybtn1_Brush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(70, 0, 0, 0)); setBarcodeDlg.Background = (System.Windows.Media.Brush)mybtn1_Brush; setBarcodeDlg.ShowDialog(); if (setBarcodeDlg.DialogResult == true) { foreach (XmlNode choiceLabwareNode in coatingLabwareNodeList) { string labwareNameUpdate = choiceLabwareNode.SelectSingleNode("labware_sname").InnerText; DataRow[] selRowUpdate = dtCoatingFile.Select(string.Format("TargetB = '{0}'", labwareNameUpdate)); if (selRowUpdate != null) { string targetBarcode = selRowUpdate[0]["TargetBarcode"].ToString(); choiceLabwareNode.SelectSingleNode("labware_barcode").InnerText = targetBarcode; } // 更新已使用的涂布目标孔的颜色 ControlCom.UpdateDesPlateWellsColor(xmlEnv, choiceLabwareNode.SelectSingleNode("labware_sname").InnerText, LaunchView); } // 继续执行 // 状态4 运行 绿色 CommonBll.StatusLamp(4, isSimulator); } else { bIsBreak = true; } #endregion })); if (bIsBreak) { return false; } return GetInfo(methodNode, xmlEnv, isSimulator); } #endregion #region 数据准备2 // 全部有效孔list string allValidWells = m_curCoatingLabNode.SelectSingleNode("allValidWells").InnerText; m_lstAllValidWells = ComUtility.GetValidWells(allValidWells); // 当前涂布的孔位 m_curValidWell = m_lstResidueValidWells[0]; // 当前孔在所有有效孔中的排序 m_curValidWellIndex = m_lstAllValidWells.IndexOf(m_curValidWell); // 涂布板位:P13 m_coatingLatticeName = m_curCoatingLabNode.SelectSingleNode("labware_sname").InnerText; // 涂布耗材条码 m_coatingLabwareBarcode = m_curCoatingLabNode.SelectSingleNode("labware_barcode").InnerText; // 涂布板位lattice_id m_latticeid = ControlCom.GetLatticeId(Convert.ToInt32(m_curCoatingLabNode.SelectSingleNode("lattice_id").InnerText)); #endregion return true; } } }