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.Linq;
using System.Xml;
using XCommon;
using XCommon.Log;
using XCore;
using XHandler.Controls.Run.Com;
using XHandler.View;
using XImagingXhandler.XDAL;
using static HxEnum.OtherEnum;
namespace XHandler.Controls
{
///
/// 挑选转板控制逻辑类
///
public class ChoiceTransferControl
{
#region 变量
// 系统语言
private string m_currentCulture = string.Empty;
private WellCalc wellCalc = new WellCalc();
#region 挑菌用变量
public static MethodChoiceAndTransfer ChoiceData = null;
// 当前孔在所有有效孔中的排序
private static int CurValidWellIndex = -1;
// 全部有效孔位list:A1、B1、C1
private static List LstAllValidWells = new List();
// 挑菌台面位置
private static string ChoiceLatticeName = string.Empty;
// 菌落信息
public static Bacteria BacteriaInfo = null;
private static XmlNode XmlEnv = null;
private bool IsSimulator = false;
#endregion
#region BLL
private CoatingFileBll coatingFileBll = new CoatingFileBll();
private BacteriaBll bacteriaBll = new BacteriaBll();
public static ChoiceBll choiceBll = new ChoiceBll();
#endregion
// 运行界面
public static RunWnd LaunchView = null;
public HxSocketClient SocketTcpClientToRemote = null;
#endregion
///
/// 构造函数
///
public ChoiceTransferControl()
{
m_currentCulture = Shared.SoftwareInformation.currentculture;
}
#region 执行挑选转板
///
/// 执行挑选转板
///
///
///
///
/// 0:异常结束, 1:正常继续(跳出for),2:正常结束
public int ExecuteChoiceTransfer(XmlDocument xmlDocument, XmlNode methodNode, bool isSimulator)
{
int nResult = 2;
bool bResult = false;
this.IsSimulator = isSimulator;
string strMethodName = methodNode.SelectSingleNode("name").InnerText;
#region 任务被取消
if (LaunchView._cancelSource.IsCancellationRequested)
{
nResult = 0;
return nResult;
}
#endregion
XmlEnv = xmlDocument.SelectSingleNode("root/env");
#region Log
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 数据准备1
ChoiceData = choiceBll.GenerateMethodChoiceAndTransferDataByXmlNode(methodNode);
XmlNode curChoiceLabNode = null; // 当前挑菌板位的台面信息
string curValidWell = string.Empty; // 当前挑菌的孔位:A1
List lstResidueValidWells = new List(); // 剩余有效孔位list:B1、C1
ChoiceLatticeName = string.Empty; // 挑菌台面位置
string choiceLabwareBarcode = string.Empty; // 挑菌耗材条码
int nLatticeid = -1; // 挑菌板位lattice_id
// Z轴安全位置
float zAxisSafeVal = (float)Convert.ToDouble(ConfigurationManager.AppSettings["zAxisSafeVal"]);
BacteriaInfo = bacteriaBll.GetABacteria(ChoiceData.bacteriaValue);
LoggerHelper.InfoLog($"[ChoiceTransferControl]:Args: {JsonConvert.SerializeObject(ChoiceData)}");
#endregion
#region 获取挑菌类型所有效的孔
ResidueValidWells residueValidWells = GetResidueValidWells();
if (residueValidWells == null)
{
LaunchView.AddLogs("【" + DateTime.Now.ToString("HH:mm:ss:fff") + "】> Xhandler: 【" + strMethodName + "】" + Properties.ChoiceResource.strNoValidWells.ToString());
nResult = 1;
return nResult;
}
curChoiceLabNode = residueValidWells.CurChoiceLabNode;
lstResidueValidWells = residueValidWells.LstResidueValidWells;
#endregion
#region 数据准备2
// 全部有效孔list
string allValidWells = curChoiceLabNode.SelectSingleNode("allValidWells").InnerText;
LstAllValidWells = ComUtility.GetValidWells(allValidWells);
// 当前挑菌的孔位
curValidWell = lstResidueValidWells[0];
// 当前孔在所有有效孔中的排序
CurValidWellIndex = LstAllValidWells.IndexOf(curValidWell);
// 挑菌板位:Px
ChoiceLatticeName = curChoiceLabNode.SelectSingleNode("labware_sname").InnerText;
// 挑菌耗材条码
choiceLabwareBarcode = curChoiceLabNode.SelectSingleNode("labware_barcode").InnerText;
// 挑菌板位lattice_id
nLatticeid = ControlCom.GetLatticeId(Convert.ToInt32(curChoiceLabNode.SelectSingleNode("lattice_id").InnerText));
#endregion
#region 自动开盖
// 自动开挑选板盖
bResult = OpenClover(XmlEnv, isSimulator);
if (!bResult)
{
nResult = 0;
return nResult;
}
// 查找涂布转板方法
XmlNodeList xmlNodeMethodList = xmlDocument.SelectNodes("root/method[label='涂布转板']");
if (xmlNodeMethodList.Count > 0)
{
// 自动开涂布板盖
CoatingTransferControl.LaunchView = LaunchView;
bResult = CoatingTransferControl.OpenClover(XmlEnv, xmlNodeMethodList[0], isSimulator);
if (!bResult)
{
nResult = 0;
return nResult;
}
}
#endregion
#region 超声探测
// 超声已开启
if (CurValidWellIndex == 0 && ChoiceData.isEnableultrasonic)
{
// 超声探测
int nRtn = ControlCom.DoUltrasonic(LaunchView, XmlEnv, methodNode, isSimulator, ChoiceLatticeName);
if (nRtn == 2) // 2:停止
{
nResult = 0;
return nResult;
}
}
#endregion
#region 安装涂布头
//先去安装枪头
float tipoffsetLength = float.Parse(methodNode.SelectSingleNode("choiceOffset").InnerText);
bool bLoadTipResult = ControlCom.LoadTipAutomation(XmlEnv.SelectNodes("platform"), methodNode,
isSimulator, LaunchView, SocketTcpClientToRemote, tipoffsetLength);
#endregion
#region 挑选参数
// 获取板位坐标
Lattice latticeChoice = LatticeDB.GetLatticeDataByIdFromdb(nLatticeid.ToString());
// 获取耗材信息
Labware labwares = LabwareDB.GetLabware(ChoiceData.choiceLabwareValue);
// 获取板位孔的坐标数据
List lstTipsTable = ControlCom.GenerateWellCoordinate(labwares, latticeChoice);
// 获取耗材上指定孔位的坐标
TipsTable targetWellInfo = lstTipsTable.SingleOrDefault(t => t.lattice_id.Equals(nLatticeid.ToString())
&& t.labware_id.Equals(ChoiceData.choiceLabwareValue)
&& t.wellname.Equals(curValidWell));
#endregion
#region 挑菌前吸液
if (ChoiceData.choiceAgoAspirateData.bEnableBeforeAspirate)
{
string wellName = string.Empty;
string labwareId = string.Empty;
ChoiceData.choiceAgoAspirateData.armValue = ChoiceData.armValue;
// 吸液用来源板的参数
if (ChoiceData.choiceMode == EnumManagement.GetEnumValue(ChoiceModeEnum.AspirateMode)) // 吸液
{
wellName = curValidWell;
labwareId = ChoiceData.choiceLabwareValue;
}
else
{
wellName = ChoiceData.choiceAgoAspirateData.wellarray;
labwareId = ChoiceData.choiceAgoAspirateData.labwareValue;
}
// 挑菌前吸液
Lattice latticeBeforeAspirate = null;
if (ChoiceData.choiceMode == EnumManagement.GetEnumValue(ChoiceModeEnum.AspirateMode)) // 吸液
{
ChoiceData.choiceAgoAspirateData.labwareValue = ChoiceData.choiceLabwareValue; // 吸液耗材Id
ChoiceData.choiceAgoAspirateData.positionValue = nLatticeid.ToString(); // 吸液板位Id
}
// 获取台面板位信息
latticeBeforeAspirate = LatticeDB.GetLatticeDataByIdFromdb(ChoiceData.choiceAgoAspirateData.positionValue);
// 吸液
bool bBeforeAspirate = ControlCom.DoBeforeAspirate(LaunchView, XmlEnv, strMethodName,
ChoiceData.choiceAgoAspirateData, latticeBeforeAspirate,
wellName, labwareId, choiceLabwareBarcode, isSimulator);
if (!bBeforeAspirate)
{
nResult = 0;
return nResult;
}
// 吸液用来源板的参数
if (ChoiceData.choiceMode == EnumManagement.GetEnumValue(ChoiceModeEnum.AspirateMode)) // 吸液
{
// 更新挑菌孔位
UpdateChoiceWellData(lstResidueValidWells, curChoiceLabNode);
}
}
#endregion
#region 挑选
// 吸液以外
if (ChoiceData.choiceMode != EnumManagement.GetEnumValue(ChoiceModeEnum.AspirateMode))
{
#region 执行挑选动作
ChoiceMParam choiceMParam = new ChoiceMParam();
choiceMParam.xAxisVal = (float)Convert.ToDouble(targetWellInfo.axis_b_X.ToString()) +
float.Parse(BacteriaInfo.choice_xaxis_distance.ToString());
choiceMParam.yAxisVal = (float)Convert.ToDouble(targetWellInfo.axis_b_Y.ToString()) +
float.Parse(BacteriaInfo.choice_yaxis_distance.ToString());
choiceMParam.xAxisOffsetVal = 0;
choiceMParam.yAxisOffsetVal = 0;
choiceMParam.armId = Convert.ToInt32(ChoiceData.armValue);
choiceMParam.channelId = 1;
choiceMParam.choiceMode = ChoiceData.choiceMode; // 挑菌模式:1:单选; 2:穿刺; 3:吸放液; 4:放液
choiceMParam.basezAxisVal = zAxisSafeVal;
choiceMParam.enableSupersonic = ChoiceData.isEnableultrasonic; // 挑菌时是否开启超声波探测值作为Z轴值:true:用;false:不用
choiceMParam.currentLengthOfTip = ControlCom.CurrentLengthOfTip; // 当前挑菌安装枪头后,枪增加的长度
choiceMParam.choiceTimeOnSameplace = 1; // 同一个菌落点第几次挑选;1:第一次;2:第二次...
choiceMParam.latticeName = ChoiceLatticeName; // 挑菌板位名称
if (ChoiceData.choiceMode == EnumManagement.GetEnumValue(ChoiceModeEnum.SigleSelectMode)) // 单选
{
choiceMParam.xAxisOffsetVal = 0;
choiceMParam.yAxisOffsetVal = 0;
choiceMParam.zAxisVal = (float)targetWellInfo.axis_b_Z - float.Parse(BacteriaInfo.choice_position_distance.ToString());
}
else if (ChoiceData.choiceMode == EnumManagement.GetEnumValue(ChoiceModeEnum.PricksMode)) // 穿刺
{
choiceMParam.xAxisOffsetVal = float.Parse(BacteriaInfo.choice_xaxis_distance.ToString());
choiceMParam.yAxisOffsetVal = float.Parse(BacteriaInfo.choice_yaxis_distance.ToString());
// 丝状真菌-固定高度挑菌:板位Z高度 - 底孔高度 - 枪头突出高度 - 挑菌位置距离
choiceMParam.zAxisVal = (float)latticeChoice.lattice_Z - (float)Convert.ToDouble(labwares.well_bottom_height) -
ControlCom.CurrentLengthOfTip - (float)BacteriaInfo.choice_position_distance;
}
// 执行挑菌动作
bool bIsOk = ControlCom.RunChoice(LaunchView, strMethodName, choiceMParam, targetWellInfo.wellname,
ChoiceLatticeName, choiceLabwareBarcode, isSimulator, targetWellInfo);
if (!bIsOk)
{
return 0;
}
#endregion
// 更新挑菌孔位
UpdateChoiceWellData(lstResidueValidWells, curChoiceLabNode);
}
#endregion
}
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;
#endregion
}
return nResult;
}
///
/// 获取挑菌类型所有效的孔
///
///
public static ResidueValidWells GetResidueValidWells()
{
ResidueValidWells residueValidWells = null;
List lstResidueValidWells = new List(); // 剩余有效孔位list:B1、C1
// 生成和挑菌耗材类型一致的条件
string strChoiceLabwareWhere = string.Format("platform[labware_id='{0}']", ChoiceData.choiceLabwareValue);
// 获取满足挑菌耗材类型的所有台面点位
XmlNodeList choiceLabwareNodeList = XmlEnv.SelectNodes(strChoiceLabwareWhere);
// 循环台面耗材点位,查找
foreach (XmlNode choiceLabwareNodeItem in choiceLabwareNodeList)
{
string strResidueValidWells = choiceLabwareNodeItem.SelectSingleNode("residueValidWells").InnerText;
// 有效孔字符串转换成List
lstResidueValidWells = ComUtility.GetValidWells(strResidueValidWells);
if (lstResidueValidWells.Count == 0)
{
continue;
}
residueValidWells = new ResidueValidWells();
residueValidWells.CurChoiceLabNode = choiceLabwareNodeItem;
residueValidWells.LstResidueValidWells = lstResidueValidWells;
break;
}
return residueValidWells;
}
#endregion
#region 自动开挑选板盖
///
/// 自动开挑选板盖
///
///
///
///
public static bool OpenClover(XmlNode xmlEnv, bool isSimulator)
{
bool bResult = true;
// 自动开盖: 当前孔是第一个有效孔
if (ChoiceData != null &&
ChoiceData.autoOpenCloseCover == 1 &&
CurValidWellIndex == 0)
{
// 挑菌的板放盖位号:P2,P3
List listCoatingCoverLatticeId = ComUtility.GetPlateCoverLatticeName();
// 转移板盖到放盖位方法
string strTransferPlateCoverMethodFileName = AppDomain.CurrentDomain.BaseDirectory +
"\\" + ConfigurationManager.AppSettings["transferDesPlateCoverMethod"].ToString();
// 转移目标板的盖到放盖位:PX->P2
bResult = ControlCom.DoReadMethodFileAndActionTransfer(strTransferPlateCoverMethodFileName, xmlEnv, ChoiceLatticeName, PositonTypeEnum.Desktop, GripperModelEnum.Right,
listCoatingCoverLatticeId[0], 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 (ChoiceData != null &&
ChoiceData.autoOpenCloseCover == 1 &&
((CurValidWellIndex == LstAllValidWells.Count() - 1) || isForceCloseClover))
{
// 挑菌的板放盖位号:P2,P3
List listCoatingCoverLatticeId = ComUtility.GetPlateCoverLatticeName();
// 转移板盖到放盖位方法
string strTransferPlateCoverMethodFileName = AppDomain.CurrentDomain.BaseDirectory +
"\\" + ConfigurationManager.AppSettings["transferDesPlateCoverMethod"].ToString();
// 转移目标板的盖到板上:P2->Px
bResult = ControlCom.DoReadMethodFileAndActionTransfer(strTransferPlateCoverMethodFileName, xmlEnv, listCoatingCoverLatticeId[0], PositonTypeEnum.Desktop, GripperModelEnum.Right,
ChoiceLatticeName, PositonTypeEnum.Desktop, GripperModelEnum.Right, isSimulator, LaunchView, TransferTypeEnum.Close);
}
return bResult;
}
#endregion
///
/// 更新挑菌孔位
///
///
///
private void UpdateChoiceWellData(List lstResidueValidWells, XmlNode curChoiceLabNode)
{
// 删除当前挑菌孔位
lstResidueValidWells.RemoveAt(0);
// 更新剩余有效孔位
curChoiceLabNode.SelectSingleNode("residueValidWells").InnerText = string.Join(",", lstResidueValidWells);
}
}
}