using DataEntity.Share; using DriverLib.Engine; using HxSocket; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Media; using System.Xml; using XCommon; using XCommon.Log; using XCore; using XHandler.Class; using XHandler.Controls.Run.Com; using XHandler.View; using XHandler.View.MethodProperty; using XImagingXhandler.XDAL; namespace XHandler.Controls { /// /// 文件移液控制逻辑类 /// public class TransferFileControl { #region 类内变量、引用类对象实例等 string strCurrentCulture = ""; WellCalc wellCalc = new WellCalc(); LatticeBll latticeBll = new LatticeBll(); AspirateBll aspirateBll = new AspirateBll(); public RunWnd launchView = null; MethodFrame methodFrame = new MethodFrame(); CoatingFileBll coatingFileBll = new CoatingFileBll(); CoatingBll coatingBll = new CoatingBll(); //Operate.UIElement uiElement = new Operate.UIElement();//控件元素操作类对象 TransferFileBll transferFileBll = new TransferFileBll(); DispenseBll dispenseBll = new DispenseBll(); LoadTipsBll loadTipsBll = new LoadTipsBll(); public HxSocketClient socketTcpClientToRemote = null; #endregion public TransferFileControl(string strCurrentCulture) { this.strCurrentCulture = strCurrentCulture; } #region 加载文件数据 /// /// 加载文件数据 /// /// /// /// private DataTable GetFileData(string methodName, string file) { DataTable transferData = null; if (!File.Exists(file)) { if (strCurrentCulture.Equals("zh-CN")) { launchView.AddLogs($"【{DateTime.Now.ToString("HH:mm:ss:fff")}】> Xhandler: 【{methodName}】{Properties.TransferFileResource.strFileNotExists} {file}"); } else { launchView.AddLogs($"【{DateTime.Now.ToString("HH:mm:ss:fff")}】> Xhandler: 【{methodName}】file not exists: {file}"); } return transferData; } string ext = Path.GetExtension(file); if (string.Compare(ext, ".csv", true) == 0) { transferData = ExcelAndCsvHelper.GetDataTableFromCsvFile(file, false); } else { transferData = ExcelAndCsvHelper.GetDataTableFromExcelFile(file, true); } return transferData; } #endregion #region 执行移液文件,返回结果字符串 /// /// 执行移液文件,返回结果字符串 /// /// 所有放板的板位 /// 装载方法属性节点对象 /// 本次使用的通道 /// 当前已加载的Tip头后枪增加的长度 /// z轴安全距离 /// false:连接谁;true:仿真 /// public bool ExecuteTransferFile(XmlNode xmlEnv, XmlNode methodNode, float zAxisVal, bool isSimulator) { bool result = true; var platformNodeList = xmlEnv.SelectNodes("platform"); string methodName = methodNode.SelectSingleNode("name").InnerText; if (launchView._cancelSource.IsCancellationRequested) { result = false; return result; } if (strCurrentCulture.Equals("zh-CN")) { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strStart.ToString()); } else { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】start:"); } #region 数据准备 string labwaretipText = methodNode.SelectSingleNode("labwaretip/text").InnerText; string strlabwaretipId = methodNode.SelectSingleNode("labwaretip/value").InnerText; string channelNums = methodNode.SelectSingleNode("channels").InnerText; string armName = methodNode.SelectSingleNode("arm/text").InnerText; string armId = methodNode.SelectSingleNode("arm/value").InnerText; string filePath = methodNode.SelectSingleNode("filePath").InnerText; int beginLine = Convert.ToInt32(methodNode.SelectSingleNode("beginLine").InnerText); MethodTransferFile methodTransferFile = methodFrame.GenerateMethodTransferFile(methodNode);//获取移液表 methodTransferFile.transferDataTable = GetFileData(methodName, methodNode.SelectSingleNode("filePath").InnerText); string cnSourceLabware = methodNode.SelectSingleNode("sourceLabware").InnerText;//来源板列名 string cnSourceWell = methodNode.SelectSingleNode("sourceWell").InnerText;//来源孔列名 string cnDestinationLabware = methodNode.SelectSingleNode("destinationLabware").InnerText;//目标板列名 string cnDestinationWell = methodNode.SelectSingleNode("destinationWell").InnerText;//目标孔列名 string cnDestVolume = methodNode.SelectSingleNode("destVolume").InnerText;//目标体积列名 string cnTipSet = methodNode.SelectSingleNode("tipSet").InnerText;//Tip设置 int cnChangeTipsMode = Convert.ToInt32(methodNode.SelectSingleNode("changeTipsMode").InnerText);//更换枪头设置 string cnChangeToTipText = methodNode.SelectSingleNode("changeToTipText").InnerText;//更换枪头设置下拉项名称 string cnChangeToTipValue = methodNode.SelectSingleNode("changeToTipValue").InnerText;//更换枪头设置下拉项Id bool cnJump0Volume = methodNode.SelectSingleNode("jump0Volume").InnerText.ToLower() == "true" ? true : false;//是否跳过为0的体积 string cnLiquididText = methodNode.SelectSingleNode("liquidid/text").InnerText;//液体名称 string cnLiquididValue = methodNode.SelectSingleNode("liquidid/value").InnerText;//液体Id string cnliquidrangeidText = methodNode.SelectSingleNode("liquidrangeid/text").InnerText;//液体范围名称 string cnliquidrangeidValue = methodNode.SelectSingleNode("liquidrangeid/value").InnerText;//液体范围Id string cnliquidpidText = methodNode.SelectSingleNode("liquidpid/text").InnerText;//液体参数名称 string cnliquidpidVaue = methodNode.SelectSingleNode("liquidpid/value").InnerText;//液体参数Id bool enableMix = methodNode.SelectSingleNode("enableMix").InnerText.ToLower() == "true" ? true : false;//是否混合 double mixvolume = Convert.ToDouble(methodNode.SelectSingleNode("mixvolume").InnerText);//混合体积 int mixcount = Convert.ToInt32(methodNode.SelectSingleNode("mixcount").InnerText);//混合次数 string mixAspiratePositionText = methodNode.SelectSingleNode("mixAspiratePosition/text").InnerText;//吸液混合位置名称 string mixAspiratePositionValue = methodNode.SelectSingleNode("mixAspiratePosition/value").InnerText;//吸液混合位置Id double mixAspirateDistance = Convert.ToDouble(methodNode.SelectSingleNode("mixAspirateDistance").InnerText);//吸液混合时距离 double mixAspirateSpeed = Convert.ToDouble(methodNode.SelectSingleNode("mixAspirateSpeed").InnerText);//吸液混合时速度 string mixDispensePositionText = methodNode.SelectSingleNode("mixDispensePosition/text").InnerText;//排液混合位置名称 string mixDispensePositionValue = methodNode.SelectSingleNode("mixDispensePosition/value").InnerText;//排液混合位置Id double mixDispenseDistance = Convert.ToDouble(methodNode.SelectSingleNode("mixDispenseDistance").InnerText);//排液混合时距离 double mixDispenseSpeed = Convert.ToDouble(methodNode.SelectSingleNode("mixDispenseSpeed").InnerText);//排液混合时速度 bool enableLiquidSensor = methodNode.SelectSingleNode("enableLiquidSensor").InnerText.ToLower() == "true" ? true : false; int liquidSensorCount = Convert.ToInt32(methodNode.SelectSingleNode("liquidSensorCount").InnerText); double liquidSensorDistance = Convert.ToDouble(methodNode.SelectSingleNode("liquidSensorDistance").InnerText); double liquidSensorEndDistance = Convert.ToDouble(methodNode.SelectSingleNode("liquidSensorEndDistance").InnerText); double liquidSensorSpeed = Convert.ToDouble(methodNode.SelectSingleNode("liquidSensorSpeed").InnerText); double liquidSensorRadio = Convert.ToDouble(methodNode.SelectSingleNode("liquidSensorRadio").InnerText); string liquidSensorDisIdText = methodNode.SelectSingleNode("liquidSensorDisId/text").InnerText; string liquidSensorDisIdValue = methodNode.SelectSingleNode("liquidSensorDisId/value").InnerText; bool enableLiquidFollow = methodNode.SelectSingleNode("enableLiquidFollow").InnerText.ToLower() == "true" ? true : false; int liquidFollowType = Convert.ToInt32(methodNode.SelectSingleNode("liquidFollowType/value").InnerText); string liquidFollowTypeName = methodNode.SelectSingleNode("liquidFollowType/text").InnerText; double liquidFollowSpeed = Convert.ToDouble(methodNode.SelectSingleNode("liquidFollowSpeed").InnerText); double liquidFollowDistance = Convert.ToDouble(methodNode.SelectSingleNode("liquidFollowDistance").InnerText); double liquidFollowArea = Convert.ToDouble(methodNode.SelectSingleNode("liquidFollowArea").InnerText); bool enableMixFollow = methodNode.SelectSingleNode("enableMixFollow").InnerText.ToLower() == "true" ? true : false; bool enableSensorBlock = methodNode.SelectSingleNode("enableSensorBlock").InnerText.ToLower() == "true" ? true : false;//是否开启堵塞探测 //double liquidSensorBlockDistance = Convert.ToDouble(methodNode.SelectSingleNode("liquidSensorBlockDistance").InnerText);//堵塞探测距离 //string liquidSensorBlockDisIdText = methodNode.SelectSingleNode("liquidSensorBlockDisId/text").InnerText;//未探测到堵塞时选项名称 //int liquidSensorBlockDisIdValue = Convert.ToInt32(methodNode.SelectSingleNode("liquidSensorBlockDisId/value").InnerText);//未探测到堵塞时选项Id string aspirateBlockDisIdText = methodNode.SelectSingleNode("aspirateBlockDisId/text").InnerText; string aspirateBlockDisIdValue = methodNode.SelectSingleNode("aspirateBlockDisId/value").InnerText; string dispenseBlockDisIdText = methodNode.SelectSingleNode("dispenseBlockDisId/text").InnerText; string dispenseBlockDisIdValue = methodNode.SelectSingleNode("dispenseBlockDisId/value").InnerText; string[] charray = channelNums.Split(','); #endregion try { #region 文件数据检查 // 移液文件不存在 if (methodTransferFile.transferDataTable == null) { result = false; return result; } // 检查数据中的板子名称是否在台面存在 string notExistlabwarename = ""; bool isExistPlate = transferFileBll.CheckDataExist(methodTransferFile, xmlEnv, out notExistlabwarename); if (isExistPlate == false) { if (strCurrentCulture.Equals("zh-CN")) { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strProgress.ToString() + Properties.RunTransferFileResource.strWithoutLattice.ToString() + " 板位 " + notExistlabwarename); } else { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler:【" + methodName + "】" + notExistlabwarename + " labware is not exist on lattice."); } result = false; return result; } // 排序文件并检查文件是否完整 List labwareRSLattices = transferFileBll.GetLabwareEntities(methodTransferFile, xmlEnv); DataTable dtSorted = new DataTable();//保存重新排序后的数据 dtSorted = methodTransferFile.transferDataTable.Clone(); if (Shared.ChannelCount > 1) { foreach (LabwareRSLattice l in labwareRSLattices) { #region Del 暂时不用 //bool b = transferFileBll.IsEntire6ChannelsSolidWells(methodTransferFile, l); //if (b) //{ // if (strCurrentCulture.Equals("zh-CN")) // { // launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strProgress.ToString() + Properties.RunTransferFileResource.strNotEntireData.ToString()); // LoggerRunHelper.InfoLog("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strProgress.ToString() + Properties.RunTransferFileResource.strNotEntireData.ToString()); // } // else // { // launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler:【" + methodName + "】" + Properties.MachineRunResource.strError.ToString() + " table data is not whole."); // LoggerRunHelper.InfoLog("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler:【" + methodName + "】" + Properties.MachineRunResource.strError.ToString() + " table data is not whole."); // } // result = false; // return result; //} #endregion DataTable d = transferFileBll.SortALabwareDataForChoiceSH(methodTransferFile, l); if (d != null) { for (int i = 0; i < d.Rows.Count; i++) { dtSorted.ImportRow(d.Rows[i]); } } else { if (strCurrentCulture.Equals("zh-CN")) { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strProgress.ToString() + Properties.RunTransferFileResource.strWithErrorData.ToString()); LoggerRunHelper.InfoLog("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + methodName + "】" + Properties.MachineRunResource.strProgress.ToString() + Properties.RunTransferFileResource.strWithErrorData.ToString()); } else { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler:【" + methodName + "】" + Properties.MachineRunResource.strError.ToString() + " table data is wrong."); LoggerRunHelper.InfoLog("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler:【" + methodName + "】" + Properties.MachineRunResource.strError.ToString() + " table data is wrong."); } result = false; return result; } } } else if (Shared.ChannelCount == 1) { dtSorted = methodTransferFile.transferDataTable; } #endregion if (dtSorted.Rows.Count != 0) { if (Shared.ChannelCount > 1) { int total = dtSorted.Rows.Count; // 待移液的数据总条目数 string targetWellName = dtSorted.Rows[0][methodTransferFile.destinationWell].ToString(); // 目标板孔位 int targetWellIndex0 = Convert.ToInt32(targetWellName.Substring(1, targetWellName.Length - 1)); // 列号 // 首先取剩余列的Tip总数,直接装枪做完 // 满列Tip继续安装,循环执行剩余的待做总数 // 如果是接续的目标列,且目标板孔位间距小于18mm,则判断板位上下板位是否有耗材高于25mm,如果有则改成单孔一个个做,如果没有则直接做; TransferFileSubSHControl transferFileSubSHControl = new TransferFileSubSHControl(Shared.SoftwareInformation.currentculture); transferFileSubSHControl.launchView = this.launchView; result = transferFileSubSHControl.ExecuteTransferFilegByWholeTipPriorForSH(xmlEnv, methodNode, methodTransferFile.transferDataTable, zAxisVal, isSimulator); return result; } } } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); if (strCurrentCulture.Equals("zh-CN")) { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】>Xhandler: 【" + methodNode.SelectSingleNode("name").InnerText + "】" + Properties.MachineRunResource.strError.ToString() + " 源 " + ex.Source + " 错误信息 " + ex.Message + ";"); } else { launchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】>Xhandler: 【" + methodNode.SelectSingleNode("name").InnerText + "】error:source:" + ex.Source + ";error:" + ex.Message + ";"); } result = false; } return result; } #endregion } }