using Aitex.Core.RT.Routine; using Aitex.Core.Util; using MECF.Framework.Common.Routine; using CyberX8_Core; using System; using System.Collections.Generic; using Aitex.Core.RT.Log; using MECF.Framework.Common.CommonData.Dryer; using MECF.Framework.Common.CommonData; using CyberX8_RT.Devices.Facilities; using CyberX8_RT.Devices.Dryer; using Aitex.Core.RT.Device; using Aitex.Core.RT.SCCore; using MECF.Framework.Common.RecipeCenter; namespace CyberX8_RT.Modules.Dryer { sealed class DryerCycleManualProcessRecipeRoutine : RoutineBase, IRoutine { #region 常量 private const int LOTTRACK_TIME = 1000; private const string EXHAUST_PRESSURE = "ExhaustPressure"; #endregion private enum CycleManualRunRecipeStep { LoopStart, LoopRunProcess, LoopWaitRunProcess, LoopEnd, End } #region 内部变量 private DryerRunRecipeRoutine _dryerRunRecipeRoutine; private int _cycle = 0; private int _achievedCycle; private object[] param; /// /// lock track time /// private DateTime _lotTackTime = DateTime.Now; /// /// LotTrack数据 /// private List _datas = new List(); /// /// LotTrack文件头数据 /// private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData(); /// /// Facilities /// private SystemFacilities _facilities; /// /// 设备对象 /// private DryerDevice _device; /// /// HVD Recipe /// private HvdRecipe _hvdRecipe; #endregion #region 属性 /// /// LotTrack数据 /// public List DryerLotTrackDatas { get { return _datas; } } /// /// LotTrack文件头数据 /// public LotTrackFileHeaderCommonData DryerLotTrackHeaderDatas { get { return _header; } } #endregion /// /// 构造函数 /// /// public DryerCycleManualProcessRecipeRoutine(string module) : base(module) { _dryerRunRecipeRoutine = new DryerRunRecipeRoutine(module); } /// /// Abort /// public void Abort() { _dryerRunRecipeRoutine.Abort(); Runner.Stop("Cycle ManualRunRecipe Abort"); } public RState Start(params object[] objs) { _cycle = (int)objs[1]; _achievedCycle = 0; param = objs; _hvdRecipe = objs[0] as HvdRecipe; if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID"); _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); _header.Recipe = $"{_hvdRecipe.Ppid}.hvd.rcp"; //lotTract记录SequenceRecipe DryerEntity dryerEntity = Singleton.Instance.GetModule(Module); if (dryerEntity.WaferHolderInfo != null && dryerEntity.WaferHolderInfo.SequenceRecipe != null && !String.IsNullOrEmpty(dryerEntity.WaferHolderInfo.SequenceRecipe.Ppid.ToString())) { _header.SequenceRecipe = dryerEntity.WaferHolderInfo.SequenceRecipe.Ppid.ToString(); _header.ProcessTransferList = new List(); _header.ProcessTransferList.AddRange(dryerEntity.WaferHolderInfo.SchedulerModules); dryerEntity.WaferHolderInfo.SchedulerModules.Clear(); } _facilities = DEVICE.GetDevice("System.Facilities"); if (_facilities == null) { LOG.WriteLog(eEvent.ERR_DRYER, Module, "Facility is null"); return RState.Failed; } _device = DEVICE.GetDevice(Module); if (_device == null) { LOG.WriteLog(eEvent.ERR_DRYER, Module, "Device is null"); return RState.Failed; } _lotTackTime = DateTime.Now; _datas.Clear(); return Runner.Start(Module, "Start cycle ManualRunRecipe"); } public RState Monitor() { //记录Lot track LottrackRecord(); Runner.LoopStart(CycleManualRunRecipeStep.LoopStart, "Loop Start ManualRunRecipe", _cycle, NullFun, _delay_1ms) .LoopRun(CycleManualRunRecipeStep.LoopRunProcess, () => _dryerRunRecipeRoutine.Start(param) == RState.Running, _delay_1ms) .LoopRunWithStopStatus(CycleManualRunRecipeStep.LoopWaitRunProcess, () => CheckRoutineEndStatus(_dryerRunRecipeRoutine), () => CheckRoutineStopStatus(_dryerRunRecipeRoutine,_dryerRunRecipeRoutine.ErrorMsg)) .LoopEnd(CycleManualRunRecipeStep.LoopEnd, AchievedCycleCount, _delay_1ms) .End(CycleManualRunRecipeStep.End, NullFun, _delay_1ms); return Runner.Status; } private bool CheckRoutineEndStatus(IRoutine routine) { return routine.Monitor() == RState.End; } private bool CheckRoutineStopStatus(IRoutine routine,string error) { RState state = routine.Monitor(); if (state == RState.Failed || state == RState.Timeout) { AddLotTrackData(); NotifyError(eEvent.ERR_DRYER, error, 0); return true; } return false; } /// /// 统计完成的Cycle次数 /// /// private bool AchievedCycleCount() { _achievedCycle += 1; return true; } /// /// 获取已经完成的Cycle次数 /// /// public int GetAchievedCycle() { return _achievedCycle; } /// /// 重试 /// /// public RState Retry(int step) { List preStepIds = new List(); _datas.Clear(); return Runner.Retry(CycleManualRunRecipeStep.LoopStart, preStepIds, Module, "RunRecipe Retry"); } /// /// 获取Lot Track数据 /// /// private void AddLotTrackData() { DryerLotTrackData data = new DryerLotTrackData(); data.TimeStamp = DateTime.Now; data.BlowerEnable = _device.CommonData.BlowerHigh; data.PressureSensor = _device.CommonData.ExhaustPressure; data.SystemExhaust = _facilities.GetCommonLimitDataByName(EXHAUST_PRESSURE).Value; _datas.Add(data); } /// /// 记录Lottrack /// private void LottrackRecord() { //记录Lottrack if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME) { AddLotTrackData(); _lotTackTime = DateTime.Now; } } } }