using System; using System.Collections.Generic; using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; 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 MECF.Framework.Common.Equipment; using MECF.Framework.Common.SubstrateTrackings; using VirgoCommon; using VirgoRT.HostWrapper; using VirgoRT.Instances; using VirgoRT.Module; namespace VirgoRT.Modules { class RouteManager : Entity, IEntity { public enum MSG { MoveWafer, ReturnWafer, HomeUnit, PauseAuto, ResumeAuto, Stop, StartCycle, HOME, RESET, ABORT, ERROR, SetAutoMode, SetManualMode, ResetIdleCleanTime, ResetIdlePurgeTime, CreateJob, PauseJob, ResumeJob, StartJob, StopJob, AbortJob, JobDone, CassetteLeave, //For unload light control off afer job done Map, ReturnAllWafer, } //public LoadPortEntity LP1 { get; private set; } //public LoadPortEntity LP2 { get; private set; } //public CoolingStorageEntity Aligner { get; private set; } public EfemEntity EFEM { get; private set; } public PMEntity PMA { get; private set; } public PMEntity PMB { get; private set; } //routine public bool IsAutoIdle { get { return fsm.State == (int)RtState.AutoIdle; } } public bool IsAutoMode { get { return fsm.State == (int)RtState.AutoRunning || fsm.State == (int)RtState.AutoIdle; } } public string Name { get; set; } public bool IsInit { get { return fsm.State == (int)RtState.Init; } } public bool IsIdle { get { return fsm.State == (int)RtState.Idle; } } public bool IsAlarm { get { return fsm.State == (int)RtState.Error; } } public bool IsEntityError { get { return (EFEM?.IsError ?? false) || (PMA?.IsError ?? false) || (PMB?.IsError ?? false); } } public bool IsRunning { get { return !IsInit && !IsAlarm && !IsIdle; } } private ManualTransfer _manualTransfer; private AutoTransfer _auto = null; private ReturnAllWafer _returnWafer; private HomeAll _homeAll = new HomeAll(); private bool _isWaitUnload; public RouteManager() { Name = "System"; //LP1 = new LoadPortEntity(ModuleName.LP1); //LP2 = new LoadPortEntity(ModuleName.LP2); //Aligner = new CoolingStorageEntity(ModuleName.Aligner); EFEM = new EfemEntity(); if (SC.GetValue("System.PMAIsInstalled")) PMA = new PMEntity(ModuleName.PMA); if (SC.GetValue("System.PMBIsInstalled")) PMB = new PMEntity(ModuleName.PMB); fsm = new StateMachine(Name, (int)RtState.Init, 50); BuildTransitionTable(); SubscribeDataVariable(); SubscribeOperation(); Running = true; } private void BuildTransitionTable() { EnterExitTransition(RtState.AutoRunning, fEnterAutoRunning, FSM_MSG.NONE, fExitAutoTransfer); EnterExitTransition(RtState.Transfer, null, FSM_MSG.NONE, fExitTransfer); EnterExitTransition(RtState.Idle, fEnterIdle, FSM_MSG.NONE, fExitIdle); EnterExitTransition(RtState.ReturnWafer, null, FSM_MSG.NONE, FsmExitReturnWafer); //Init sequence Transition(RtState.Init, MSG.HOME, FsmStartHome, RtState.Initializing); Transition(RtState.Idle, MSG.HOME, FsmStartHome, RtState.Initializing); Transition(RtState.Error, MSG.HOME, FsmStartHome, RtState.Initializing); // EnterExitTransition(RtState.Initializing, fStartInit, FSM_MSG.NONE, null); Transition(RtState.Initializing, FSM_MSG.TIMER, FsmMonitorHome, RtState.Idle); Transition(RtState.Initializing, MSG.ERROR, fError, RtState.Error); Transition(RtState.Initializing, MSG.ABORT, FsmAbort, RtState.Init); //Reset AnyStateTransition(MSG.RESET, fStartReset, RtState.Idle); AnyStateTransition(MSG.ERROR, fError, RtState.Error); AnyStateTransition((int)FSM_MSG.ALARM, fError, (int)RtState.Error); //Unload cassette AnyStateTransition(MSG.CassetteLeave, fCassetteLeave, FSM_STATE.SAME); //Auto/manual Transition(RtState.Idle, MSG.SetAutoMode, fStartAutoTransfer, RtState.AutoIdle); Transition(RtState.AutoRunning, FSM_MSG.TIMER, fAutoTransfer, RtState.Idle); Transition(RtState.AutoRunning, MSG.ABORT, fAbortAutoTransfer, RtState.Idle); //Transition(RtState.AutoRunning, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle); Transition(RtState.AutoRunning, MSG.JobDone, fJobDone, RtState.AutoIdle); //Transition(RtState.AutoRunning, MSG.CassetteLeave, fCassetteLeave, RtState.AutoRunning); //For unload light control off afer job done Transition(RtState.AutoRunning, MSG.CreateJob, FsmCreateJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.StartJob, FsmStartJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.PauseJob, FsmPauseJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.ResumeJob, FsmResumeJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.StopJob, FsmStopJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.AbortJob, FsmAbortJob, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.Map, FsmMap, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.ResetIdleCleanTime, FsmResetIdleCleanTime, RtState.AutoRunning); Transition(RtState.AutoRunning, MSG.ResetIdlePurgeTime, FsmResetIdlePurgeTime, RtState.AutoRunning); Transition(RtState.AutoIdle, FSM_MSG.TIMER, FsmMonitorAutoIdle, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.SetManualMode, FsmStartSetManualMode, RtState.Idle); Transition(RtState.AutoIdle, MSG.CreateJob, FsmCreateJob, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.StartJob, FsmStartJob, RtState.AutoRunning); Transition(RtState.AutoIdle, MSG.PauseJob, FsmPauseJob, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.ResumeJob, FsmResumeJob, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.StopJob, FsmStopJob, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.AbortJob, FsmAbortJob, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.Map, FsmMap, RtState.AutoIdle); //Transition(RtState.AutoIdle, MSG.CassetteLeave, fCassetteLeave, RtState.AutoIdle); //For unload light control off afer job done Transition(RtState.AutoIdle, MSG.ResetIdleCleanTime, FsmResetIdleCleanTime, RtState.AutoIdle); Transition(RtState.AutoIdle, MSG.ResetIdlePurgeTime, FsmResetIdlePurgeTime, RtState.AutoIdle); //Transfer Transition(RtState.Idle, MSG.MoveWafer, fStartTransfer, RtState.Transfer); Transition(RtState.Transfer, FSM_MSG.TIMER, fTransfer, RtState.Idle); Transition(RtState.Transfer, MSG.ABORT, FsmAbort, RtState.Idle); //Return Wafer Transition(RtState.Idle, MSG.ReturnAllWafer, FsmStartReturnWafer, RtState.ReturnWafer); Transition(RtState.ReturnWafer, FSM_MSG.TIMER, FsmMonitorReturnWafer, RtState.Idle); Transition(RtState.ReturnWafer, MSG.ABORT, FsmAbort, RtState.Idle); } void SubscribeDataVariable() { DATA.Subscribe("Rt.Status", () => ((RtState)fsm.State).ToString()); DATA.Subscribe(ModuleName.System.ToString(), "AlarmEvent", EV.GetAlarmEvent); DATA.Subscribe("System.IsAutoMode", () => IsAutoMode); DATA.Subscribe("System.IsIdle", () => IsIdle || IsInit || IsAutoIdle); DATA.Subscribe("System.IsAlarm", () => IsAlarm || IsEntityError); DATA.Subscribe("System.IsBusy", () => IsRunning); DATA.Subscribe("System.IsWaitUnload", () => _isWaitUnload && IsAutoMode); DATA.Subscribe("System.IsConnectedWithHost", () => Singleton.Instance.IsConnected); DATA.Subscribe("EquipmentMode", () => IsAutoMode ? 0 : 1, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe("EquipmentStatus", () => { //"0 = Uninit //1 = Idle //2 = Running //3 = Error //4 = Pause //" if (IsInit) return 0; if (IsIdle||fsm.State == (int)RtState.AutoIdle) return 1; if (IsAlarm) return 3; return 2; }, SubscriptionAttribute.FLAG.IgnoreSaveDB); } void SubscribeOperation() { OP.Subscribe("CreateWafer", InvokeCreateWafer); OP.Subscribe("DeleteWafer", InvokeDeleteWafer); OP.Subscribe("ReturnWafer", InvokeReturnWafer); OP.Subscribe("System.ReturnAllWafer", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.ReturnAllWafer, args[0], args[1]); }); OP.Subscribe("System.MoveWafer", (string cmd, object[] args) => { if (!Enum.TryParse((string)args[0], out ModuleName source)) { EV.PostWarningLog(Name, $"Parameter source {(string)args[0]} not valid"); return false; } if (!Enum.TryParse((string)args[2], out ModuleName destination)) { EV.PostWarningLog(Name, $"Parameter destination {(string)args[1]} not valid"); return false; } return CheckToPostMessage((int)MSG.MoveWafer, source, (int)args[1], destination, (int)args[3], (bool)args[4], (int)args[5], (bool)args[6], (int)args[7], (string)args[8]); }); OP.Subscribe("System.HomeAll", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.HOME); }); OP.Subscribe("System.Abort", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.ABORT); }); OP.Subscribe("System.Reset", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.RESET); }); OP.Subscribe("System.SetAutoMode", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.SetAutoMode); }); OP.Subscribe("System.SetManualMode", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.SetManualMode); }); OP.Subscribe("System.CreateJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.CreateJob, args[0]); }); OP.Subscribe("System.StartJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.StartJob, args[0]); }); OP.Subscribe("System.PauseJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.PauseJob, args[0]); }); OP.Subscribe("System.ResumeJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.ResumeJob, args[0]); }); OP.Subscribe("System.StopJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.StopJob, args[0]); }); OP.Subscribe("System.AbortJob", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.AbortJob, args[0]); }); OP.Subscribe("LP1.Map", (string cmd, object[] args) => { if (IsAutoMode) { return CheckToPostMessage((int)MSG.Map, ModuleName.LP1.ToString()); } return EFEM.InvokeMap(ModuleName.LP1.ToString())!= (int)FSM_MSG.NONE; }); OP.Subscribe("LP2.Map", (string cmd, object[] args) => { if (IsAutoMode) { return CheckToPostMessage((int)MSG.Map, ModuleName.LP2.ToString()); } return EFEM.InvokeMap(ModuleName.LP2.ToString()) != (int)FSM_MSG.NONE; }); OP.Subscribe(RtOperation.SetConfig.ToString(), (name, args) => { string sc_key = args[0] as string; if (!string.IsNullOrWhiteSpace(sc_key) && args.Length > 1) { SC.SetItemValue(sc_key, args[1]); } return true; }); OP.Subscribe("System.ResetIdleCleanTime", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.ResetIdleCleanTime, args[0]); }); OP.Subscribe("System.ResetIdlePurgeTime", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.ResetIdlePurgeTime, args[0]); }); OP.Subscribe("System.SetWaferSize", (string cmd, object[] args) => { string module = (string)args[0]; string size = (string)args[1]; switch (size) { case "3": WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS3); break; case "4": WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS4); break; case "6": WaferManager.Instance.UpdateWaferSize(ModuleHelper.Converter(module), 0, WaferSize.WS6); break; default: EV.PostWarningLog("System", $"wafer size {size} not valid"); break; } return true; }); OP.Subscribe("System.CassetteLeave", (string cmd, object[] args) => { return CheckToPostMessage((int)MSG.CassetteLeave); }); } public bool CheckToPostMessage(int msg, params object[] args) { if (!fsm.FindTransition(fsm.State, msg)) { EV.PostWarningLog(Name, $"{Name} is in { (RtState)fsm.State} state,can not do {(MSG)msg}"); return false; } fsm.PostMsg(msg, args); return true; } public bool Check(int msg, out string reason, params object[] args) { if (!fsm.FindTransition(fsm.State, msg)) { reason = String.Format("{0} is in {1} state,can not do {2}", Name, (RtState)fsm.State, (MSG)msg); return false; } if (msg == (int)MSG.StartCycle) { if (!IsAutoMode) { reason = String.Format("can not do {0}, isn't auto mode.", msg.ToString()); return false; } } reason = ""; return true; } protected override bool Init() { _manualTransfer = new ManualTransfer(); Singleton.Instance.OnAlarmEvent += Instance_OnAlarmEvent; EFEM.Initialize(); //Aligner.Initialize(); //LP1.Initialize(); //LP2.Initialize(); PMA?.Initialize(); PMB?.Initialize(); _auto = new AutoTransfer(); _returnWafer = new ReturnAllWafer(); return true; } private void Instance_OnAlarmEvent(EventItem obj) { FSM_MSG msg = FSM_MSG.NONE; if (obj.Level == EventLevel.Warning) msg = FSM_MSG.WARNING; else if (obj.Level == EventLevel.Alarm) msg = FSM_MSG.ALARM; switch (obj.Source) { case "PMA": PMA?.PostMsg(msg, obj.Id, obj.Description); break; case "PMB": PMB?.PostMsg(msg, obj.Id, obj.Description); break; case "EFEM": EFEM?.PostMsg(msg, obj.Id, obj.Description); break; //case "System": // PostMsg(msg, obj.Id, obj.Description); // break; } } protected override void Term() { PMA?.Terminate(); PMB?.Terminate(); //LP2.Terminate(); //LP1.Terminate(); EFEM.Terminate(); } #region Init private bool FsmStartHome(object[] objs) { return _homeAll.Start() == Result.RUN; } private bool FsmMonitorHome(object[] objs) { Result ret = _homeAll.Monitor(); if (ret == Result.DONE) { _homeAll.Clear(); return true; } if (ret == Result.FAIL) { _homeAll.Clear(); PostMsg(MSG.ERROR); } return false; } private bool fError(object[] objs) { if (fsm.State == (int)RtState.Transfer) { _manualTransfer.Clear(); } //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.RED, LightStatus.ON); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.YELLOW, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.GREEN, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BLUE, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BUZZER1, LightStatus.ON); return true; } private bool fEnterIdle(object[] param) { //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.RED, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.YELLOW, LightStatus.ON); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.GREEN, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BLUE, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BUZZER1, LightStatus.OFF); return true; } private bool fExitIdle(object[] param) { return true; } #endregion Init #region AutoTransfer private bool FsmMonitorAutoIdle(object[] param) { Result ret = _auto.Monitor(); if (!_auto.CheckAllJobDone()) { return false; } _isWaitUnload = (bool)DATA.Poll("LP1.NotifyJobDone") || (bool)DATA.Poll("LP2.NotifyJobDone"); return ret == Result.DONE; } private bool FsmStartSetManualMode(object[] objs) { if (_auto.HasJobRunning) { EV.PostWarningLog("System", "Can not change to manual mode, abort running job first"); return false; } return true; } private bool fStartAutoTransfer(object[] objs) { Result ret = _auto.Start(objs); return ret == Result.RUN; } private bool fAutoTransfer(object[] objs) { Result ret = _auto.Monitor(); if (_auto.CheckJobJustDone(out string jobInfo)) { EV.PostPopDialogMessage(EventLevel.InformationNoDelay, "Job complete", jobInfo); } if (_auto.CheckAllJobDone()) { if (!CheckToPostMessage((int)MSG.JobDone)) return false; } _isWaitUnload = (bool)DATA.Poll("LP1.NotifyJobDone") || (bool)DATA.Poll("LP2.NotifyJobDone"); return ret == Result.DONE; } private bool fEnterAutoRunning(object[] objs) { //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.RED, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.GREEN, LightStatus.ON); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.YELLOW, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BLUE, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BUZZER1, LightStatus.OFF); return true; } private bool fExitAutoTransfer(object[] objs) { _auto.Clear(); return true; } private bool fJobDone(object[] objs) { //Unload light control on //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.RED, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.GREEN, LightStatus.BLINK); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.YELLOW, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BLUE, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BUZZER1, LightStatus.OFF); _isWaitUnload = true; return true; } private bool fCassetteLeave(object[] objs) { //Unload light control off,light as idle & autoidle mode //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.RED, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.GREEN, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.YELLOW, LightStatus.ON); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BLUE, LightStatus.OFF); //EFEM.PostMsg(EfemEntity.MSG.LED, LightType.BUZZER1, LightStatus.OFF); _isWaitUnload = false; return true; } private bool fAbortAutoTransfer(object[] objs) { _auto.Clear(); return true; } #endregion AutoTransfer #region return wafer private bool FsmStartReturnWafer(object[] objs) { Result ret = _returnWafer.Start(objs); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmMonitorReturnWafer(object[] objs) { Result ret = _returnWafer.Monitor(objs); if (ret == Result.FAIL) { PostMsg(MSG.ERROR); return false; } return ret == Result.DONE; } private bool FsmExitReturnWafer(object[] objs) { _returnWafer.Clear(); return true; } #endregion cycle #region Transfer private bool fStartTransfer(object[] objs) { Result ret = _manualTransfer.Start(objs); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool fTransfer(object[] objs) { Result ret = _manualTransfer.Monitor(objs); if (ret == Result.FAIL) { PostMsg(MSG.ERROR); return false; } return ret == Result.DONE; } private bool fExitTransfer(object[] objs) { _manualTransfer.Clear(); return true; } #endregion Transfer #region reset private bool fStartReset(object[] objs) { //LP1.InvokeReset(); //LP2.InvokeReset(); //Aligner.InvokeReset(); EFEM.InvokeReset(); PMA?.InvokeReset(); PMB?.InvokeReset(); Singleton.Instance.PostMsg(DeviceEntity.MSG.RESET); Singleton.Instance.ClearAlarm(null); if (fsm.State == (int)RtState.Error) return true; return false; } #endregion reset private bool FsmMap(object[] param) { _auto.Map((string)param[0]); return true; } public bool CheckRecipeUsedInJob(string pathName) { if (!IsAutoMode) return false; return _auto.CheckRecipeUsedInJob(pathName); } public bool CheckSequenceUsedInJob(string pathName) { if (!IsAutoMode) return false; return _auto.CheckSequenceUsedInJob(pathName); } private bool FsmCreateJob(object[] param) { _auto.CreateJob((Dictionary)param[0]); return true; } private bool FsmAbortJob(object[] param) { _auto.AbortJob((string)param[0]); return true; } private bool FsmStopJob(object[] param) { _auto.StopJob((string)param[0]); return true; } private bool FsmResumeJob(object[] param) { _auto.ResumeJob((string)param[0]); return true; } private bool FsmPauseJob(object[] param) { _auto.PauseJob((string)param[0]); return true; } private bool FsmStartJob(object[] param) { _auto.StartJob((string)param[0]); return true; } private bool FsmAbort(object[] param) { if (fsm.State == (int)RtState.Transfer) { _manualTransfer.Clear(); } if (fsm.State == (int)RtState.AutoRunning) { _auto.Clear(); } if (fsm.State == (int)RtState.ReturnWafer) { _returnWafer.Clear(); } return true; } private bool FsmResetIdlePurgeTime(object[] param) { _auto.ResetIdlePurgeTime((string)param[0]); return true; } private bool FsmResetIdleCleanTime(object[] param) { _auto.ResetIdleCleanTime((string)param[0]); return true; } private bool InvokeReturnWafer(string arg1, object[] args) { ModuleName target = ModuleHelper.Converter(args[0].ToString()); int slot = (int)args[1]; if (ModuleHelper.IsLoadPort(target)) { EV.PostInfoLog("System", string.Format("Wafer already at LoadPort {0} {1}, return operation is not valid", target.ToString(), slot + 1)); return false; } if (!WaferManager.Instance.IsWaferSlotLocationValid(target, slot)) { EV.PostWarningLog("System", string.Format("Invalid position,{0},{1}", target.ToString(), slot.ToString())); return false; } WaferInfo wafer = WaferManager.Instance.GetWafer(target, slot); if (wafer.IsEmpty) { EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, return operation is not valid", target.ToString(), slot + 1)); return false; } return CheckToPostMessage((int)MSG.MoveWafer, target, slot, (ModuleName)wafer.OriginStation, wafer.OriginSlot, false, 0, false, 0 , "Blade1"); } private bool InvokeDeleteWafer(string arg1, object[] args) { ModuleName chamber = ModuleHelper.Converter(args[0].ToString()); int slot = (int)args[1]; if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot)) { if (WaferManager.Instance.CheckHasWafer(chamber, slot)) { WaferManager.Instance.DeleteWafer(chamber, slot); EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferDelete, chamber.ToString(), slot + 1); } else { EV.PostInfoLog("System", string.Format("No wafer at {0} {1}, delete not valid", chamber.ToString(), slot + 1)); } } else { EV.PostWarningLog("System", string.Format("Invalid position,{0},{1}", chamber.ToString(), slot.ToString())); return false; } return true; } private bool InvokeCreateWafer(string arg1, object[] args) { ModuleName chamber = ModuleHelper.Converter(args[0].ToString()); int slot = (int)args[1]; WaferStatus state = WaferStatus.Normal; if (WaferManager.Instance.IsWaferSlotLocationValid(chamber, slot)) { if (WaferManager.Instance.CheckHasWafer(chamber, slot)) { EV.PostInfoLog("System", string.Format("{0} slot {1} already has wafer.create wafer is not valid", chamber, slot)); } else if (WaferManager.Instance.CreateWafer(chamber, slot, state) != null) { EV.PostMessage(ModuleName.System.ToString(), EventEnum.WaferCreate, chamber.ToString(), slot + 1, state.ToString()); } } else { EV.PostWarningLog("System", string.Format("Invalid position,{0},{1}", chamber.ToString(), slot.ToString())); return false; } return true; } } }