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.Utilities; using Aitex.Sorter.Common; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.RT.ModuleLibrary.LPModules; using System; using VirgoRT.Devices.EFEM; namespace VirgoRT.Modules.LPs { /// /// LP entity /// sealed class LoadPortModule : LoadPortModuleBase { public event Action OnEnterError; private enum STATE { Unknown, Idle, // 1 Init, Error, Homing, // 2 Mapping, // 4 Loading, ReadingCarrierId, Unloading, Docking, Undocking, Clamping, Unclamping, WritingCarrierId, ReadingTagData, WritingTagData, } public enum MSG { Home, // 0 Map, // 1 ActionDone, // 2 Abort, // 5 Online, // 6 Error, // 7 Reset, ReadCarrierId, WriteCarrierID, Load, Unload, Dock, Undock, Clamp, Unclamp, ToInit, ToIdle, ReadTagData, WriteTagData, } private readonly Efem _efem; private Loadport _lpDevice; public Loadport LPDevice { get { return _lpDevice; } } public override bool IsReady { get { return FsmState == (int)STATE.Idle && CheckAllMessageProcessed(); } } public override bool IsError { get { return FsmState == (int)STATE.Error; } } public override bool IsInit { get { return FsmState == (int)STATE.Init; } } private LoadPortHomeRoutine _home; //private LoadPortCloseDoorRoutine _closeDoor; private LoadPortClampRoutine _clamp; private LoadPortReadCarrierIdRoutine _readCarrierId; private LoadPortWriteCarrierIdRoutine _writeCarrierId; private LoadPortReadTagDataRoutine _readTag; private LoadPortWriteTagDataRoutine _writeTag; private LoadPortUnclampRoutine _unclamp; //private LoadPortUndockRoutine _undock; private LoadPortLoadRoutine _load; private LoadPortUnloadRoutine _unload; private bool _isInit; public LoadPortModule(ModuleName module, Efem efem) : base(25) { Name = module.ToString(); Module = module.ToString(); _efem = efem; InitFsmMap(); OP.Subscribe($"{Module}.ReadCarrierId", (cmd, args) => { PostMsg(MSG.ReadCarrierId); return true; }); OP.Subscribe($"{Module}.WriteCarrierID", (cmd, args) => { PostMsg(MSG.WriteCarrierID, args[0]); return true; }); OP.Subscribe($"{Module}.ReadTagData", (cmd, args) => { PostMsg(MSG.ReadTagData); return true; }); OP.Subscribe($"{Module}.WriteTagData", (cmd, args) => { PostMsg(MSG.WriteTagData, args[0]); return true; }); OP.Subscribe($"{Module}.Load", (cmd, args) => { PostMsg(MSG.Load); return true; }); OP.Subscribe($"{Module}.Unload", (cmd, args) => { PostMsg(MSG.Unload); return true; }); OP.Subscribe($"{Module}.Clamp", (cmd, args) => { PostMsg(MSG.Clamp); return true; }); OP.Subscribe($"{Module}.Unclamp", (cmd, args) => { PostMsg(MSG.Unclamp); return true; }); OP.Subscribe($"{Module}.Dock", (cmd, args) => { PostMsg(MSG.Dock); return true; }); OP.Subscribe($"{Module}.Undock", (cmd, args) => { PostMsg(MSG.Undock); return true; }); OP.Subscribe($"{Module}.Reset", (cmd, args) => { PostMsg(MSG.Reset); return true; }); OP.Subscribe($"{Module}.Home", (cmd, args) => { PostMsg(MSG.Home); return true; }); OP.Subscribe($"{Module}.Abort", (cmd, args) => { PostMsg(MSG.Abort); return true; }); OP.Subscribe($"{Module}.Online", (cmd, args) => { PostMsg(MSG.Online); return true; }); DATA.Subscribe($"{Module}.Status", () => ((STATE)FsmState).ToString()); DATA.Subscribe($"{Module}.FsmState", () => ((STATE)FsmState).ToString()); DATA.Subscribe($"{Module}.FsmPrevState", () => ((STATE)FsmPreviousState).ToString()); DATA.Subscribe($"{Module}.FsmLastMessage", GetFsmLastMessage); _lpDevice = efem[module] as Loadport; InitRoutine(); } internal bool CheckPlaced(ModuleName module) { return _lpDevice.HasCassette; } private void InitRoutine() { _home = new LoadPortHomeRoutine(this); //_closeDoor = new LoadPortCloseDoorRoutine(this); _clamp = new LoadPortClampRoutine(this); //_dock = new LoadPortDockRoutine(this); //_map = new LoadPortMapRoutine(this); //_openDoor = new LoadPortOpenDoorRoutine(this); _readCarrierId = new LoadPortReadCarrierIdRoutine(this); _writeCarrierId = new LoadPortWriteCarrierIdRoutine(this); _readTag = new LoadPortReadTagDataRoutine(this); _writeTag = new LoadPortWriteTagDataRoutine(this); _unclamp = new LoadPortUnclampRoutine(this); //_undock = new LoadPortUndockRoutine(this); //_MapDT = new LoadPortGetMapInfoRoutine(this); _load = new LoadPortLoadRoutine(this); _unload = new LoadPortUnloadRoutine(this); } private string GetFsmLastMessage() { int msg = FsmLastMessage; if (msg >= (int)MSG.Home && msg <= (int)MSG.Error) return ((MSG)msg).ToString(); if (msg == (int)FSM_MSG.TIMER) return "Timer"; return msg.ToString(); } private void InitFsmMap() { EnableFsm(50, STATE.Idle); //online AnyStateTransition(MSG.Online, fnOnline, FSM_STATE.SAME); //Error AnyStateTransition(MSG.Error, FsmOnError, STATE.Error); AnyStateTransition(MSG.Reset, FsmReset, STATE.Idle); EnterExitTransition(STATE.Error, FsmEnterError, FSM_MSG.NONE, FsmExitError); //Init Transition(STATE.Init, MSG.Home, FsmStartHome, STATE.Homing); 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); AnyStateTransition(MSG.ToInit, FsmToInit, STATE.Init); //load Transition(STATE.Idle, MSG.Load, FsmStartLoad, STATE.Loading); Transition(STATE.Loading, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Loading, MSG.Abort, FsmAbortTask, STATE.Idle); //unload Transition(STATE.Idle, MSG.Unload, FsmStartUnload, STATE.Unloading); Transition(STATE.Unloading, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Unloading, MSG.Abort, FsmAbortTask, STATE.Idle); //read carrier id Transition(STATE.Idle, MSG.ReadCarrierId, FsmStartReadCarrierId, STATE.ReadingCarrierId); Transition(STATE.ReadingCarrierId, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.ReadingCarrierId, MSG.Abort, FsmAbortTask, STATE.Idle); //clamp Transition(STATE.Idle, MSG.Clamp, FsmStartClamp, STATE.Clamping); Transition(STATE.Clamping, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Clamping, MSG.Abort, FsmAbortTask, STATE.Idle); //unclamp Transition(STATE.Idle, MSG.Unclamp, FsmStartUnclamp, STATE.Unclamping); Transition(STATE.Unclamping, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Unclamping, MSG.Abort, FsmAbortTask, STATE.Idle); //dock Transition(STATE.Idle, MSG.Dock, FsmStartDock, STATE.Docking); Transition(STATE.Docking, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Docking, MSG.Abort, FsmAbortTask, STATE.Idle); //undock Transition(STATE.Idle, MSG.Undock, FsmStartUndock, STATE.Undocking); Transition(STATE.Undocking, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.Undocking, MSG.Abort, FsmAbortTask, STATE.Idle); //write carrier id Transition(STATE.Idle, MSG.WriteCarrierID, FsmStartWriteCarrierId, STATE.WritingCarrierId); Transition(STATE.WritingCarrierId, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.WritingCarrierId, MSG.Abort, FsmAbortTask, STATE.Idle); //read tag data Transition(STATE.Idle, MSG.ReadTagData, FsmStartReadTagData, STATE.ReadingTagData); Transition(STATE.ReadingTagData, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.ReadingTagData, MSG.Abort, FsmAbortTask, STATE.Idle); //write tag data Transition(STATE.Idle, MSG.WriteTagData, FsmStartWriteTagData, STATE.WritingTagData); Transition(STATE.WritingTagData, FSM_MSG.TIMER, FsmMonitorTask, STATE.Idle); Transition(STATE.WritingTagData, MSG.Abort, FsmAbortTask, STATE.Idle); EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); } private bool FsmAbortTask(object[] param) { return true; } private bool FsmReset(object[] param) { LPDevice.LPReset(); if (!_isInit) { PostMsg(MSG.ToInit); return false; } if (_lpDevice.IsError) { EV.PostWarningLog(Module, $"{Module} in error, home to recover"); PostMsg(MSG.ToInit); return false; } return true; } private bool FsmOnError(object[] param) { if (FsmState == (int)STATE.Error) { return false; } AbortRoutine(); if (FsmState == (int)STATE.Init) return false; return true; } private bool FsmExitError(object[] param) { return true; } private bool FsmEnterError(object[] param) { if (OnEnterError != null) OnEnterError(Module); return true; } private bool FsmMonitorTask(object[] param) { Result ret = MonitorRoutine(); if (ret == Result.FAIL) { PostMsg(MSG.Error); return false; } return ret == Result.DONE; } private bool FsmStartHome(object[] param) { Result ret = StartRoutine(_home); if (ret == Result.FAIL || ret == Result.DONE) return false; _isInit = false; return ret == Result.RUN; } 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 FsmToInit(object[] param) { return true; } private bool FsmStartUndock(object[] param) { QueueRoutine.Clear(); QueueRoutine.Enqueue(_unload); _clamp.IsUnloadClamp = true; QueueRoutine.Enqueue(_clamp); Result ret = StartRoutine(); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartDock(object[] param) { //Result ret = StartRoutine(_dock); //if (ret == Result.FAIL || ret == Result.DONE) return false; //return ret == Result.RUN; } private bool FsmStartUnclamp(object[] param) { Result ret = StartRoutine(_unclamp); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartClamp(object[] param) { _clamp.IsUnloadClamp = false; Result ret = StartRoutine(_clamp); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartReadCarrierId(object[] param) { Result ret = StartRoutine(_readCarrierId); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartWriteCarrierId(object[] param) { _writeCarrierId.CarrierIdSetPoint = (string) param[0]; Result ret = StartRoutine(_writeCarrierId); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartReadTagData(object[] param) { Result ret = StartRoutine(_readTag); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartWriteTagData(object[] param) { _writeTag.TagDataSetPoint = (string)param[0]; Result ret = StartRoutine(_writeTag); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartUnload(object[] param) { Result ret = StartRoutine(_unload); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool FsmStartLoad(object[] param) { Result ret = StartRoutine(_load); if (ret == Result.FAIL || ret == Result.DONE) return false; return ret == Result.RUN; } private bool fnOnline(object[] param) { bool online = (bool)param[0]; _efem.SetOnline(ModuleHelper.Converter(Module), online); return true; } public bool IsPrepareTransferReady(ModuleName module, EnumTransferType type, int slot) { if (type == EnumTransferType.Pick) { //需要补充:判断LP 放好了,而且已经map过。 return _efem[module].HasCassette && _efem[module].IsMapped && _efem[module].IsThicknessValid; } else if (type == EnumTransferType.Place) { //需要补充:判断LP 放好了,而且已经map过。 return _efem[module].HasCassette && _efem[module].IsMapped && _efem[module].IsThicknessValid; } return false; } internal bool CheckReadyRunNewJob(ModuleName module) { return _efem[module].HasCassette && _efem[module].IsMapped && _efem[module].IsThicknessValid; } internal bool CheckReadyTransfer(ModuleName module) { return _efem[module].HasCassette && _efem[module].IsMapped && _efem[module].IsThicknessValid; } public override bool Home(out string reason) { throw new NotImplementedException(); } public override void NoteJobStart() { throw new NotImplementedException(); } public override void NoteJobComplete() { throw new NotImplementedException(); } public override bool PrepareTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { throw new NotImplementedException(); } public override bool TransferHandoff(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { throw new NotImplementedException(); } public override bool PostTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { throw new NotImplementedException(); } public override bool CheckReadyForTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { throw new NotImplementedException(); } public override void NoteTransferStart(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { throw new NotImplementedException(); } public override void NoteTransferStop(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { throw new NotImplementedException(); } public override bool CheckReadyForMap(ModuleName robot, Hand blade, out string reason) { throw new NotImplementedException(); } } }