using Aitex.Core.RT.Log; using Aitex.Core.RT.Routine; using MECF.Framework.Common.RecipeCenter; using MECF.Framework.Common.Routine; using CyberX8_Core; using CyberX8_RT.Devices.AXIS; using CyberX8_RT.Devices.SRD; using System; using System.Collections.Generic; using MECF.Framework.Common.Utilities; using MECF.Framework.Common.CommonData; using MECF.Framework.Common.CommonData.SRD; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Device; using CyberX8_RT.Devices.Facilities; using Aitex.Core.Util; using MECF.Framework.Common.Persistent.SRD; namespace CyberX8_RT.Modules.SRD { public class SRDProcessRecipeRoutine : RoutineBase, IRoutine { #region 常量 private const int LOTTRACK_TIME = 1000; #endregion private enum SRDProcessState { Ready, StartLoad, Loading, StartRunRecipe, RunReciping, StartUnload, Unloading, CycleEnd, End } #region 内部变量 /// /// 次数 /// private int _cycleCount = 0; /// /// Rotation Axis /// private JetAxisBase _rotationAxis; /// /// Arm Axis /// //private JetAxisBase _armAxis; /// /// SRD Recipe /// private SrdRecipe _srdRecipe; /// /// 设备对象 /// private SrdCommonDevice _srdCommonDevice; /// /// Run Recipe Routine /// private SRDRunRecipeRoutine _runRecipeRoutine; /// /// Unloader Routine /// private SRDUnloaderRoutine _unloaderRoutine; /// /// Loader Routine /// private SRDLoaderRoutine _loaderRoutine; /// /// lock track time /// private DateTime _lotTackTime = DateTime.Now; /// /// LotTrack数据 /// private List _datas = new List(); /// /// LotTrack文件头数据 /// private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData(); /// /// Facilities /// private SystemFacilities _facilities; /// /// Manual模式 /// private bool _isManual = false; #endregion #region 属性 /// /// 当前子状态机 /// public string CurrentStateMachine { get { return GetCurrentStateMachine(); } } /// /// 当前cycle次数 /// public int AchievedCycle { get { return Runner.LoopCounter; } } /// /// 是否正在用水 /// public bool IsUsingWater { get { return _runRecipeRoutine.IsUsingWater; } } /// /// LotTrack数据 /// public List SRDLotTrackDatas { get { return _datas; } } /// /// LotTrack文件头数据 /// public LotTrackFileHeaderCommonData SRDLotTrackHeaderDatas { get { return _header; } } #endregion /// /// 构造函数 /// /// public SRDProcessRecipeRoutine(string module, JetAxisBase rotationAxis, JetAxisBase armAxis, SrdCommonDevice srdCommon) : base(module) { _rotationAxis = rotationAxis; //_armAxis = armAxis; _srdCommonDevice = srdCommon; _runRecipeRoutine = new SRDRunRecipeRoutine(module); _unloaderRoutine= new SRDUnloaderRoutine(module); _loaderRoutine = new SRDLoaderRoutine(module); } /// /// 取消 /// public void Abort() { if(_unloaderRoutine.Monitor() == RState.Running) { _unloaderRoutine.Abort(); } if (_runRecipeRoutine.Monitor() == RState.Running) { _runRecipeRoutine.Abort(); } if (_loaderRoutine.Monitor() == RState.Running) { _loaderRoutine.Abort(); } Runner.Stop("Manual Abort"); if (_srdCommonDevice != null) { _srdCommonDevice.EnterErrorOperation(); } //停电机 if (_rotationAxis != null && _rotationAxis.IsRun) _rotationAxis.StopPositionOperation(); } /// /// 监控 /// /// /// public RState Monitor() { LottrackRecord(); Runner.LoopStart(SRDProcessState.Ready, "Process Recipe Start", _cycleCount, NullFun, _delay_1ms) .LoopRunIf(SRDProcessState.StartLoad, !_isManual,() => { return StartLoad(); }, _delay_1ms) .LoopRunIfWithStopStatus(SRDProcessState.Loading, !_isManual, CheckLoaderEndStatus, CheckLoaderErrorStatus) .LoopRun(SRDProcessState.StartRunRecipe, () => { return StartRunRecipe(); }, _delay_1ms) .LoopRunWithStopStatus(SRDProcessState.RunReciping, CheckRunRecipeEndStatus, CheckRunRecipeErrorStatus) .LoopRunIf(SRDProcessState.StartUnload, !_isManual, () => { return StartUnload(); }, _delay_1ms) .LoopRunIfWithStopStatus(SRDProcessState.Unloading, !_isManual, CheckUnloaderEndStatus, CheckUnloaderErrorStatus) .LoopEnd(SRDProcessState.CycleEnd, NullFun, _delay_1ms) .End(SRDProcessState.End, NullFun, _delay_1ms); return Runner.Status; } /// /// 启动 /// /// /// /// public RState Start(params object[] objects) { _srdRecipe = objects[0] as SrdRecipe; if (_srdRecipe == null) { LOG.WriteLog(eEvent.ERR_SRD, Module.ToString(), " recipe is null"); return RState.Failed; } _cycleCount = (int)objects[1]; if (_cycleCount == 0) { return RState.End; } _isManual = false; SRDPersistentValue srdPersistentValue = SRDPersistentManager.Instance.GetModulePersistentValue(Module); if(srdPersistentValue.OperatingMode.Equals("Manual")) _isManual = true; _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); _header.Recipe = $"{_srdRecipe.Ppid}.srd.rcp"; if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID"); _facilities = DEVICE.GetDevice("System.Facilities"); if (_facilities == null) { LOG.WriteLog(eEvent.ERR_SRD, Module, "Facility is null"); return RState.Failed; } _datas.Clear(); _lotTackTime = DateTime.Now; SRDEntity srdEntity = Singleton.Instance.GetModule(Module); if (srdEntity.IsManual && !srdEntity.IsLoaded) { NotifyError(eEvent.ERR_SRD, $"{Module} is not Loaded, can't run recipe", 0); return RState.Failed; } return Runner.Start(Module, "Process Recipe"); } #region Loader /// /// 启动LoaderRoutine /// /// /// private bool StartLoad() { bool result = _loaderRoutine.Start() == RState.Running; if (!result) { NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0); } return result; } /// /// 检验LoaderRoutine完成情况 /// /// private bool CheckLoaderEndStatus() { return CommonFunction.CheckRoutineEndState(_loaderRoutine); } /// /// 检验LoaderRoutine错误情况 /// /// private bool CheckLoaderErrorStatus() { bool result = CommonFunction.CheckRoutineStopState(_loaderRoutine); if (result) { AddLotTrackData(); if (_srdCommonDevice != null) { _srdCommonDevice.EnterErrorOperation(); } NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0); } return result; } #endregion #region RunRecipe /// /// 启动状态机 /// /// /// private bool StartRunRecipe() { bool result = _runRecipeRoutine.Start(_srdRecipe)==RState.Running; if (result) { LOG.WriteLog(eEvent.INFO_SRD, Module.ToString(), $"Start Run Recipe, recipe[{_srdRecipe.Ppid}] times[{_cycleCount + 1}]"); } else { NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0); } return result; } /// /// 检验RunRecipeRoutine完成情况 /// /// private bool CheckRunRecipeEndStatus() { return CommonFunction.CheckRoutineEndState(_runRecipeRoutine); } /// /// 检验RunRecipeRoutine错误情况 /// /// private bool CheckRunRecipeErrorStatus() { bool result = CommonFunction.CheckRoutineStopState(_runRecipeRoutine); if (result) { AddLotTrackData(); if (_srdCommonDevice != null) { _srdCommonDevice.EnterErrorOperation(); } NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0); } return result; } #endregion #region Unloader /// /// 启动UnloaderRoutine /// /// /// private bool StartUnload() { bool result= _unloaderRoutine.Start(false) == RState.Running; if (!result) { NotifyError(eEvent.ERR_SRD,_unloaderRoutine.ErrorMsg, 0); } return result; } /// /// 检验UnloaderRoutine完成情况 /// /// private bool CheckUnloaderEndStatus() { return CommonFunction.CheckRoutineEndState(_unloaderRoutine); } /// /// 检验UnloaderRoutine错误情况 /// /// private bool CheckUnloaderErrorStatus() { bool result= CommonFunction.CheckRoutineStopState(_unloaderRoutine); if (result) { AddLotTrackData(); NotifyError(eEvent.ERR_SRD, _unloaderRoutine.ErrorMsg, 0); } return result; } #endregion /// /// 获取当前子状态机 /// private string GetCurrentStateMachine() { string result; if (Runner.CurrentStep.ToString().Contains("Loading")) { result = _loaderRoutine.CurrentStep; } else if(Runner.CurrentStep.ToString().Contains("RunReciping")) { result = _runRecipeRoutine.CurrentStep; } else if(Runner.CurrentStep.ToString().Contains("Unloading")) { result = _unloaderRoutine.CurrentStep; } else { result = Runner.CurrentStep.ToString(); } return result; } /// /// 记录Lottrack /// private void LottrackRecord() { //记录Lottrack if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME) { AddLotTrackData(); _lotTackTime = DateTime.Now; } } /// /// 获取Lot Track数据 /// /// private void AddLotTrackData() { SRDLotTrackData data = new SRDLotTrackData(); data.TimeStamp = DateTime.Now; data.StateMachine = GetCurrentStateMachine(); data.WaterPressure = _srdCommonDevice.CommonData.WaterPressure; data.ChuckVacuumOn = _srdCommonDevice.CommonData.ChuckVacuum; data.ChuckVacuumPressure = _srdCommonDevice.CommonData.VacuumValue; //data.SpinTorque = _rotationAxis.MotionData.ActualTorque; data.RotationSpeed = _rotationAxis.MotionData.ActualVelocity; data.WaterOn = _srdCommonDevice.CommonData.WaterOn; data.WaterFlow = _srdCommonDevice.CommonData.WaterFlow; data.LoaderDIEnable = _facilities.LoaderDiEnable; _datas.Add(data); } /// /// 重试 /// /// public RState Retry(int step) { List preStepIds = new List(); return Runner.Retry(SRDProcessState.Ready, preStepIds, Module, "RunRecipe Retry"); } /// /// 检验前面完成状态 /// /// public bool CheckCompleteCondition(int index) { //if (_armAxis.IsRun) //{ // NotifyError(eEvent.ERR_SRD, "Arm axis is run", 0); // return false; //} //if (!_armAxis.IsHomed) //{ // NotifyError(eEvent.ERR_SRD, "Arm axis is not homed", 0); // return false; //} if (_rotationAxis.IsRun) { NotifyError(eEvent.ERR_SRD, "Rotation axis is run", 0); return false; } if (!_rotationAxis.IsHomed) { NotifyError(eEvent.ERR_SRD, "Rotation axis is not homed", 0); return false; } if (!_srdCommonDevice.CommonData.ChuckVacuum) { NotifyError(eEvent.ERR_SRD, "Vacuum is not released", 0); return false; } if (!_srdCommonDevice.CommonData.DoorOpened) { NotifyError(eEvent.ERR_SRD, "Door is not opened", 0); return false; } return true; } } }