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
}
}