using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Aitex.Core.RT.Fsm; using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Event; 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 Venus_Core; using Venus_RT.Modules.PMs; using Aitex.Core.RT.Log; namespace Venus_RT.Modules { class RouteManager : Entity, IEntity { public enum MSG { MoveWafer, ReturnWafer, HomeUnit, PauseAuto, ResumeAuto, Stop, StartCycle, StopCycle, 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, TMCycle, } public PMEntity PMA { get; private set; } public PMEntity PMB { get; private set; } public PMEntity PMC { get; private set; } public PMEntity PMD { get; private set; } public TMEntity TM { get; private set; } public LLEntity LLA { get; private set; } public LLEntity LLB { get; private set; } public EfemEntity EFEM { get; private set; } public string Name { get; set; } public bool IsAutoMode { get { return fsm.State == (int)RtState.AutoRunning || fsm.State == (int)RtState.AutoIdle; } } public bool IsInit { get { return fsm.State == (int)RtState.Init; } } public bool IsIdle { get { return fsm.State == (int)RtState.Idle || fsm.State == (int)RtState.AutoIdle; } } 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 TMCycle _TMCycle; public RouteManager() { Name = "System"; if (ModuleHelper.IsInstalled(ModuleName.PMA)) PMA = new PMEntity(ModuleName.PMA); if (ModuleHelper.IsInstalled(ModuleName.PMB)) PMB = new PMEntity(ModuleName.PMB); if (ModuleHelper.IsInstalled(ModuleName.PMC)) PMC = new PMEntity(ModuleName.PMC); if (ModuleHelper.IsInstalled(ModuleName.PMD)) PMD = new PMEntity(ModuleName.PMD); if (ModuleHelper.IsInstalled(ModuleName.TM)) TM = new TMEntity(); if (ModuleHelper.IsInstalled(ModuleName.LLA)) LLA = new LLEntity(ModuleName.LLA); if (ModuleHelper.IsInstalled(ModuleName.LLB)) LLB = new LLEntity(ModuleName.LLB); if (ModuleHelper.IsInstalled(ModuleName.EFEM)) EFEM = new EfemEntity(); fsm = new StateMachine(Name, (int)RtState.Init, 200); SubscribeOperation(); } 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, 0, (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; } 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); 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) return 1; if (IsAlarm) return 3; return 2; }, SubscriptionAttribute.FLAG.IgnoreSaveDB); } void SubscribeOperation() { OP.Subscribe("CreateWafer", InvokeCreateWafer); OP.Subscribe("DeleteWafer", InvokeDeleteWafer); OP.Subscribe("System.Home", (cmd, args) => CheckToPostMessage((int)MSG.HOME, args)); OP.Subscribe("TMCycle.Start", (cmd, args) => CheckToPostMessage((int)MSG.TMCycle, args)); OP.Subscribe("TMCycle.Abort", (cmd, args) => CheckToPostMessage((int)MSG.StopCycle, args)); DATA.Subscribe("SYSTEM.FsmState", () => (((RtState)fsm.State).ToString())); DATA.Subscribe("TMCycle.CycleIndex", () => (_TMCycle.CycleIndex)); } public bool CheckToPostMessage(int msg, params object[] args) { if (!fsm.FindTransition(fsm.State, msg)) { LOG.Write(eEvent.WARN_FSM_WARN, ModuleName.TM, $"TM is in {(RtState)fsm.State} state,can not do {(MSG)msg}"); return false; } Running = true; fsm.PostMsg(msg, args); 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()); LOG.Write(eEvent.EV_WAFER_CREATE, ModuleName.System, chamber.ToString(), (slot + 1).ToString(), state.ToString()); } } else { EV.PostWarningLog("System", string.Format("Invalid position,{0},{1}", chamber.ToString(), slot.ToString())); return false; } return true; } 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; } public PMEntity GetPM(ModuleName mod) { if (ModuleHelper.IsInstalled(mod)) { switch (mod) { case ModuleName.PMA: return PMA; case ModuleName.PMB: return PMB; case ModuleName.PMC: return PMC; case ModuleName.PMD: return PMD; } } return null; } public LLEntity GetLL(ModuleName mod) { if (ModuleHelper.IsInstalled(mod)) { switch (mod) { case ModuleName.LLA: return LLA; case ModuleName.LLB: return LLB; } } return null; } public TMEntity GetTM() { return TM; } protected override bool Init() { PMA?.Initialize(); PMB?.Initialize(); TM?.Initialize(); LLA?.Initialize(); LLB?.Initialize(); EFEM?.Initialize(); _TMCycle = new TMCycle(); BuildTransitionTable(); return true; } private void BuildTransitionTable() { fsm = new StateMachine(ModuleName.System.ToString(), (int)RtState.Init, 50); //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.Idle, FSM_MSG.TIMER, FsmMonitor, RtState.Idle); Transition(RtState.Init, FSM_MSG.TIMER, FsmMonitor, RtState.Init); Transition(RtState.Initializing, FSM_MSG.TIMER, FsmMonitorHome, RtState.Idle); Transition(RtState.Initializing, MSG.ERROR, FsmError, RtState.Error); Transition(RtState.Initializing, MSG.ABORT, FsmAbort, RtState.Init); // TM Cycle Transition(RtState.Idle, MSG.TMCycle, FsmStartTMCycle, RtState.TMCycle); Transition(RtState.TMCycle, FSM_MSG.TIMER, FsmMonitorTMCycle, RtState.Idle); Transition(RtState.TMCycle, MSG.StopCycle, FsmStopTMCycle, RtState.Idle); } private bool FsmMonitor(object[] objs) { _debugRoutine(); return true; } private bool FsmStartHome(object[] objs) { PMA?.Invoke("Home"); PMB?.Invoke("Home"); PMC?.Invoke("Home"); PMD?.Invoke("Home"); TM?.Invoke("Home"); LLA?.Invoke("Home"); LLB?.Invoke("Home"); return true; } private bool FsmMonitorHome(object[] objs) { bool CheckHomed(string name, bool bValid, bool bDone) { if (bValid && !bDone) { if (fsm.ElapsedTime > 20 * 1000) { LOG.Write(eEvent.ERR_ROUTER, ModuleName.System, $"{name} home timeout"); PostMsg(MSG.ERROR); return true; } else return false; } return true; } return CheckHomed("PMA", PMA != null, PMA != null&&PMA.IsIdle) && CheckHomed("PMB", PMB != null, PMB != null&&PMA.IsIdle) && CheckHomed("PMC", PMC != null, PMC != null&&PMC.IsIdle) && CheckHomed("PMD", PMD != null, PMD != null&&PMD.IsIdle) && CheckHomed("LLA", LLA != null, LLA != null&&LLA.IsIdle) && CheckHomed("LLB", LLB != null, LLB != null&&LLB.IsIdle) && CheckHomed("TM", TM != null, TM != null&&TM.IsIdle); } private bool FsmError(object[] objs) { return true; } private bool FsmAbort(object[] objs) { return true; } private bool FsmStartTMCycle(object[] objs) { return _TMCycle.Start(objs) == RState.Running; } private bool FsmMonitorTMCycle(object[] objs) { RState ret = _TMCycle.Monitor(); if (ret == RState.Failed || ret == RState.Timeout) { PostMsg(MSG.ERROR); return false; } return ret == RState.End; } private bool FsmStopTMCycle(object[] objs) { _TMCycle.Abort(); return true; } private void _debugRoutine() { int flag = 0; // Test Home routine if (flag == 1) { PostMsg(MSG.HOME); } else if (flag == 2) { PostMsg(MSG.TMCycle); } } } }