using Aitex.Core.Common; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Event; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.OperationCenter; using Aitex.Sorter.Common; using MECF.Framework.Common.DBCore; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Event; using MECF.Framework.Common.SubstrateTrackings; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.OcrReaders { public abstract class OCRReaderBaseDevice : Entity, IDevice, IEntity { public OCRReaderBaseDevice(string module,string name):base() { Module = module; Name = name; InitializeOCRReader(); } public ModuleName InstalledModule { get; set; } public event Action ActionDone; public event Action OnDeviceAlarmStateChanged; public bool IsBusy = false; public OCRReaderStateEnum DeviceState => (OCRReaderStateEnum)fsm.State; public string CurrentJobName { get; set; } public bool IsReadLaserMark1 { get; set; } public string LaserMark1 { get; set; } = ""; public string LaserMark1Score { get; set; } = ""; public string LaserMark1ReadTime { get; set; } = string.Empty; public string LaserMark2 { get; set; } = ""; public string LaserMark2Score { get; set; } = ""; public string LaserMark2ReadTime { get; set; } = string.Empty; public string CurrentLaserMark { get; set; } = ""; public string CurrentLaserMarkOnWafer { get { if (WaferManager.Instance.CheckHasWafer(ModuleName.Aligner, 0)) return CurrentLaserMark; return ""; } } public virtual string CurrentImageFileName { get; set; } = ""; public DateTime StartReadTime { get; private set; } public int TimeLimitForRead { get; set; } = 30; public List JobFileList { get; set; } public bool ReadOK { get; set; } public string AlarmWIDReadTimeout { get => Name.ToString() + "WIDReadTimeout"; } public string AlarmWIDLostCommunication { get => Name.ToString() + "WIDLostCommunication"; } public string AlarmWIDLoadJobFail { get => Name.ToString() + "WIDLoadJobFail"; } public string LaserMark1ReadResult { get; set; } public string LaserMark2ReadResult { get; set; } public virtual bool IsReady() { if (DeviceState != OCRReaderStateEnum.Idle) return false; if (IsBusy) return false; return true; } private void InitializeOCRReader() { BuildTransitionTable(); SubscribeDataVariable(); SubscribeOperation(); SubscribeDeviceOperation(); Running = true; } private void SubscribeDeviceOperation() { DEVICE.Register(string.Format("{0}.{1}", Name, "ReadWaferID"),//DeviceOperationName.ReadWaferID), (out string reason, int time, object[] param) => { var bLaser = bool.Parse((string)param[0]); var jobName = (string)param[1]; var ret = ReadWaferID(jobName, bLaser?0:1); if (ret) { reason = string.Format("{0}", Name, "Read Laser Mark."); return true; } else reason = string.Format("{0}", Name, "Can't read Laser Mark."); return false; }); DEVICE.Register(string.Format("{0}.{1}", Name, "ReadLM1"),//DeviceOperationName.ReadWaferID), (out string reason, int time, object[] param) => { var jobName = (string)param[0]; var ret = ReadWaferID(jobName, 0); if (ret) { reason = string.Format("{0}", Name, "Read Laser Mark."); return true; } else reason = string.Format("{0}", Name, "Can't read Laser Mark."); return false; }); DEVICE.Register(string.Format("{0}.{1}", Name, "ReadLM2"),//DeviceOperationName.ReadWaferID), (out string reason, int time, object[] param) => { reason = ""; var jobName = (string)param[0]; var ret = ReadWaferID(jobName,1); if (ret) { reason = string.Format("{0}", Name, "Read Laser Mark."); return true; } else reason = string.Format("{0}", Name, "Can't read Laser Mark."); return false; }); DEVICE.Register($"{Name}.RefreshJobList", (out string reason, int time, object[] param) => { reason = ""; return CheckToPostMessage((int)OCRReaderMsg.ReadParameter, new object[] { "JobList" }); }); DEVICE.Register($"{Name}.Reset", (out string reason, int time, object[] param) => { reason = ""; return CheckToPostMessage((int)OCRReaderMsg.Reset, new object[] { "Reset" }); }); DEVICE.Register($"{Name}.ManualSetLaserMark", (out string reason, int time, object[] param) => { reason = ""; CurrentLaserMark = param[0].ToString(); var wafer = WaferManager.Instance.GetWafer(InstalledModule, 0); if (!wafer.IsEmpty) { wafer.LaserMarker = CurrentLaserMark; Guid guid = Guid.NewGuid(); OCRDataRecorder.OcrReadComplete(guid.ToString(), wafer.WaferID, wafer.OriginStation.ToString(), wafer.OriginCarrierID ?? "", wafer.OriginSlot.ToString(), "0", "0", true, CurrentLaserMark, "0", "0"); } return true; }); } private void SubscribeOperation() { OP.Subscribe($"{Name}.ReadWaferID", (string cmd, object[] param) => { var bLaser = bool.Parse(param[0].ToString()); var jobName = (string)param[1]; var ret = ReadWaferID(jobName, bLaser ? 0 : 1); if (!ret) { EV.PostWarningLog(Module, $"{Name} can not read laser mark."); return false; } EV.PostInfoLog(Module, $"{Name} start read laser mark"); return true; }); OP.Subscribe($"{Name}.ReadLM1", (string cmd, object[] param) => { var jobName = (string)param[0]; var ret = ReadWaferID(jobName, 0); if (ret) { return true; } return false; }); OP.Subscribe($"{Name}.RefreshJobList", (string cmd, object[] param) => { return CheckToPostMessage((int)OCRReaderMsg.ReadParameter, new object[] { "JobList" }); }); OP.Subscribe($"{Name}.Reset", (out string reason, int time, object[] param) => { reason = ""; return CheckToPostMessage((int)OCRReaderMsg.Reset, new object[] { "Reset" }); }); } private void SubscribeDataVariable() { DATA.Subscribe(Name, "WIDReaderState", () => DeviceState.ToString()); DATA.Subscribe(Name, "WIDReaderBusy", () => (DeviceState != OCRReaderStateEnum.Idle && DeviceState != OCRReaderStateEnum.Init)); DATA.Subscribe(Name, "WRIDReaderState", () => DeviceState.ToString()); DATA.Subscribe(Name, "WRIDReaderBusy", () => (DeviceState != OCRReaderStateEnum.Idle && DeviceState != OCRReaderStateEnum.Init)); DATA.Subscribe(Name, "LaserMaker1", () => LaserMark1); DATA.Subscribe(Name, "LaserMaker2", () => LaserMark2); DATA.Subscribe(Name, "LaserMark1Result", () => LaserMark1ReadResult); DATA.Subscribe(Name, "LaserMark2Result", () => LaserMark2ReadResult); DATA.Subscribe(Name, "JobFileList", () => JobFileList); DATA.Subscribe(Name, "CurrentLaserMark", () => CurrentLaserMarkOnWafer); DATA.Subscribe(Name, "CurrentImageFileName", () => CurrentImageFileName); DATA.Subscribe(Name, "CurrentWaferID", () => WaferManager.Instance.GetWafer(InstalledModule, 0).WaferID); EV.Subscribe(new EventItem("Alarm", AlarmWIDLoadJobFail, $"{Name} WID Reader load job failed.", EventLevel.Alarm, EventType.EventUI_Notify)); EV.Subscribe(new EventItem("Alarm", AlarmWIDLostCommunication, $"{Name} WID Reader lost communication.", EventLevel.Alarm, EventType.EventUI_Notify)); EV.Subscribe(new EventItem("Alarm", AlarmWIDReadTimeout, $"{Name} WID Reader read laser mark timeout.", EventLevel.Alarm, EventType.EventUI_Notify)); } private void BuildTransitionTable() { fsm = new StateMachine(Module + Name + ".OCRReaderReaderStateMachine", (int)OCRReaderStateEnum.Init, 50); AnyStateTransition(OCRReaderMsg.Error, fError, OCRReaderStateEnum.Error); AnyStateTransition(OCRReaderMsg.Reset, fStartReset, OCRReaderStateEnum.Resetting); Transition(OCRReaderStateEnum.Resetting, OCRReaderMsg.ActionDone, fResetComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Resetting, OCRReaderMsg.ResetComplete, fResetComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Resetting, FSM_MSG.TIMER, fMonitorReset, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Init, OCRReaderMsg.StartInit, fStartInit, OCRReaderStateEnum.Initializing); Transition(OCRReaderStateEnum.Initializing, OCRReaderMsg.InitComplete, fInitComplete, OCRReaderStateEnum.Initializing); Transition(OCRReaderStateEnum.Initializing, OCRReaderMsg.ActionDone, fInitComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Initializing, FSM_MSG.TIMER, fMonitorInit, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Error, OCRReaderMsg.Clear, fStartClear, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Idle, OCRReaderMsg.SetParameter, fStartSetParameter, OCRReaderStateEnum.SetParameter); Transition(OCRReaderStateEnum.SetParameter, OCRReaderMsg.SetComplete, fSetParameterComplete, OCRReaderStateEnum.SetParameter); Transition(OCRReaderStateEnum.SetParameter, OCRReaderMsg.ActionDone, fSetParameterComplete, OCRReaderStateEnum.SetParameter); Transition(OCRReaderStateEnum.Idle, OCRReaderMsg.ReadParameter, fStartReadParameter, OCRReaderStateEnum.ReadParameter); Transition(OCRReaderStateEnum.ReadParameter, OCRReaderMsg.ReadParaComplete, fReadParameterComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.ReadParameter, OCRReaderMsg.ActionDone, fReadParameterComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.ReadParameter, FSM_MSG.TIMER, fMonitorReadParameter, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Idle, OCRReaderMsg.ReadWaferID, fStartReadWaferID, OCRReaderStateEnum.ReadWaferID); Transition(OCRReaderStateEnum.ReadWaferID, OCRReaderMsg.ReadCarrierIDComplete, fReadWaferIDComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.ReadWaferID, OCRReaderMsg.ActionDone, fReadWaferIDComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.ReadWaferID, FSM_MSG.TIMER, fMonitorReading, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.Idle, OCRReaderMsg.SavePicture, fStartSavePicture, OCRReaderStateEnum.SavingPicture); Transition(OCRReaderStateEnum.SavingPicture, OCRReaderMsg.SavePictureComplete, fSavePictureComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.SavingPicture, OCRReaderMsg.ActionDone, fSavePictureComplete, OCRReaderStateEnum.Idle); Transition(OCRReaderStateEnum.SavingPicture, FSM_MSG.TIMER, fMonitorSavingPicture, OCRReaderStateEnum.Idle); } protected virtual void OnWaferIDRead(string wid, string score, string readtime) { EV.PostInfoLog(Name, $"{Name} read laser mark successfully,ID:{wid},score:{score},read time:{readtime}."); CheckToPostMessage((int)OCRReaderMsg.ReadCarrierIDComplete, null); } protected virtual bool fMonitorSavingPicture(object[] param) { return false; } protected virtual bool fMonitorReading(object[] param) { if (DateTime.Now - StartReadTime > TimeSpan.FromSeconds((double)TimeLimitForRead)) { OnError(AlarmWIDReadTimeout); } return false; } protected virtual bool fMonitorReadParameter(object[] param) { return false; } protected virtual bool fSavePictureComplete(object[] param) { return true; ; } protected abstract bool fStartSavePicture(object[] param); protected virtual bool fError(object[] param) { return true; } protected abstract bool fStartReset(object[] param); protected virtual bool fResetComplete(object[] param) { return true; } protected virtual bool fMonitorReset(object[] param) { return true; } protected abstract bool fStartInit(object[] param); protected virtual bool fInitComplete(object[] param) { return true; } protected virtual bool fMonitorInit(object[] param) { return true; } protected virtual bool fStartClear(object[] param) { return true; } protected abstract bool fStartSetParameter(object[] param); protected virtual bool fSetParameterComplete(object[] param) { return true; } protected abstract bool fStartReadParameter(object[] param); protected virtual bool fReadParameterComplete(object[] param) { return true; } protected abstract bool fStartReadWaferID(object[] param); protected virtual bool fReadWaferIDComplete(object[] param) { return true; } public virtual bool ReadWaferID(string jobname,int lasermarkindex=0) { StartReadTime = DateTime.Now; CurrentJobName = jobname; return CheckToPostMessage((int)OCRReaderMsg.ReadWaferID, new object[] { jobname, lasermarkindex }); } public abstract string[] GetJobFileList(); public bool SavePicture(string path = "",string filename = "") { return CheckToPostMessage((int)OCRReaderMsg.SavePicture, new object[] { "SavePicture", path, filename }); } protected override bool Init() { return base.Init(); } public virtual void Monitor() { return; } public virtual void Reset() { } public virtual bool OnActionDone(object[] param) { IsBusy = false; CheckToPostMessage((int)OCRReaderMsg.ActionDone, new object[] { "ActionDone" }); if (ActionDone != null) ActionDone(true); return true; } public void OnActionDone(bool result) { if (ActionDone != null) ActionDone(result); } public virtual bool OnError(string errorMsg) { EV.PostAlarmLog(Module, $"{Name} occured error:{errorMsg}"); return CheckToPostMessage((int)OCRReaderMsg.Error, null); } public bool CheckToPostMessage(int msg, params object[] args) { if (!fsm.FindTransition(fsm.State, msg)) { EV.PostWarningLog(Name, $"{Name} is in { (OCRReaderStateEnum)fsm.State} state,can not do {(OCRReaderMsg)msg}"); return false; } if ((OCRReaderMsg)msg == OCRReaderMsg.Reset || (OCRReaderMsg)msg == OCRReaderMsg.ReadParameter || (OCRReaderMsg)msg == OCRReaderMsg.ReadWaferID || (OCRReaderMsg)msg == OCRReaderMsg.SavePicture || (OCRReaderMsg)msg == OCRReaderMsg.SetParameter || (OCRReaderMsg)msg == OCRReaderMsg.StartInit) IsBusy = true; else IsBusy = 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, (OCRReaderStateEnum)fsm.State, (OCRReaderMsg)msg); return false; } reason = ""; return true; } public virtual bool Error { get; } public string Module { get ; set ; } public string Name { get; set ; } public bool HasAlarm { get; set; } } public enum OCRReaderStateEnum { Undefined = 0, Init, Initializing, Idle, SetParameter, ReadParameter, ReadWaferID, SavingPicture, Error, Resetting, } public enum OCRReaderMsg { Reset, ResetComplete, Clear, StartInit, InitComplete, SetParameter, SetComplete, ReadParameter, ReadParaComplete, ReadWaferID, ReadCarrierIDComplete, SavePicture, SavePictureComplete, ActionDone, Error, } }