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.Log; using Aitex.Core.RT.OperationCenter; 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.Device.Bases; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Schedulers; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FurnaceRT.Equipments.Stockers { public partial class StockerModule : StockerModuleBase { public enum STATE { NotInstall, NotConnected, Idle, Error, InTransfer, } public enum MSG { Home, Disconnected, Connected, Reset, Abort, Error, InTransfer, TransferComplete, } 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 false; } } public bool IsFoupPresent { get { if (SC.GetValue("System.IsSimulatorMode")) return CarrierManager.Instance.HasCarrier(Module); return _diStationCassettePresent == null ? false : _diStationCassettePresent.Value; } } public bool IsCassetteHasWafer { get; set; } public StockerModule(ModuleName module) : base(SC.GetValue("System.CassetteSlotCount")) { Name = module.ToString(); Module = module.ToString(); if (!SC.ContainsItem($"System.Stocker.{Module}WaferType")) { WaferType = "None"; } else { WaferType = SC.GetStringValue($"System.Stocker.{Module}WaferType"); } IsOnline = true; SetDisplayName(); } public override bool Initialize() { InitRoutine(); InitDevice(); InitFsm(); InitOp(); InitData(); Singleton.Instance.OnAlarmEvent += Instance_OnAlarmEvent; return base.Initialize(); } private void Instance_OnAlarmEvent(EventItem item) { if (item != null && item.Level == EventLevel.Alarm && (item.Source == Name || item.Source == Module)) { DEVICE.GetDevice("System.SignalTower")?.Reset(); LOG.Write($"{item.Source} {item.EventEnum} {item.Description}\n"); PostMsg(MSG.Error); } } private void InitRoutine() { } private void InitData() { DATA.Subscribe($"{Module}.Status", () => StringFsmStatus); DATA.Subscribe($"{Module}.IsOnline", () => IsOnline); DATA.Subscribe($"{Module}.IsError", () => IsError); DATA.Subscribe(Name, "FoupPresent", () => IsFoupPresent); DATA.Subscribe(Name, "CassetteHasWafer", () => IsCassetteHasWafer); DATA.Subscribe(Name, "LotID", () => CarrierManager.Instance.CheckHasCarrier(Module, 0) ? CarrierManager.Instance.GetCarrier(Module, 0).LotId : ""); DATA.Subscribe(Name, "CarrierType", () => CarrierManager.Instance.CheckHasCarrier(Module, 0) ? CarrierManager.Instance.GetCarrier(Module, 0).CarrierType : CarrierType.None); } private void InitOp() { OP.Subscribe($"{Module}.Home", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Home)); OP.Subscribe($"{Module}.Reset", (string cmd, object[] args) => CheckToPostMessage((int)MSG.Reset)); 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) CheckToPostMessage((int)MSG.Reset); } 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; } } } return true; }); } private void InitFsm() { EnumLoop.ForEach((item) => { MapState((int)item, item.ToString()); }); EnumLoop.ForEach((item) => { MapMessage((int)item, item.ToString()); }); EnableFsm(1000, IsInstalled ? STATE.Idle : STATE.NotInstall); Transition(STATE.Idle, MSG.Disconnected, null, STATE.NotConnected); Transition(STATE.Idle, MSG.InTransfer, null, STATE.InTransfer); Transition(STATE.InTransfer, MSG.TransferComplete, null, STATE.Idle); Transition(STATE.InTransfer, MSG.Abort, null, STATE.Idle); Transition(STATE.NotConnected, MSG.Connected, null, STATE.Idle); } #region Service Functions public override bool Home(out string reason) { reason = string.Empty; return true; } public override void Reset() { base.Reset(); } public override bool PrepareTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { 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) { reason = string.Empty; return true; } public override bool CheckReadyForTransfer(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType, out string reason) { reason = string.Empty; return true; } public override void NoteTransferStart(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { CheckToPostMessage(MSG.InTransfer); } public override void NoteTransferStop(ModuleName robot, Hand blade, int targetSlot, EnumTransferType transferType) { if (FsmState == (int)STATE.InTransfer) CheckToPostMessage(MSG.TransferComplete); } #endregion } }