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