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;
}
}
}