using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.Utilities;
using MECF.Framework.Common.WaferHolder;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.TransPorter;
using CyberX8_RT.Modules.Loader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aitex.Core.Common;
using MECF.Framework.Common.Alarm;
using MECF.Framework.Common.CommonData;
using System.Threading;
using MECF.Framework.Common.SubstrateTrackings;
namespace CyberX8_RT.Modules.Transporter
{
public class TransporterPickUpValidateRoutine : RoutineBase, IRoutine
{
private enum PickUpStep
{
PickUp,
PickUpWait,
ReadBarcodeConfirm,
Place,
PlaceWait,
End
}
#region 内部变量
private string _cellName;
private TransporterPickUpFromRoutine _pickupFromRoutine;
private TransporterPickDownToRoutine _placeRoutine;
private JetAxisBase _gantryAxis;
private TransporterCommon _transporterCommon;
private bool _validate = false;
#endregion
///
/// 构造函数
///
///
public TransporterPickUpValidateRoutine(string module) : base(module)
{
_pickupFromRoutine=new TransporterPickUpFromRoutine(module);
_placeRoutine=new TransporterPickDownToRoutine(module);
}
///
/// 中止
///
public void Abort()
{
Runner.Stop("Manual Abort");
}
///
/// 监控
///
///
public RState Monitor()
{
//1.1 PickupFrom
Runner .Run(PickUpStep.PickUp, () => { return _pickupFromRoutine.Start(_cellName) == RState.Running; }, _delay_1ms)
.WaitWithStopCondition(PickUpStep.PickUpWait, () => CommonFunction.CheckRoutineEndState(_pickupFromRoutine),
() => CheckRoutineStopStatus(_pickupFromRoutine, "PickUpValidate Routine", _pickupFromRoutine.ErrorMsg, 0))
//2.1 Read Barcode 确认与Material Tracking的转移是否一致
.Run(PickUpStep.ReadBarcodeConfirm, ReadBarcode, _delay_1ms)
.RunIf(PickUpStep.Place, !_validate, ()=> { return _placeRoutine.Start(_cellName) == RState.Running; },_delay_1ms )
.WaitWithStopConditionIf(PickUpStep.PlaceWait,!_validate, () => CommonFunction.CheckRoutineEndState(_placeRoutine),
() => CheckRoutineStopStatus(_placeRoutine, "Place Routine", _placeRoutine.ErrorMsg, 1))
.End(PickUpStep.End,NullFun,100);
return Runner.Status;
}
///
/// 检验Routine异常结束状态
///
///
///
private bool CheckRoutineStopStatus(IRoutine routine, string routineName, string errorMsg, int step)
{
RState ret = routine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
NotifyError(eEvent.ERR_TRANSPORTER, $"PickUp Validate WaferHolder Routine\r\n{routineName}\\r\n{errorMsg}", step);
return true;
}
return false;
}
///
/// 读取条码
///
///
private bool ReadBarcode()
{
TransporterEntity transporterEntity = Singleton.Instance.GetModule(Module.ToString());
if (transporterEntity == null)
{
return true;
}
WaferHolderInfo waferHolderInfo = transporterEntity.WaferHolderInfo;
if (waferHolderInfo == null)
{
return true;
}
bool isSimulator = SC.GetValue("System.IsSimulatorMode");
string str = CycleReadBarcode(isSimulator);
string error = "";
if(!string.IsNullOrEmpty(str))
{
if (waferHolderInfo.Id == str)
{
_validate = true;
}
else
{
error = $"Wafer Shuttle Id {waferHolderInfo?.Id} is not matched with reader {str}";
_validate = false;
}
}
else
{
if (isSimulator)
{
_validate = true;
return true;
}
error = $"reader data is empty";
}
if (!_validate)
{
if (CheckWaferHolderAllAssistWafers(waferHolderInfo))
{
WaferHolderManager.Instance.DisableWaferHolder(waferHolderInfo);
LOG.WriteLog(eEvent.WARN_TRANSPORTER, Module, error);
LOG.WriteLog(eEvent.WARN_TRANSPORTER, Module, $"disable WaferHolder {waferHolderInfo.Id}");
AlarmList alarmList = new AlarmList(Module.ToString(), "", 0, error, 0, (int)AlarmType.Warning);
AlarmListManager.Instance.AddAlarm(alarmList);
}
else
{
_validate = true;
}
}
return true;
}
///
/// 检验WaferHolder所有的Wafer是辅助片
///
///
///
private bool CheckWaferHolderAllAssistWafers(WaferHolderInfo waferHolderInfo)
{
if (!string.IsNullOrEmpty(waferHolderInfo.WaferAId))
{
WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferAId);
if (waferInfo!=null&&waferInfo.WaferType!=WaferType.Assit)
{
return false;
}
}
if (!string.IsNullOrEmpty(waferHolderInfo.WaferBId))
{
WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferBId);
if (waferInfo != null && waferInfo.WaferType != WaferType.Assit)
{
return false;
}
}
return true;
}
///
/// 循环读取Barcode
///
///
///
private string CycleReadBarcode(bool isSimulator)
{
int count = 0;
string str = "";
//读取Barcode3遍
while (count < 3)
{
str = _transporterCommon.ReaderBarcode();
str = str.Trim();
if (!string.IsNullOrEmpty(str))
{
break;
}
if (isSimulator)
{
break;
}
Thread.Sleep(10);
}
return str;
}
///
/// 启动
///
///
///
public RState Start(params object[] objs)
{
_cellName = objs[0].ToString();
_transporterCommon = DEVICE.GetDevice($"{Module}.Common");
_gantryAxis = DEVICE.GetDevice($"{Module}.Gantry");
_validate = false;
return Runner.Start(Module, $"PickUpValidate {_cellName}");
}
///
/// 重试
///
///
public RState Retry(int step)
{
if (string.IsNullOrEmpty(_cellName))
{
NotifyError(eEvent.ERR_TRANSPORTER, "source cell is empty", step);
return RState.Failed;
}
List preStepIds = new List();
if (step == 0 || step == -1)
{
return Runner.Retry(PickUpStep.PickUp, preStepIds, Module, "PickUp Validate Retry");
}
else
{
AddPreSteps(PickUpStep.Place, preStepIds);
return Runner.Retry(PickUpStep.Place, preStepIds, Module, $"Pickup Validate step {PickUpStep.Place} Retry");
}
}
///
/// 忽略前步骤
///
///
///
private void AddPreSteps(PickUpStep step, List preStepIds)
{
for (int i = 0; i < (int)step; i++)
{
preStepIds.Add((PickUpStep)i);
}
}
///
/// 检验前面Unload完成状态
///
///
public bool CheckCompleteCondition(int index)
{
TransporterEntity transporterEntity = Singleton.Instance.GetModule(Module);
if (transporterEntity.WaferHolderInfo == null)
{
NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} does not have waferholder", index);
return false;
}
double gantryPsition = _gantryAxis.MotionData.MotorPosition;
if (!_gantryAxis.CheckPositionIsInStation(gantryPsition, _cellName))
{
NotifyError(eEvent.ERR_TRANSPORTER, $"{Module} gantry not in {_cellName}", index);
return false;
}
return true;
}
}
}