using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Venus_Core;
using Venus_RT.Devices;
using Venus_RT.Devices.PreAligner;
using Venus_RT.Devices.TM;
using Venus_RT.Devices.VCE;
using Venus_RT.Modules.PMs;
using static Mono.Security.X509.X520;
namespace Venus_RT.Modules.TM.VenusEntity
{
public class SETMEntity : Entity, IModuleEntity
{
public enum STATE
{
Unknown,
Init,
Initializing,
InitializingRB,
Idle,
Error,
Pumping,
Venting,
Purging,
Leakchecking,
Picking,
Placing,
Swaping,
PMPicking,
PMPlacing,
PMSwaping,
Aligning,
Mapping,
Extending,
Retracting,
Swapping,
Gotoing,
ControllingPressure,
}
public enum MSG
{
Home,
RobotHome,
Online,
Offline,
Pump,
Vent,
Purge,
CyclePurge,
LeakCheck,
Pick,
Place,
Swap,
DoublePick,
DoublePlace,
DoubleSwap,
PMPick,
PMPlace,
PMSwap,
Extend,
Retract,
TMCycle,
ControlPressure,
Error,
Abort,
AbortControlPressure,
Align,
CreateJob,
StartJob,
Goto,
}
#region 公开变量
public ModuleName Module => _module;
public bool IsIdle
{
get { return fsm.State == (int)STATE.Idle; }
}
public bool IsError
{
get { return fsm.State == (int)STATE.Error; }
}
public bool IsInit
{
get { return fsm.State == (int)STATE.Unknown || fsm.State == (int)STATE.Init; }
}
public bool IsBusy
{
get { return !IsInit && !IsError && !IsIdle; }
}
public RState RobotStatus
{
get
{
if (_robot.Status != RState.Running)
{
if (_robotWatch.ElapsedMilliseconds < 100)
return RState.Running;
else
return _robot.Status;
}
else
return RState.Running;
}
}
///
/// VCE部分的内容从变量转化为查询方法
///
public bool VCEIsATM(ModuleName VCEName)
{
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
return _tm.IsVCEATM;
case ConfigType.VenusDE:
return VCEName == ModuleName.VCEA ? _tm.IsVCEAATM: _tm.IsVCEBATM;
default:
return false;
}
}
public bool TMIsATM => _tm.IsTMATM;
public bool TMIsVAC => _tm.IsTMVAC;
public bool VCEIsVAC(ModuleName VCEName)
{
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
return _tm.IsVCEVAC;
case ConfigType.VenusDE:
return VCEName == ModuleName.VCEA ? _tm.IsVCEAVAC : _tm.IsVCEBVAC;
default:
return false;
}
}
public bool IsPMASlitDoorClosed => _tm.PMASlitDoorClosed;
public bool IsPMBSlitDoorClosed => _tm.PMBSlitDoorClosed;
public bool IsPMCSlitDoorClosed => _tm.PMCSlitDoorClosed;
public bool IsPMDSlitDoorClosed => _tm.PMDSlitDoorClosed;
public bool IsVCESlitDoorClosed(ModuleName VCEName)
{
return _tm.VCESlitDoorClosed(VCEName);
}
public bool IsPMASlitDoorOpen => _tm.CheckSlitValveOpen(ModuleName.PMA);
public bool IsPMBSlitDoorOpen => _tm.CheckSlitValveOpen(ModuleName.PMB);
public bool IsPMCSlitDoorOpen => _tm.CheckSlitValveOpen(ModuleName.PMC);
public bool IsPMDSlitDoorOpen => _tm.CheckSlitValveOpen(ModuleName.PMD);
//public bool IsVCESlitDoorOpen => _tm.CheckSlitValveOpen(ModuleName.VCE1);
public double VCEPressure(ModuleName VCEName)
{
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
return _tm.VCEPressure;
case ConfigType.VenusDE:
return VCEName == ModuleName.VCEA ? _tm.VCEAPressure: _tm.VCEBPressure;
default:
return 0;
}
}
public bool VCECanMove(ModuleName VCEName)
{
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
if(_tm.VCESlitDoorClosed(VCEName))
return true;
else
return _tm.RobotNotExtendVCE;
case ConfigType.VenusDE:
if (_tm.VCESlitDoorClosed(VCEName))
return true;
else
return VCEName == ModuleName.VCEA ? _tm.RobotNotExtendVCEA : _tm.RobotNotExtendVCEB;
default:
return false;
}
}
private bool _IsOnline;
public bool IsOnline => _IsOnline;
//public bool IsTMVac => _tm.IsTMVac;
//public bool IsTMATM => _tm.IsTMATM;
#endregion
#region 私有变量
private readonly TMBase _tm;
private readonly ITransferRobot _robot;
private readonly IPreAlign _vpa;
private readonly SEMFHomeRoutine _homeRoutine;
private readonly SEMFPickRoutine _pickRoutine;
private readonly SEMFPlaceRoutine _placeRoutine;
private readonly SEMFVentRoutine _ventRoutine;
private readonly SEMFPumpRoutine _pumpRoutine;
private readonly SEMFLeakCheckRoutine _leakcheckRoutine;
private readonly SEMFPMPickRoutine _pickpmRoutine;
private readonly SEMFPMPlaceRoutine _placepmRoutine;
private readonly SEMFSwapRoutine _swaproutine;
private readonly SEMFPMSwapRoutine _pmswaproutine;
private readonly SEMFPMRetractRoutine _pmRetractRoutine;
private readonly SEMFPMExtendRoutine _pmExtendRoutine;
//private readonly
//private bool startControlPressureFlag = true;
//private bool stopControlPressureFlag = false;
private Stopwatch _robotWatch = new Stopwatch();
private R_TRIG _robotIdleTrigger = new R_TRIG();
//private int _controlPressureCheckPoint = 100;
//private int _controlPressureSetPoint = 90;
//private int _controlFlowSetPoint = 90;
private ModuleName _module;
#endregion
public SETMEntity(ModuleName module)
{
_module = module;
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
_tm = DEVICE.GetDevice(module.ToString());
break;
case ConfigType.VenusDE:
_tm = DEVICE.GetDevice(module.ToString());
break;
}
if (ModuleHelper.IsInstalled(ModuleName.TMRobot))
_robot = new HongHuVR(_module);
_vpa = new HongHuVPA(_module);
_robotWatch = new Stopwatch();
_homeRoutine = new SEMFHomeRoutine(_tm,_robot, _vpa, module);
_pickRoutine = new SEMFPickRoutine(_tm,_robot, _vpa, module);
_placeRoutine = new SEMFPlaceRoutine(_tm, _robot, _vpa, module);
_pumpRoutine = new SEMFPumpRoutine(_tm, module);
_ventRoutine = new SEMFVentRoutine(_tm, module);
_leakcheckRoutine = new SEMFLeakCheckRoutine(_tm, module);
_pickpmRoutine = new SEMFPMPickRoutine(_tm, _robot, module);
_placepmRoutine = new SEMFPMPlaceRoutine(_tm, _robot, module);
_swaproutine = new SEMFSwapRoutine(_tm, _robot, module);
_pmswaproutine = new SEMFPMSwapRoutine(_tm, _robot, module);
_pmExtendRoutine = new SEMFPMExtendRoutine(_tm, _robot, _vpa, module);
_pmRetractRoutine = new SEMFPMRetractRoutine(_tm, _robot, _vpa, module);
InitFsmMap();
}
protected override bool Init()
{
DATA.Subscribe($"{_module}.FsmState", () => ((STATE)fsm.State).ToString());
DATA.Subscribe($"{_module}.RobotMoveAction", () => _robot.TMRobotMoveInfo, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{_module}.RobotMoveAction.ArmTarget", () => _robot.TMRobotMoveInfo.ArmTarget.ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{_module}.RobotMoveAction.BladeTarget", () => _robot.TMRobotMoveInfo.BladeTarget, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{_module}.RobotMoveAction.RobotAction", () => _robot.TMRobotMoveInfo.Action.ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{_module}.IsOnline", () => IsOnline, SubscriptionAttribute.FLAG.IgnoreSaveDB);
DATA.Subscribe($"{_module}.IsOffline", () => !IsOnline, SubscriptionAttribute.FLAG.IgnoreSaveDB);
OP.Subscribe($"{_module}.Goto", (cmd, args) => RobotGoto(args));
OP.Subscribe($"{_module}.Home", (cmd, args) => { PostMsg(MSG.Home, args); return true; });
OP.Subscribe($"{_module}.Abort", (cmd, args) => { PostMsg(MSG.Abort); return true; });
OP.Subscribe($"{_module}.Pick", (cmd, args) => { PostMsg(MSG.Pick, args); return true; });
OP.Subscribe($"{_module}.Place", (cmd, args) => { PostMsg(MSG.Place, args); return true; });
OP.Subscribe($"{_module}.Extend", (cmd, args) => { PostMsg(MSG.Extend, args); return true; });
OP.Subscribe($"{_module}.Retract", (cmd, args) => { PostMsg(MSG.Retract, args); return true; });
OP.Subscribe($"{_module}.PMPick", (cmd, args) => { PostMsg(MSG.PMPick, args); return true; });
OP.Subscribe($"{_module}.PMPlace", (cmd, args) => { PostMsg(MSG.PMPlace, args); return true; });
OP.Subscribe($"{_module}.PumpDown", (cmd, args) => { PostMsg(MSG.Pump); return true; });
OP.Subscribe($"{_module}.Vent", (cmd, args) => { PostMsg(MSG.Vent); return true; });
OP.Subscribe($"{_module}.LeakCheck", (cmd, args) => { PostMsg(MSG.LeakCheck); return true; });
OP.Subscribe($"{_module}.Online", (cmd, args) =>
{
if (IsIdle)
_IsOnline = true;
else
LOG.Write(eEvent.WARN_TM,_module,"cannot Set Online as TM is not idle");
return true;
});
OP.Subscribe($"{_module}.Offline", (cmd, args) =>
{
_IsOnline = false;
return true;
});
return true;
}
private void InitFsmMap()
{
fsm = new StateMachine($"{_module}", (int)STATE.Init, 50);
AnyStateTransition(MSG.Error, fnError, STATE.Error);
AnyStateTransition(MSG.Online, fnOnline, FSM_STATE.SAME);
AnyStateTransition(MSG.Offline, fnOffline, FSM_STATE.SAME);
AnyStateTransition(MSG.Home, fnHome, STATE.Initializing);
//Home
Transition(STATE.Initializing, FSM_MSG.TIMER, fnHomeTimeout, STATE.Idle);
Transition(STATE.Initializing, MSG.Abort, fnAbortHome, STATE.Init);
//Pick
Transition(STATE.Idle, MSG.Pick, fnStartPick, STATE.Picking);
Transition(STATE.Picking, FSM_MSG.TIMER, fnPickTimeout, STATE.Idle);
Transition(STATE.Picking, MSG.Abort, fnAbortPick, STATE.Idle);
//Place
Transition(STATE.Idle, MSG.Place, fnStartPlace, STATE.Placing);
Transition(STATE.Placing, FSM_MSG.TIMER, fnPlaceTimeout, STATE.Idle);
Transition(STATE.Placing, MSG.Abort, fnAbortPlace, STATE.Idle);
//Pump
Transition(STATE.Idle, MSG.Pump, fnStartPump, STATE.Pumping);
Transition(STATE.Pumping, FSM_MSG.TIMER, fnPumpTimeout, STATE.Idle);
Transition(STATE.Pumping, MSG.Abort, fnAbortPump, STATE.Idle);
//Vent
Transition(STATE.Idle, MSG.Vent, fnStartVent, STATE.Venting);
Transition(STATE.Venting, FSM_MSG.TIMER, fnVentTimeout, STATE.Idle);
Transition(STATE.Venting, MSG.Abort, fnAbortVent, STATE.Idle);
//PMPick
Transition(STATE.Idle, MSG.PMPick, fnStartPMPick, STATE.PMPicking);
Transition(STATE.PMPicking, FSM_MSG.TIMER, fnPMPickTimeout, STATE.Idle);
Transition(STATE.PMPicking, MSG.Abort, fnAbortPMPick, STATE.Idle);
//PMPlace
Transition(STATE.Idle, MSG.PMPlace, fnStartPMPlace, STATE.PMPlacing);
Transition(STATE.PMPlacing, FSM_MSG.TIMER, fnPMPlaceTimeout, STATE.Idle);
Transition(STATE.PMPlacing, MSG.Abort, fnAbortPMPlace, STATE.Idle);
//PA align
Transition(STATE.Idle, MSG.Align, fnStartAlign, STATE.Aligning);
Transition(STATE.Aligning, FSM_MSG.TIMER, fnAlignTimeout, STATE.Idle);
Transition(STATE.Aligning, MSG.Abort, fnAbortAlign, STATE.Idle);
//Swap
Transition(STATE.Idle, MSG.Swap, fnStartSwap, STATE.Swapping);
Transition(STATE.Swapping, FSM_MSG.TIMER, fnSwapTimeout, STATE.Idle);
Transition(STATE.Swapping, MSG.Abort, fnAbortSwap, STATE.Idle);
//PM Swap
Transition(STATE.Idle, MSG.PMSwap, fnStartPMSwap, STATE.PMSwaping);
Transition(STATE.PMSwaping, FSM_MSG.TIMER, fnPMSwapTimeout, STATE.Idle);
Transition(STATE.PMSwaping, MSG.Abort, fnAbortPMSwap, STATE.Idle);
//Extend
Transition(STATE.Idle, MSG.Extend, FnStartExtend, STATE.Extending);
Transition(STATE.Extending, FSM_MSG.TIMER, FnExtend, STATE.Idle);
Transition(STATE.Extending, MSG.Abort, FnAbortExtend, STATE.Idle);
//Retract
Transition(STATE.Idle, MSG.Retract, FnStartRetract, STATE.Retracting);
Transition(STATE.Retracting, FSM_MSG.TIMER, FnRetract, STATE.Idle);
Transition(STATE.Retracting, MSG.Abort, FnAbortRetract, STATE.Idle);
//leakcheck
Transition(STATE.Idle, MSG.LeakCheck, FnStartLeakCheck, STATE.Leakchecking);
Transition(STATE.Leakchecking, FSM_MSG.TIMER, FnLeakCheckTimeout, STATE.Idle);
Transition(STATE.Leakchecking, MSG.Abort, FnAbortLeakCheck, STATE.Idle);
//Control Pressure
AnyStateTransition(FSM_MSG.TIMER, ControlPressureTimer_Elapsed, FSM_STATE.SAME);
Running = true;
}
private bool RobotGoto(object[] param)
{
return _robot.Goto((ModuleName)param[0], (int)param[1], (Hand)param[2]);
}
private bool FnStartExtend(object[] param)
{
return _pmExtendRoutine.Start(param) == RState.Running;
}
private bool FnExtend(object[] param)
{
RState ret = _pmExtendRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool FnAbortExtend(object[] param)
{
_pmExtendRoutine.Abort();
return true;
}
private bool FnStartRetract(object[] param)
{
return _pmRetractRoutine.Start(param) == RState.Running;
}
private bool FnRetract(object[] param)
{
RState ret = _pmRetractRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool FnAbortRetract(object[] param)
{
_pmRetractRoutine.Abort();
return true;
}
private bool FnStartLeakCheck(object[] param)
{
return _leakcheckRoutine.Start(param) == RState.Running;
}
private bool FnLeakCheckTimeout(object[] param)
{
RState ret = _leakcheckRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool FnAbortLeakCheck(object[] param)
{
_leakcheckRoutine.Abort();
return true;
}
private bool fnAbortPMSwap(object[] param)
{
_pmswaproutine.Abort();
return true;
}
private bool fnPMSwapTimeout(object[] param)
{
RState ret = _pmswaproutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartPMSwap(object[] param)
{
return _pmswaproutine.Start(param) == RState.Running;
}
private bool fnAbortSwap(object[] param)
{
_swaproutine.Abort();
return true;
}
private bool fnSwapTimeout(object[] param)
{
RState ret = _swaproutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartSwap(object[] param)
{
return _swaproutine.Start(param) == RState.Running;
}
private bool fnStartAlign(object[] param)
{
if (float.TryParse(param[0].ToString(), out float angle))
{
return _vpa.Align();
}
else
{
LOG.Write(eEvent.ERR_TM,ModuleName.Aligner1,$"wrong angle, value is {param[0]}.");
return false;
}
}
private bool fnAlignTimeout(object[] param)
{
if (_vpa.Status == RState.End)
{
return true;
}
else if (_vpa.Status != RState.Running)
{
LOG.Write(eEvent.ERR_TM, ModuleName.Aligner1, $"PreAligner align failed: {_vpa.Status}");
return true;
}
return false;
}
private bool fnAbortAlign(object[] param)
{
return true;
}
private bool fnAbortPMPlace(object[] param)
{
_placepmRoutine.Abort();
return true;
}
private bool fnPMPlaceTimeout(object[] param)
{
RState ret = _placepmRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartPMPlace(object[] param)
{
return _placepmRoutine.Start(param) == RState.Running;
}
private bool fnAbortPMPick(object[] param)
{
_pickpmRoutine.Abort();
return true;
}
private bool fnPMPickTimeout(object[] param)
{
RState ret = _pickpmRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartPMPick(object[] param)
{
return _pickpmRoutine.Start(param) == RState.Running;
}
private bool fnAbortVent(object[] param)
{
_ventRoutine.Abort();
return true;
}
private bool fnVentTimeout(object[] param)
{
RState ret = _ventRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
_ventRoutine.Abort();
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartVent(object[] param)
{
return _ventRoutine.Start(param) == RState.Running;
}
private bool fnAbortPump(object[] param)
{
_pumpRoutine.Abort();
return true;
}
private bool fnPumpTimeout(object[] param)
{
RState ret = _pumpRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
_pumpRoutine.Abort();
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartPump(object[] param)
{
return _pumpRoutine.Start(param) == RState.Running;
}
private bool fnAbortPlace(object[] param)
{
return true;
}
private bool fnPlaceTimeout(object[] param)
{
RState ret = _placeRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnStartPlace(object[] param)
{
return _placeRoutine.Start(param) == RState.Running;
}
private bool fnAbortPick(object[] param)
{
_pickRoutine.Abort();
return true;
}
private bool fnStartPick(object[] param)
{
return _pickRoutine.Start(param) == RState.Running;
}
private bool fnPickTimeout(object[] param)
{
RState ret = _pickRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnAbortHome(object[] param)
{
_homeRoutine.Abort();
return true;
}
private bool fnHome(object[] param)
{
if (fsm.State == (int)STATE.Init && param.Length > 0)//带参home
{
return false;
}
else
return _homeRoutine.Start(param) == RState.Running;
}
private bool fnHomeTimeout(object[] param)
{
RState ret = _homeRoutine.Monitor();
if (ret == RState.Failed || ret == RState.Timeout)
{
PostMsg(MSG.Error);
return false;
}
return ret == RState.End;
}
private bool fnOffline(object[] param)
{
//IsOnline = false;
//return true;
throw new NotImplementedException();
}
private bool fnOnline(object[] param)
{
//IsOnline = true;
//return true;
throw new NotImplementedException();
}
private bool fnError(object[] param)
{
return true;
}
///
/// 控压处理逻辑
/// 需要按照module去控压
/// 在SE中 因为共用drypump 其前端压力以及使用锁存在抢占可能 需要在pumpstate处于idle下
/// 在DE中 因为分开用drypump 可以在online后始终保持控压的模式
///
///
///
private bool ControlPressureTimer_Elapsed(object[] param)
{
// robot idle check
_robotIdleTrigger.CLK = _robot.Status != RState.Running;
if (_robotIdleTrigger.Q)
{
_robotWatch.Restart();
}
if (RouteManager.IsATMMode)
return true;
if (IsOnline)
{
switch (RtInstance.ConfigType)
{
case ConfigType.VenusSE:
//nobody use pump
if (_tm.PumpingState == PumpState.Idle && !_tm.IsPressureControl)
_tm.PressureControl(true);
break;
case ConfigType.VenusDE:
if(!_tm.IsPressureControl)
_tm.PressureControl(true);
break;
default:
return true;
}
}
else
{
switch (Module)
{
case ModuleName.TM:
if(_tm.IsPressureControl)
_tm.PressureControl(false);
break;
default:
return true;
}
}
//废弃代码
//if (IsOnline && _tm.PumpingState == PumpState.Idle)
//{
//
//}
//else
//{
// if (!SC.GetValue($"{_module}.PressureControl.ControlWriteMode"))
// {
// SC.SetItemValue($"{_module}.PressureControl.ControlWriteMode", true);
// }
//}
return true;
}
public bool Check(int msg, out string reason, params object[] args)
{
reason = "";
return true;
}
public bool CheckAcked(int msg)
{
return fsm.CheckExecuted(msg);
}
public bool CheckToPostMessage(int msg, params object[] args)
{
if (!fsm.FindTransition(fsm.State, msg))
{
LOG.Write(eEvent.WARN_FSM_WARN, _module, $"TM is in {(STATE)fsm.State} state,can not do {(MSG)msg}");
return false;
}
Running = true;
fsm.PostMsg(msg, args);
return true;
}
public int Invoke(string function, params object[] args)
{
switch (function)
{
case "Home":
CheckToPostMessage((int)MSG.Home);
return (int)MSG.Home;
}
return (int)FSM_MSG.NONE;
}
}
}