using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Unit; using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.Routine; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using Aitex.Core.Utilities; using Aitex.Sorter.Common; using MECF.Framework.Common.Alarms; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using FurnaceRT.Equipments.PMs.RecipeExecutions; using FurnaceRT.Equipments.PMs.Routines; using FurnaceRT.Equipments.Systems; using Process = FurnaceRT.Equipments.PMs.RecipeExecutions.Process; using Aitex.Core.Common.DeviceData; using FurnaceRT.Devices; using FurnaceRT.Modules.PMs; using MECF.Framework.Common.Device.Bases; using Aitex.Core.RT.Log; using FurnaceRT.Equipments.Boats; using MECF.Framework.Common.Event; using System.IO; using Aitex.Common.Util; using static Aitex.Core.Common.DeviceData.AITConfigData; using MECF.Framework.Common.CommonData.SorterDefines; using MECF.Framework.Common.Utilities; using System.Windows.Documents; namespace FurnaceRT.Equipments.PMs { public partial class PMModule : PMModuleBase, IRecipeExecutor { public enum STATE { NotInstall, NotConnected, Init, Idle, Homing, OpenSlitValve, CloseSlitValve, Error, PrepareTransfer, PostTransfer, PreProcess, PostProcess, Process, LeakCheck, MFCCali, Paused, InTransfer, } public enum MSG { Home, Connected, Disconnected, Transfer, PrepareTransfer, PostTransfer, Reset, Abort, Error, EndIdleRecipe, OpenSlitValve, CloseSlitValve, SelectRecipe, RunRecipe, RunIdleRecipe, RunOtherRecipe, RecipeSkipStep, RecipeJumpStep, RecipePause, RecipeContinue, RecipeAbort, Continue, SetOnline, SetOffline, PostProcess, Process, AlarmConditionJumpStep, LeakCheck, ToInit, StartMFCCalibration, } public enum ProcessFlowState { None, Idle, Standby, Ready, Run, End, Abort, } public override bool IsInit { get { return FsmState == (int)STATE.Init; } } public bool IsBusy { get { return !IsInit && !IsError && !IsReady; } } public bool IsProcessing { get { return FsmState == (int)STATE.Process; } } public override bool IsReady { get { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed(); } } public override bool IsError { get { return _alarmNumber != 0; } } public event Action OnEnterError; private PMHomeRoutine _homeRoutine; private PMLeakCheckRoutine _leakCheckRoutine; private PreProcess _preprocessRoutine; private Process _processRoutine; private PostProcess _postprocessRoutine; private PMPrepareTransferRoutine _prepareTransferRoutine; private PMPostTransferRoutine _postTransferRoutine; private ModuleName _module; private RecipeRunningInfo _recipeRunningInfo = new RecipeRunningInfo(); private bool _isInit = true; private bool _isPrepareProcess = true; private bool _isStandbyStep; private StatsData _statTubeCleanNumber; private StatsData _statTubeCleanTime; private StatsData _statTubeCleanThick; private StatsData _statBoatCleanNumber; private StatsData _statBoatCleanTime; private StatsData _statBoatCleanThick; private StatsData _statForkCleanNumber; private StatsData _statForkCleanTime; private StatsData _statForkCleanThick; private Stopwatch _processTimer = new Stopwatch(); public List ValveLists = new List(); public List FlowmeterLists = new List(); private bool _isExternalSensorConditionBypass; private bool _isTempStabilizeConditionBypass; private bool _isPressureStabilizeConditionBypass; private bool _isReachTempConditionBypass; private bool _isReachPressureConditionBypass; private bool _isFinishAutoProfileConditionBypass; private SerializableDictionary _conditionCheckDic = new SerializableDictionary(); private Dictionary _conditionCheckItemDic = new Dictionary(); private Stopwatch _waitTimer = new Stopwatch(); public string StringProcessFlowState { get; set; } = ProcessFlowState.Standby.ToString(); public bool IsExcuteRoutineFailed { get; set; } public bool IsJobProcess { get; private set; } public string EditRecipeName { get; set; } = string.Empty; public string EditRecipeStepName { get; set; } = string.Empty; public bool IsExcuteIdleRecipe { get; set; } public string ToolType { get; set; } public PMModule(ModuleName module) : base(SC.GetValue($"Boat.SlotCount")) { _module = module; Module = module.ToString(); Name = module.ToString(); EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(1, STATE.Idle); } public override bool Initialize() { IsOnline = true; InitRoutine(); InitDevice(); InitAUX(); InitInterlock(); InitFsm(); InitOp(); InitData(); InitLeakCheckData(); InitStats(); InitAlarmEvent(); InitScheduleMaintenance(); InitAlarmConditionChecker(); Singleton.Instance.OnAlarmEvent += Instance_OnAlarmEvent; ToolType = SC.GetStringValue("System.SetUp.ToolType"); return base.Initialize(); } private void Instance_OnAlarmEvent(EventItem item) { if (item != null && item.Level == EventLevel.Alarm && (item.Source == Name || item.Source == Module)) { var alarm = item as AlarmEventItem; DEVICE.GetDevice("System.SignalTower")?.Reset(); LOG.Write($"{item.Source} {item.EventEnum} {item.Description}\n"); //PostMsg(MSG.Error); } } private void InitRoutine() { _homeRoutine = new PMHomeRoutine(ModuleHelper.Converter(Module), this); _leakCheckRoutine = new PMLeakCheckRoutine(ModuleHelper.Converter(Module), this); _preprocessRoutine = new PreProcess(ModuleHelper.Converter(Module), this); _processRoutine = new Process(ModuleHelper.Converter(Module), this); _postprocessRoutine = new PostProcess(ModuleHelper.Converter(Module), this); _prepareTransferRoutine = new PMPrepareTransferRoutine(Module, this); _postTransferRoutine = new PMPostTransferRoutine(Module, this); } private void InitData() { DATA.Subscribe($"{Module}.IsError", () => IsError); DATA.Subscribe($"{Module}.Status", () => StringFsmStatus); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline); DATA.Subscribe($"{Module}.IsProcessing", () => IsProcessing); DATA.Subscribe($"{Module}.RunningMode", () => SC.ContainsItem("System.RunningMode") ? SC.GetStringValue("System.RunningMode") == ConfigEnum.Debug.ToString() : false); DATA.Subscribe($"{Module}.EnableMinics", () => SC.ContainsItem("Minics.EnableMinics") ? SC.GetValue("Minics.EnableMinics") : false); //DATA.Subscribe($"{Module}.WaferSize", () => WaferManager.Instance.GetWaferSize(_module, 0).ToString()); DATA.Subscribe($"{Module}.IsInMaintainMode", () => !IsOnline); //DATA.Subscribe($"{Name}.LeakCheckElapseTime", () => //{ // if (FsmState == (int)STATE.LeakCheck) // return _leakCheckRoutine.ElapsedTime; // return 0; //}); DATA.Subscribe($"{Name}.ChamberPressure", () => ChamberPressure); //DATA.Subscribe($"{Name}.VAC1", () => _vac1); //DATA.Subscribe($"{Name}.VAC2", () => _vac2); //DATA.Subscribe($"{Name}.VAC3", () => _vac3); DATA.Subscribe($"{Name}.MainRecipeName", () => _recipeRunningInfo.MainRecipeName); DATA.Subscribe($"{Name}.SelectedRecipeName", () => _recipeRunningInfo.RecipeName); DATA.Subscribe($"{Name}.ProcessSubRecipe", () => _recipeRunningInfo.SubRecipeName); DATA.Subscribe($"{Name}.ProcessAbortRecipe", () => _recipeRunningInfo.AbortRecipeName); DATA.Subscribe($"{Name}.AbortRecipeName", () => _recipeRunningInfo.RecipeName); DATA.Subscribe($"{Name}.SubRecipeCurrentLoopCount", () => _recipeRunningInfo.SubRecipeCurrentLoopCount); DATA.Subscribe($"{Name}.SubRecipeLoopCount", () => _recipeRunningInfo.SubRecipeLoopCount); DATA.Subscribe($"{Name}.IsExecuteSubRecipe", () => _processRoutine.IsSubReciep); DATA.Subscribe($"{Name}.RecipeBeginTime", () => _recipeRunningInfo.BeginTime); DATA.Subscribe($"{Name}.RecipeStepNumber", () => _recipeRunningInfo.StepNumber); DATA.Subscribe($"{Name}.RecipeNextStepName", () => _recipeRunningInfo.NextStepName); DATA.Subscribe($"{Name}.RecipeStepName", () => _recipeRunningInfo.StepName); DATA.Subscribe($"{Name}.RecipeStepElapseTime", () => _recipeRunningInfo.StepElapseTime); DATA.Subscribe($"{Name}.RecipeStepTime", () => _recipeRunningInfo.StepTime); DATA.Subscribe($"{Name}.RecipeTotalElapseTime", () => _recipeRunningInfo.TotalElapseTime); DATA.Subscribe($"{Name}.RecipeTotalTime", () => _recipeRunningInfo.TotalTime); DATA.Subscribe($"{Name}.RecipeHoldTime", () => _recipeRunningInfo.HoldTime); DATA.Subscribe($"{Name}.RecipeHold", () => IsPaused);//按了hold按键 DATA.Subscribe($"{Name}.RecipeHolded", () => IsHolded);//按了hold按键之后,当前step执行完了 DATA.Subscribe($"{Name}.RecipeWait", () => IsWait);//等待wait条件的结束 DATA.Subscribe($"{Name}.NewShowTime", () => GetNewShowTime()); DATA.Subscribe($"{Name}.ExecRecipeType", () => _recipeRunningInfo.ExecRecipeType); DATA.Subscribe($"{Name}.LoopCountSet", () => _recipeRunningInfo.LoopCountSet); DATA.Subscribe($"{Name}.LoopCountCurrent", () => _recipeRunningInfo.LoopCountCurrent); DATA.Subscribe($"{Name}.IsLooping", () => _recipeRunningInfo.IsLooping); DATA.Subscribe("ProcessFlow.Status", () => StringProcessFlowState); DATA.Subscribe($"{Name}.ConditionCheck", () => _conditionCheckDic); //DATA.Subscribe($"{Name}.LZoneHeaterData", () => Heater2.DeviceData.IsLspModeFeedBack ? Heater2.DeviceData : Heater1.DeviceData); //DATA.Subscribe($"{Name}.CLZoneHeaterData", () => Heater4.DeviceData.IsLspModeFeedBack ? Heater4.DeviceData : Heater3.DeviceData); //DATA.Subscribe($"{Name}.CZoneHeaterData", () => Heater6.DeviceData.IsLspModeFeedBack ? Heater6.DeviceData : Heater5.DeviceData); //DATA.Subscribe($"{Name}.CUZoneHeaterData", () => Heater8.DeviceData.IsLspModeFeedBack ? Heater8.DeviceData : Heater7.DeviceData); //DATA.Subscribe($"{Name}.UZoneHeaterData", () => Heater10.DeviceData.IsLspModeFeedBack ? Heater10.DeviceData : Heater9.DeviceData); SensorRecipeOK = new AITSensorData() { DeviceName = "SensorRecipeOK", DeviceSchematicId = "SensorRecipe", DisplayName = "SensorRecipe", Value = false, }; DATA.Subscribe($"{Module}.{SensorRecipeOK.DeviceName}", () => SensorRecipeOK); SensorPROCManualOK = new AITSensorData() { DeviceName = "SensorPROCManualOK", DeviceSchematicId = "PROCManual", DisplayName = "PROCManual", Value = false, }; DATA.Subscribe($"{Module}.{SensorPROCManualOK.DeviceName}", () => SensorPROCManualOK); DATA.Subscribe($"{Module}.EditRecipeName", () => EditRecipeName); DATA.Subscribe($"{Module}.EditRecipeStepName", () => EditRecipeStepName); DATA.Subscribe($"{Module}.HTR1Enable", () => IsHTR1Enable); DATA.Subscribe($"{Module}.HTR2Enable", () => IsHTR2Enable); DATA.Subscribe($"{Module}.HTR3Enable", () => IsHTR3Enable); DATA.Subscribe($"{Module}.IsCEXHOn", () => _isCEXHOn); DATA.Subscribe($"{Module}.IsF2ClnOn", () => { return IsF2ClnOn; }); DATA.Subscribe($"{Module}.IsHFClnOn", () => { return IsHFClnOn; }); DATA.Subscribe($"{Module}.IsDEPOOn", () => TrigDEPOSW != null ? TrigDEPOSW.Value : false); DATA.Subscribe($"{Module}.IsCREFOn", () => TrigCREFON != null ? TrigCREFON.Value : false); DATA.Subscribe($"{Module}.IsSIREFOn", () => TrigSIREFON != null ? TrigSIREFON.Value : false); DATA.Subscribe($"{Module}.MFCList", () => { List aITMfcDataList = new List(); var mfcs = DEVICE.GetDevice(); if (mfcs != null) { foreach (var item in mfcs) { if (item == null) continue; if (item.IsMFCInstalled) { aITMfcDataList.Add(item.DeviceData); } } } return aITMfcDataList; }); InitOtherData(); InitN2PurgeData(); } private void InitStats() { _statTubeCleanNumber = new StatsData($"{Module}.Tube Clean Number", "Tube clean number", 0); _statTubeCleanTime = new StatsData($"{Module}.Tube Clean Time", "Tube clean time(Min)", 0); _statTubeCleanThick = new StatsData($"{Module}.Tube Clean thick", "Tube clean thick(nm)", 0); _statBoatCleanNumber = new StatsData($"{Module}.Boat Clean Number", "Boat clean number", 0); _statBoatCleanTime = new StatsData($"{Module}.Boat Clean Time", "Boat clean time(Min)", 0); _statBoatCleanThick = new StatsData($"{Module}.Boat Clean thick", "Boat clean thick(nm)", 0); _statForkCleanNumber = new StatsData($"{Module}.Fork Clean Number", "Fork clean number", 0); _statForkCleanTime = new StatsData($"{Module}.Fork Clean Time", "Fork clean time(Min)", 0); _statBoatCleanThick = new StatsData($"{Module}.Boat Clean thick", "Boat clean thick(nm)", 0); _statForkCleanThick = new StatsData($"{Module}.Fork Clean thick", "Fork clean thick", 0); } private void InitOp() { OP.Subscribe($"{Module}.Home", (string cmd, object[] args) => { if (!(Singleton.Instance.Modules[ModuleName.WaferRobot] as IModuleDevice).IsReady) { TubeHomeFailedWarning.Set($"Wafer Robot is not in ilde state, init failed."); return false; } return CheckToPostMessage((int)MSG.Home); }); OP.Subscribe($"{Module}.Reset", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Reset)); OP.Subscribe($"{Module}.Abort", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Abort)); OP.Subscribe($"{Module}.PutOnline", (string cmd, object[] args) => CheckToPostMessage((int)MSG.SetOnline)); OP.Subscribe($"{Module}.PutOffline", (string cmd, object[] args) => CheckToPostMessage((int)MSG.SetOffline)); OP.Subscribe($"{Name}.SelectRecipe", (string cmd, object[] args) => CheckToPostMessage((int)MSG.SelectRecipe, args[0])); OP.Subscribe($"{Name}.RunRecipe", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RunRecipe, (string)args[0])); OP.Subscribe($"{Name}.RecipeSkipStep", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RecipeSkipStep)); OP.Subscribe($"{Name}.RecipeJumpStep", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RecipeJumpStep, args[0], args[1])); OP.Subscribe($"{Name}.RecipePause", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RecipePause)); OP.Subscribe($"{Name}.RecipeContinue", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RecipeContinue)); OP.Subscribe($"{Name}.RecipeAbort", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RecipeAbort)); OP.Subscribe($"{Name}.RecipeIdle", (string cmd, object[] args) => CheckToPostMessage((int)MSG.RunIdleRecipe)); OP.Subscribe($"{Name}.LeakCheck", (string cmd, object[] args) => CheckToPostMessage((int)MSG.LeakCheck, args[0], args[1], args[2], args[3])); OP.Subscribe($"{Name}.Wait", (string cmd, object[] args) => { IsWait = !IsWait; return true; }); OP.Subscribe($"{Module}.AlarmAction", (string cmd, object[] args) => { Enum.TryParse(args[0].ToString(), out AlarmAction alarmAction); string eventName = null; if (args.Length > 1) eventName = args[1].ToString(); if (eventName != null) { EV.ClearAlarmEvent(eventName); var item = _triggeredAlarmList.FirstOrDefault(x => x.EventEnum == eventName); if (item != null) { item.Reset(); _triggeredAlarmList.Remove(item); } if (item != null) { switch (alarmAction) { case AlarmAction.Retry: { CheckToPostMessage((int)item.RetryMessage, item.RetryMessageParas); } break; case AlarmAction.Abort: { CheckToPostMessage((int)MSG.Abort); } break; case AlarmAction.Clear: { int alarmCount = 0; var alarms = EV.GetAlarmEvent(); foreach (var alarm in alarms) { if (alarm.Level == EventLevel.Alarm && alarm.Source == Name) alarmCount++; } if (alarmCount == 0 && !IsProcessing) { CheckToPostMessage((int)MSG.Reset); _alarmNumber = 0; } } break; case AlarmAction.Continue: { int alarmCount = 0; var alarms = EV.GetAlarmEvent(); foreach (var alarm in alarms) { if (alarm.Level == EventLevel.Alarm && alarm.Source == Name) alarmCount++; } if (alarmCount == 0) CheckToPostMessage((int)MSG.Reset); } break; case AlarmAction.ClearAll: ResetAUXTrig(); break; } } } return true; }); OP.Subscribe($"{Name}.SetConditionCheck", SetConditionCheck); OP.Subscribe($"{Name}.SetBoatZAxisMotion", SetBoatZAxisMotion); OP.Subscribe($"{Name}.SetBoatRAxisMotion", SetBoatRAxisMotion); OP.Subscribe($"{Name}.SetAutoShutterUp", SetAutoShutterUp); OP.Subscribe($"{Name}.SetAutoShutterOpen", SetAutoShutterOpen); OP.Subscribe($"{Name}.SetAutoShutterRotateOpen", SetAutoShutterRotateOpen); OP.Subscribe($"{Name}.BypassStandbyFactor", SeBypassStandbyFactor); OP.Subscribe($"{Name}.SetCommand", SetCommand); OP.Subscribe($"{Name}.SetN2PurgeMode", SetN2PurgeMode); //OP.Subscribe($"{Name}.SetTemperatureDetail",) OP.Subscribe($"{Name}.SetSensorRecipeOK", SetSensorRecipeOK); OP.Subscribe($"{Name}.SetSensorPROCManualOK", SetSensorPROCManualOK); OP.Subscribe($"{Name}.SetEditRecipeName", SetEditRecipeName); OP.Subscribe($"{Name}.SetEditRecipeStepName", SetEditRecipeStepName); OP.Subscribe($"{Name}.Heater.SetParameters", (out string reason, int time, object[] param) => { reason = string.Empty; //Mode参数;Correct Table;PID Table //"Heater;Parameter\\TempCorrection\\tempCorrect,2,Name2;Parameter\\TempPID\\tempPID,3,Name3" SetHeaterControlParameters(param); return true; }); OP.Subscribe($"{Name}.Heater.SetPID", (out string reason, int time, object[] param) => { reason = string.Empty; SetHeaterPIDParameters(param[0].ToString()); return true; }); OP.Subscribe($"{Name}.Heater.SetCorrect", (out string reason, int time, object[] param) => { reason = string.Empty; SetHeaterCorrectParameters(param[0].ToString()); return true; }); //Recipe OP.Subscribe($"{Name}.SetBoatMotion", (out string reason, int time, object[] param) => { reason = string.Empty; SetBoatMotion(param); return true; }); //Recipe OP.Subscribe($"{Name}.SetValves", (out string reason, int time, object[] param) => { reason = string.Empty; SetValves(param); return true; }); //Recipe OP.Subscribe($"{Name}.SetAlarmConditionTable", (out string reason, int time, object[] param) => { reason = string.Empty; SetAlarmConditionTable(param); return true; }); //manual OP.Subscribe($"{Name}.SetAlarmConditionParameter", (out string reason, int time, object[] param) => { reason = string.Empty; InitAlarmCondition(param[0].ToString()); SetAlarmConditionTable(new object[1] { param[1] }); return true; }); OP.Subscribe($"{Name}.SetBoatManualMotion", (out string reason, int time, object[] param) => { reason = string.Empty; SetBoatManualMotion(param); return true; }); OP.Subscribe($"{Name}.SetCEXHEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetCEXHEnable(param); return true; }); OP.Subscribe($"{Name}.SetF2ClnEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetF2ClnEnable(param); return true; }); OP.Subscribe($"{Name}.SetHFClnEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetHFClnEnable(param); return true; }); OP.Subscribe($"{Name}.SetDEPOEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetDEPOEnable(param); return true; }); OP.Subscribe($"{Name}.SetHTR1Enable", (out string reason, int time, object[] param) => { reason = string.Empty; SetHTR1Enable(param); return true; }); OP.Subscribe($"{Name}.SetHTR2Enable", (out string reason, int time, object[] param) => { reason = string.Empty; SetHTR2Enable(param); return true; }); OP.Subscribe($"{Name}.SetHTR3Enable", (out string reason, int time, object[] param) => { reason = string.Empty; SetHTR3Enable(param); return true; }); OP.Subscribe($"{Name}.AUX.SetParameters", (out string reason, int time, object[] param) => { reason = string.Empty; //Mode参数;Correct Table;PID Table //"Heater;Parameter\\TempCorrection\\tempCorrect,2,Name2;Parameter\\TempPID\\tempPID,3,Name3" SetAUXParameters(param); return true; }); OP.Subscribe($"{Module}.SetAllMfcVirtualValue", (out string reason, int time, object[] param) => { reason = string.Empty; var dict = param[0] as Dictionary; foreach (var item in dict) { var mfc = _processMFCs.FirstOrDefault(x => x.Name == item.Key); if (mfc != null) { mfc.SetMfcVirtualValue(out reason, 0, new object[] { item.Value }); } } return true; }); OP.Subscribe($"{Module}.SetAllMfcValue", (out string reason, int time, object[] param) => { reason = string.Empty; var dict = param[0] as Dictionary; foreach (var item in dict) { var mfc = _processMFCs.FirstOrDefault(x => x.Name == item.Key); if (mfc != null) { mfc.SetMfcValue(out reason, 0, new object[] { item.Value }); } } return true; }); OP.Subscribe($"{Module}.SetAllMfcSetPoint", (out string reason, int time, object[] param) => { reason = string.Empty; var dict = param[0] as Dictionary; foreach (var item in dict) { var mfc = _processMFCs.FirstOrDefault(x => x.Name == item.Key); if (mfc != null) { mfc.SetMfcSetPoint(out reason, 0, new object[] { item.Value }); } } return true; }); OP.Subscribe($"{Module}.SetAll{AITValveOperation.GVVirtualTurnValve}", (out string reason, int time, object[] param) => { reason = string.Empty; var dict = param[0] as Dictionary; foreach (var item in dict) { var valve = _valves.FirstOrDefault(x => x.Name == item.Key); if (valve != null) { valve.InvokeOpenCloseVirtualValve("", new object[] { item.Value }); } } return true; }); OP.Subscribe($"{Module}.SetAll{AITValveOperation.GVTurnValve}", (out string reason, int time, object[] param) => { reason = string.Empty; var dict = param[0] as Dictionary; foreach (var item in dict) { _valves.FirstOrDefault(x => x.Name == item.Key).InvokeOpenCloseValve("", new object[] { item.Value }); } return true; }); OP.Subscribe($"{Name}.SetCREFEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetCREFEnable(param); return true; }); OP.Subscribe($"{Name}.SetSIREFEnable", (out string reason, int time, object[] param) => { reason = string.Empty; SetSIREFEnable(param); return true; }); InitOtherOP(); } public void SetTemperatureDetail() { } private void InitFsm() { //Error Transition(STATE.Error, MSG.Reset, FsmReset, STATE.Idle); AnyStateTransition(MSG.Error, FsmOnError, STATE.Error); AnyStateTransition(MSG.Disconnected, FsmOnDisconnect, STATE.NotConnected); EnterExitTransition(STATE.Error, FsmEnterError, FSM_MSG.NONE, FsmExitError); Transition(STATE.Idle, MSG.Abort, null, STATE.Idle); Transition(STATE.Idle, MSG.Reset, null, STATE.Idle); Transition(STATE.Init, MSG.Reset, null, STATE.Idle); Transition(STATE.Error, MSG.Abort, null, STATE.Error); //init Transition(STATE.Init, MSG.Home, FsmStartHome, STATE.Homing); AnyStateTransition(MSG.ToInit, FsmToInit, STATE.Init); //not connected Transition(STATE.NotConnected, MSG.Connected, null, STATE.Init); //Home EnterExitTransition((int)STATE.Homing, FsmEnterHome, (int)FSM_MSG.NONE, FsmExitHome); Transition(STATE.Error, MSG.Home, FsmStartHome, STATE.Homing); Transition(STATE.Idle, MSG.Home, FsmStartHome, STATE.Homing); Transition(STATE.Homing, FSM_MSG.TIMER, FsmMonitorHomeTask, STATE.Idle); Transition(STATE.Homing, MSG.Error, null, STATE.Init); Transition(STATE.Homing, MSG.Abort, FsmAbortTask, STATE.Init); //PrepareTransfer Transition(STATE.Idle, MSG.PrepareTransfer, FsmStartPrepareTransfer, STATE.PrepareTransfer); Transition(STATE.PrepareTransfer, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.PrepareTransfer, MSG.Abort, FsmAbortTask, STATE.Idle); //PostTransfer Transition(STATE.InTransfer, MSG.PostTransfer, FsmStartPostTransfer, STATE.PostTransfer); Transition(STATE.Idle, MSG.PostTransfer, FsmStartPostTransfer, STATE.PostTransfer); Transition(STATE.PostTransfer, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.PostTransfer, MSG.Abort, FsmAbortTask, STATE.Idle); //online Transition(STATE.Idle, MSG.SetOnline, FsmStartSetOnline, STATE.Idle); Transition(STATE.Idle, MSG.SetOffline, FsmStartSetOffline, STATE.Idle); //Leak check Transition(STATE.Idle, MSG.LeakCheck, FsmStartLeakCheck, STATE.LeakCheck); Transition(STATE.LeakCheck, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.LeakCheck, MSG.Abort, FsmAbortTask, STATE.Idle); EnterExitTransition(STATE.LeakCheck, FsmEnterLeakCheck, FSM_MSG.NONE, FsmExitLeakCheck); //open SlitValve Transition(STATE.Idle, MSG.OpenSlitValve, FsmStartOpenSlitValve, STATE.OpenSlitValve); Transition(STATE.OpenSlitValve, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.OpenSlitValve, MSG.Abort, FsmAbortTask, STATE.Idle); //close SlitValve Transition(STATE.Idle, MSG.CloseSlitValve, FsmStartCloseSlitValve, STATE.CloseSlitValve); Transition(STATE.CloseSlitValve, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.CloseSlitValve, MSG.Abort, FsmAbortTask, STATE.Idle); //PreProcess Transition(STATE.Process, MSG.RunIdleRecipe, FsmStartIdleRecipePreProcess, STATE.PreProcess); Transition(STATE.Process, MSG.RunOtherRecipe, FsmStartOtherRecipePreProcess, STATE.PreProcess); Transition(STATE.Idle, MSG.RunOtherRecipe, FsmStartOtherRecipePreProcess, STATE.PreProcess); Transition(STATE.Idle, MSG.SelectRecipe, FsmSelectRecipe, STATE.Idle); Transition(STATE.Idle, MSG.RunRecipe, FsmStartPreProcess, STATE.PreProcess); Transition(STATE.PreProcess, FSM_MSG.TIMER, FsmMonitorTask, STATE.PreProcess); Transition(STATE.PreProcess, MSG.Abort, FsmAbortTask, STATE.Idle); Transition(STATE.PreProcess, MSG.RecipeAbort, FsmAbortTask, STATE.Idle); //Process Transition(STATE.PreProcess, MSG.Process, FsmStartProcess, STATE.Process); Transition(STATE.Idle, MSG.AlarmConditionJumpStep, FsmStartAlarmConditionJumpStep, STATE.Process); Transition(STATE.Process, FSM_MSG.TIMER, FsmMonitorTask, STATE.Process); Transition(STATE.Process, MSG.Abort, FsmAbortTask, STATE.Idle); Transition(STATE.Process, MSG.EndIdleRecipe, null, STATE.Idle); EnterExitTransition(STATE.Process, FsmEnterProcess, FSM_MSG.NONE, FsmExitProcess); Transition(STATE.Paused, FSM_MSG.TIMER, FsmMonitorTask, STATE.Paused); Transition(STATE.Paused, MSG.Continue, FsmStartContinue, STATE.Process); Transition(STATE.Paused, MSG.Error, null, STATE.Paused); Transition(STATE.Paused, MSG.Abort, FsmAbortTask, STATE.Idle); //Transition(STATE.Paused, MSG.Error, null, STATE.Paused); Transition(STATE.Process, MSG.RecipeSkipStep, FsmSkipStep, STATE.Process); Transition(STATE.Process, MSG.RecipeJumpStep, FsmJumpStep, STATE.Process); Transition(STATE.Process, MSG.RecipePause, FsmRecipePause, STATE.Process); Transition(STATE.Process, MSG.RecipeContinue, FsmRecipeContinue, STATE.Process); Transition(STATE.Process, MSG.RecipeAbort, FsmRecipeAbort, STATE.Process); //PostProcess Transition(STATE.Process, MSG.PostProcess, FsmStartPostProcess, STATE.PostProcess); Transition(STATE.PostProcess, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.PostProcess, MSG.Abort, FsmAbortTask, STATE.Idle); EnterExitTransition(STATE.PostProcess, null, FSM_MSG.NONE, ExitPostProcess); //MFC Calibration Transition(STATE.Idle, MSG.StartMFCCalibration, FsmStartMFCCalibration, STATE.MFCCali); Transition(STATE.MFCCali, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.MFCCali, MSG.Abort, FsmAbortTask, STATE.Idle); } private bool FsmToInit(object[] param) { return true; } private bool FsmExitError(object[] param) { return true; } private bool FsmEnterError(object[] param) { if (OnEnterError != null) OnEnterError(Module); if (IsOnline) { //EV.PostWarningLog(Module, $"{Module}"); } return true; } private bool FsmStartPostTransfer(object[] param) { _postTransferRoutine.Init((EnumTransferType)Enum.Parse(typeof(EnumTransferType), (string)param[0])); Result ret = StartRoutine(_postTransferRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartPrepareTransfer(object[] param) { _prepareTransferRoutine.Init((EnumTransferType)Enum.Parse(typeof(EnumTransferType), (string)param[0])); Result ret = StartRoutine(_prepareTransferRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartSetOffline(object[] param) { IsOnline = false; return true; } private bool FsmStartSetOnline(object[] param) { IsOnline = true; return true; } private bool FsmStartLeakCheck(object[] param) { _leakCheckRoutine.Init((int)param[0], (int)param[1], (string)param[2], (bool[])param[3]); Result ret = StartRoutine(_leakCheckRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmEnterLeakCheck(object[] param) { return true; } private bool FsmExitLeakCheck(object[] param) { //ChamberProcessPressureGauge.UnsetTuning(); return true; } private bool FsmStartOpenSlitValve(object[] param) { return true; } private bool FsmStartCloseSlitValve(object[] param) { return true; } private bool FsmSelectRecipe(object[] param) { return true; } private bool FsmStartPreProcess(object[] param) { _recipeRunningInfo.RecipeName = (string)param[0]; if (!RecipeParser.Parse(_recipeRunningInfo.RecipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out string reason, "Process")) { PreprocessStartFailedWarning.Set($"Load process recipe {_recipeRunningInfo.RecipeName} failed, {reason}"); return false; } if (recipeSteps == null || recipeSteps.Count == 0) { PreprocessStartFailedWarning.Set($"Process recipe {_recipeRunningInfo.RecipeName} is empty"); return false; } string abortRecipeName = SC.ContainsItem("System.Recipe.Abort Recipe") ? SC.GetStringValue("System.Recipe.Abort Recipe") : string.Empty; if (string.IsNullOrEmpty(abortRecipeName)) { PreprocessStartFailedWarning.Set($"Load abort recipe failed, recipe file is null"); return false; } SC.SetItemValueFromString("PM1.ProcessRecipe", _recipeRunningInfo.RecipeName); if (!IsJobProcess) Singleton.Instance.CreatePj((string)param[0]); _preprocessRoutine.Init((string)param[0]); Result ret = StartRoutine(_preprocessRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; #region MyRegion if (CheckRecipeThicknessMoreThan(_recipeRunningInfo.RecipeName)) return false; if (CheckRecipeExecuteFreqMoreThan(_recipeRunningInfo.RecipeName)) return false; #endregion if (!IsJobProcess) SensorPROCManualOK.Value = true; return ret == Result.RUN; } private bool FsmStartOtherRecipePreProcess(object[] param) { _recipeRunningInfo.RecipeName = param[0].ToString(); var recipeType = param[1].ToString(); var tableID = 1; if (param.Length > 2) int.TryParse(param[2].ToString(), out tableID); if (!RecipeParser.Parse(_recipeRunningInfo.RecipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out string reason, recipeType, tableID)) { PreprocessStartFailedWarning.Set($"Load {recipeType} recipe {_recipeRunningInfo.RecipeName} failed {reason}"); return false; } if (recipeSteps == null || recipeSteps.Count == 0) { PreprocessStartFailedWarning.Set($"{recipeType} recipe {_recipeRunningInfo.RecipeName} is empty"); return false; } if (!IsJobProcess) Singleton.Instance.CreatePj(_recipeRunningInfo.RecipeName); _preprocessRoutine.Init(_recipeRunningInfo.RecipeName, false); RecipeRunningInfo.MainRecipeName = _recipeRunningInfo.RecipeName; RecipeRunningInfo.Head = recipeHead; RecipeRunningInfo.RecipeStepList = recipeSteps; Result ret = StartRoutine(_preprocessRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; if (!IsJobProcess) SensorPROCManualOK.Value = true; return ret == Result.RUN; } private bool FsmStartIdleRecipePreProcess(object[] param) { if (!CheckBoatState()) { PreprocessStartFailedWarning.Set($"boat is not ready"); return false; } _recipeRunningInfo.RecipeName = SC.ContainsItem("System.Recipe.Idle Recipe") ? SC.GetStringValue("System.Recipe.Idle Recipe") : string.Empty; if (!RecipeParser.Parse(_recipeRunningInfo.RecipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out string reason, "Idle")) { PreprocessStartFailedWarning.Set($"Load idle recipe {_recipeRunningInfo.RecipeName} failed {reason}"); return false; } if (recipeSteps == null || recipeSteps.Count == 0) { PreprocessStartFailedWarning.Set($"Process recipe {_recipeRunningInfo.RecipeName} is empty"); return false; } if (!IsJobProcess) Singleton.Instance.CreatePj(_recipeRunningInfo.RecipeName); _preprocessRoutine.Init(_recipeRunningInfo.RecipeName, false); RecipeRunningInfo.MainRecipeName = _recipeRunningInfo.RecipeName; RecipeRunningInfo.Head = recipeHead; RecipeRunningInfo.RecipeStepList = recipeSteps; Result ret = StartRoutine(_preprocessRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; if (!IsJobProcess) SensorPROCManualOK.Value = true; return ret == Result.RUN; } private bool FsmStartProcess(object[] param) { Result ret = StartRoutine(_processRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; if (ret == Result.RUN && !IsJobProcess) Singleton.Instance.StartPj(); return ret == Result.RUN; } private bool FsmStartAlarmConditionJumpStep(object[] param) { if (param != null && param.Length > 0) { int.TryParse(param[0].ToString(), out int jumpStep); _processRoutine.AlarmConditionJumpStep = jumpStep; Result ret = StartRoutine(_processRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } return false; } private bool FsmEnterProcess(object[] param) { for (int i = 0; i < SC.GetValue($"Boat.SlotCount"); i++) { if (!WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Module), i)) continue; WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), i, EnumWaferProcessStatus.InProcess); } _processTimer.Restart(); return true; } private bool FsmExitProcess(object[] param) { _processRoutine.ExitProcess(); if (!IsJobProcess && !_processRoutine.IsExecuteAbort)//非jobprocess需要recipe结束也需要更新数据库 { var firstPjId = Singleton.Instance.GetFirstPJId(); Singleton.Instance.EndPj(); _processRoutine.UpdateProcessDataPJid(firstPjId); } //_statWaferCount.Increase(); //_statProcessTime.Increase((int)(_processTimer.ElapsedMilliseconds/1000)); _isPrepareProcess = true; IsJobProcess = false; SensorPROCManualOK.Value = false; //if (SC.GetStringValue($"System.Recipe.ExcuteAfterRecipeComplete") == "StandbyStep") //{ // StringProcessFlowState = ProcessFlowState.Standby.ToString(); // _recipeRunningInfo.StepName = "Standby"; // var standbyStep = _recipeRunningInfo.RecipeStepList.Where(x => x.StepName == "Standby").FirstOrDefault(); // if (standbyStep != null) // { // EV.PostInfoLog(Module, $"Recipe {_recipeRunningInfo.RecipeName} complete excute standby step"); // foreach (var recipeCmd in standbyStep.RecipeCommands.Keys) // { // if (!OP.CanDoOperation($"{Module}.{recipeCmd}", out string reason, standbyStep.RecipeCommands[recipeCmd])) // { // if (!OP.CanDoOperation($"{ModuleName.PM1}.{recipeCmd}", out reason, standbyStep.RecipeCommands[recipeCmd])) // { // if (!OP.CanDoOperation($"{ModuleName.System}.{recipeCmd}", out reason, standbyStep.RecipeCommands[recipeCmd])) // { // reason = $"Can not execute {recipeCmd}, {reason}"; // return false; // } // else // { // OP.DoOperation($"{ModuleName.System}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); // } // } // else // { // OP.DoOperation($"{ModuleName.PM1}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); // } // } // else // { // OP.DoOperation($"{Module}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); // } // } // } // _isStandbyStep = true; // IsExcuteIdleRecipe = false; //} //else if (SC.GetStringValue($"System.Recipe.ExcuteAfterRecipeComplete") == "IdleRecipe") //{ // if (!IsExcuteIdleRecipe) // { // PostMsg((int)MSG.RunIdleRecipe); // IsExcuteIdleRecipe = true; // } // else // { // IsExcuteIdleRecipe = false; // _isStandbyStep = false; // } //} //else //{ // IsExcuteIdleRecipe = false; // _isStandbyStep = false; //} return true; } public string GetN2PurgeModeEnumByStr(string str) { if ((str == N2PurgeModeEnum.ATMMode.ToString()) || (str == N2PurgeModeEnum.ATMMode.ToDescription()) || (str.StartsWith("ATM"))) { return N2PurgeModeEnum.ATMMode.ToString(); } if ((str == N2PurgeModeEnum.N2PurgeMode.ToString()) || (str == N2PurgeModeEnum.N2PurgeMode.ToDescription()) || (str.StartsWith("N2"))) { return N2PurgeModeEnum.N2PurgeMode.ToString(); } return N2PurgeModeEnum.ManualMode.ToString(); } private bool FsmStartContinue(object[] param) { return true; } private bool FsmSkipStep(object[] param) { _processRoutine.SkipCurrentRecipeStep(); return true; } private bool FsmJumpStep(object[] param) { int.TryParse(param[0].ToString(), out int stepNumber); _processRoutine.JumpCurrentRecipeStep(stepNumber, param[1].ToString()); return true; } private bool FsmRecipePause(object[] param) { _processRoutine.PauseRecipe(); return true; } private bool FsmRecipeContinue(object[] param) { _processRoutine.ContinueRecipe(); return true; } private bool FsmRecipeAbort(object[] param) { Singleton.Instance.EndPj("Recipe Abort"); _processRoutine.Abort(); IsWait = false; IsJobProcess = false; var recipeName = _recipeRunningInfo.Head.AbortRecipe; var reason = ""; if (!File.Exists($"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Abort\\{recipeName}.rcp") || !RecipeParser.Parse(recipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out reason, "Abort")) { recipeName = SC.GetStringValue("System.Recipe.Abort Recipe"); if (!File.Exists($"{PathManager.GetRecipeDir()}\\{SC.GetStringValue("System.Recipe.SupportedChamberType")}\\Abort\\{recipeName}.rcp") || !RecipeParser.Parse(SC.GetStringValue("System.Recipe.Abort Recipe"), ModuleName.PM1.ToString(), out recipeHead, out recipeSteps, out reason, "Abort")) { PostMsg(MSG.Error); ExecuteAbortRecipeFailAlarm.Set($"Load abort recipe {recipeName} failed, {reason}"); return false; } } RecipeRunningInfo.MainRecipeName = recipeName; RecipeRunningInfo.Head = recipeHead; RecipeRunningInfo.RecipeStepList = recipeSteps; Result ret = StartRoutine(_processRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartPostProcess(object[] param) { Result ret = StartRoutine(_postprocessRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool ExitPostProcess(object[] param) { return true; } private bool FsmStartMFCCalibration(object[] param) { return true; } private bool FsmOnDisconnect(object[] param) { if (FsmState == (int)STATE.Error) { return false; } return true; } private bool FsmOnError(object[] param) { if (FsmState == (int)STATE.Error) { return false; } if ((FsmState == (int)STATE.Process) || (FsmState == (int)STATE.PreProcess) || (FsmState == (int)STATE.PostProcess)) { for (int i = 0; i < SC.GetValue($"Boat.SlotCount"); i++) { if (!WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Module), i)) continue; WaferManager.Instance.UpdateWaferProcessStatus(ModuleHelper.Converter(Module), i, EnumWaferProcessStatus.Failed); } _processRoutine.Abort(); _postprocessRoutine.Abort(); _preprocessRoutine.Abort(); IsWait = false; } return true; } private bool FsmReset(object[] param) { if (!_isInit) { PostMsg(MSG.ToInit); return false; } foreach (var device in _allModuleDevice) { if (device.HasAlarm) { CheckHasAlarmWarning.Set($"{device.Name} has error"); } } if (CheckHasAlarm()) return false; return true; } private bool FsmStartHome(object[] param) { //if (!CheckIsConnected()) //{ // PostMsg(MSG.Disconnected); // return false; //} if (CheckHasAlarm()) { CheckHasAlarmWarning.Set($"There exist active alarm, reset error before continue the initialization"); PostMsg(MSG.Error); return false; } Result ret = StartRoutine(_homeRoutine); if (ret == Result.FAIL || ret == Result.DONE) return false; _isInit = false; return ret == Result.RUN; } private bool FsmExitHome(object[] param) { return true; } private bool FsmEnterHome(object[] param) { return true; } private bool FsmAbortTask(object[] param) { AbortRoutine(); _isPrepareProcess = true; return true; } private bool FsmMonitorHomeTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } if (ret == Result.DONE) { _isInit = true; return true; } return false; } private bool FsmMonitorTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } if (ret == Result.DONE && FsmState == (int)STATE.PreProcess) { PostMsg(MSG.Process); return true; } if (ret == Result.DONE && FsmState == (int)STATE.Process) { PostMsg(MSG.PostProcess); return true; } if (ret == Result.DONE && IsExcuteIdleRecipe && FsmState == (int)STATE.PostProcess) { PostMsg(MSG.RunIdleRecipe); return true; } return ret == Result.DONE; } #region Service functions public override bool Home(out string reason) { CheckToPostMessage((int)MSG.Home); reason = string.Empty; return true; } public override void Reset() { ResetAUXTrig(); if (!IsProcessing) CheckToPostMessage((int)MSG.Reset); } public override bool PrepareTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { CheckToPostMessage((int)MSG.PrepareTransfer, transferType.ToString()); reason = string.Empty; return true; } public override bool TransferHandoff(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return true; } public override bool PostTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { CheckToPostMessage((int)MSG.PostTransfer, transferType.ToString()); reason = string.Empty; return true; } public override bool CheckReadyForTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; var boat = Singleton.Instance.Modules[ModuleName.Boat] as BoatModule; if (!boat.IsBoatElevatorAtHomePosition) { reason = "Boat z axis is not at home position"; return false; } if (!boat.IsBoatRotationAtHomePosition) { reason = "Boat r axis is not at home position"; return false; } return true; } public override void NoteTransferStart(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { //if (FsmState == (int)STATE.InTransfer) // CheckToPostMessage(MSG.Transfer) } public override void NoteTransferStop(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { //if (FsmState == (int)STATE.InTransfer) // CheckToPostMessage(MSG.Transfer) } public override bool Process(string recipeName, bool isCleanRecipe, bool withWafer, out string reason) { _recipeRunningInfo.RecipeName = recipeName; _isPrepareProcess = false; _isStandbyStep = false; IsJobProcess = true; IsExcuteIdleRecipe = false; CheckToPostMessage((int)MSG.RunRecipe, recipeName); reason = string.Empty; return true; } public override bool Standby(string recipeName, out string reason) { reason = string.Empty; _recipeRunningInfo.RecipeName = recipeName; _recipeRunningInfo.MainRecipeName = recipeName; if (!RecipeParser.Parse(_recipeRunningInfo.RecipeName, ModuleName.PM1.ToString(), out var recipeHead, out var recipeSteps, out reason, "Process")) { reason = $"Load process recipe {_recipeRunningInfo.RecipeName} failed, {reason}"; return false; } if (recipeSteps == null || recipeSteps.Count == 0) { reason = $"Process recipe {_recipeRunningInfo.RecipeName} is empty"; return false; } _isStandbyStep = true; var standbyStep = recipeSteps.Where(x => x.StepName == "Standby").FirstOrDefault(); if (standbyStep != null) { StringProcessFlowState = ProcessFlowState.Standby.ToString(); _recipeRunningInfo.StepName = "Standby"; EV.PostInfoLog(Module, $"pj job excute recipe {recipeName} standby step"); foreach (var recipeCmd in standbyStep.RecipeCommands.Keys) { if (!OP.CanDoOperation($"{Module}.{recipeCmd}", out reason, standbyStep.RecipeCommands[recipeCmd])) { if (!OP.CanDoOperation($"{ModuleName.PM1}.{recipeCmd}", out reason, standbyStep.RecipeCommands[recipeCmd])) { if (!OP.CanDoOperation($"{ModuleName.System}.{recipeCmd}", out reason, standbyStep.RecipeCommands[recipeCmd])) { reason = $"Can not execute {recipeCmd}, {reason}"; return false; } else { OP.DoOperation($"{ModuleName.System}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); } } else { OP.DoOperation($"{ModuleName.PM1}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); } } else { OP.DoOperation($"{Module}.{recipeCmd}", out string reason1, 0, standbyStep.RecipeCommands[recipeCmd]); } } } return true; } public void EndIdleRecipe() { CheckToPostMessage((int)MSG.EndIdleRecipe); } private double GetNewShowTime() { return GetWaitTime() + _recipeRunningInfo.HoldTime; } private double GetWaitTime() { if (StringFsmStatus == "Idle") { _waitTimer.Reset(); } if (IsWait) { _waitTimer.Start(); } else { _waitTimer.Stop(); } return _waitTimer.ElapsedMilliseconds / 1000; } } #endregion }