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
|
{
|
/// <summary>
|
/// 挑选转板控制逻辑类
|
/// </summary>
|
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<string> LstAllValidWells = new List<string>();
|
// 挑菌台面位置
|
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
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
public ChoiceTransferControl()
|
{
|
m_currentCulture = Shared.SoftwareInformation.currentculture;
|
}
|
|
#region 执行挑选转板
|
/// <summary>
|
/// 执行挑选转板
|
/// </summary>
|
/// <param name="xmlEnv"></param>
|
/// <param name="methodNode"></param>
|
/// <param name="isSimulator"></param>
|
/// <returns>0:异常结束, 1:正常继续(跳出for),2:正常结束</returns>
|
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<string> lstResidueValidWells = new List<string>(); // 剩余有效孔位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<TipsTable> 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;
|
}
|
|
/// <summary>
|
/// 获取挑菌类型所有效的孔
|
/// </summary>
|
/// <returns></returns>
|
public static ResidueValidWells GetResidueValidWells()
|
{
|
ResidueValidWells residueValidWells = null;
|
List<string> lstResidueValidWells = new List<string>(); // 剩余有效孔位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 自动开挑选板盖
|
/// <summary>
|
/// 自动开挑选板盖
|
/// </summary>
|
/// <param name="xmlEnv"></param>
|
/// <param name="isSimulator"></param>
|
/// <returns></returns>
|
public static bool OpenClover(XmlNode xmlEnv, bool isSimulator)
|
{
|
bool bResult = true;
|
|
// 自动开盖: 当前孔是第一个有效孔
|
if (ChoiceData != null &&
|
ChoiceData.autoOpenCloseCover == 1 &&
|
CurValidWellIndex == 0)
|
{
|
// 挑菌的板放盖位号:P2,P3
|
List<string> 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;
|
}
|
|
/// <summary>
|
/// 自动关挑选板盖
|
/// </summary>
|
/// <param name="xmlEnv"></param>
|
/// <param name="isSimulator"></param>
|
/// <param name="isForceCloseClover">是否强制关盖</param>
|
/// <returns></returns>
|
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<string> 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
|
|
/// <summary>
|
/// 更新挑菌孔位
|
/// </summary>
|
/// <param name="lstResidueValidWells"></param>
|
/// <param name="curChoiceLabNode"></param>
|
private void UpdateChoiceWellData(List<string> lstResidueValidWells, XmlNode curChoiceLabNode)
|
{
|
// 删除当前挑菌孔位
|
lstResidueValidWells.RemoveAt(0);
|
// 更新剩余有效孔位
|
curChoiceLabNode.SelectSingleNode("residueValidWells").InnerText = string.Join(",", lstResidueValidWells);
|
}
|
}
|
}
|