#include "cprocess_trans.h"

#include "logic.h"
#include "cprocess_scan.h"
#include "cmotordriver_base.h"
#include "cmallsystem.h"
#include "cbarcodedriver.h"
#include "clog_impl.h"
#define DEFAULTSPD_MOTORD_TRANS_SCALE   2
#define DEFAULTSPD_MOTORHJ_UPDOWN_SCALE 2
#define MOTORA_CLAW_HALFSPD 0.3

CProcess_Trans::CProcess_Trans(const QString& name, int32_t id)
    :CMProcess(name, id)
{

    m_Variants.add_Variant(Var_Process_Trans_CylinderMove_TimeOut,
                           QObject::trUtf8("CylinderMove_TimeOut"), int(10000), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosWait,
                           QObject::trUtf8("PosClawWait"), double(-400), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosCassOut,
                           QObject::trUtf8("PosClawCassOut"), double(-1133.5), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_Offset_DisCassUnLoad,
                           QObject::trUtf8("DisClawCassUnLoadOffset"), double(-1080), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosRailNear,
                           QObject::trUtf8("ClawPosRailNear"), double(-970), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosRailFar,
                           QObject::trUtf8("ClawPosRailFar"), double(-970), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_Offset_DisClawLocation,
                           QObject::trUtf8("DisClawCoatOffset"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosCheckBoxOut,
                           QObject::trUtf8("PosClawCheckBoxOut"), double(1133.5), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_Offset_DisCheckBoxUnLoad,
                           QObject::trUtf8("DisClawCheckBoxUnLoadOffset"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_RailNear_PosOpen,
                           QObject::trUtf8("PosRailNearOpen"), double(-7), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_RailNear_PosClose,
                           QObject::trUtf8("PosRailNearClose"), double(-11.4), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailCloseReady,
                           QObject::trUtf8("PosRailCloseReady"), double(-10.4), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailClosePull,
                           QObject::trUtf8("PosRailClosePull"), double(-9), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailOpenPull,
                           QObject::trUtf8("PosRailOpenPull"), double(-9.8), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_RailNear_PosOpenMax,
                           QObject::trUtf8("PosRailNearOpenMax"), double(-6), false,
                           Variant::TOXML);


    m_Variants.add_Variant(Var_Process_RailFar_PosOpen,
                           QObject::trUtf8("PosRailFarOpen"), double(-7), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_RailFar_PosClose,
                           QObject::trUtf8("PosRailFarClose"), double(-11.4), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_RailFar_PosOpenMax,
                           QObject::trUtf8("PosRailFarOpenMax"), double(-6), false,
                           Variant::TOXML);


    //转移抓手的点位
    m_Variants.add_Variant(Var_Process_Trans_PosVWait,
                           QObject::trUtf8("PosTransVWait"), double(-30), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Trans_PosPickupWafer,
                           QObject::trUtf8("PosTransVClaw"), double(-49.8), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosPutdownWafer,
                           QObject::trUtf8("PosTransVPutdownWafer"), double(-49.5), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailNearReady,
                           QObject::trUtf8("PosTransRailNearReady"), double(-39), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailNear,
                           QObject::trUtf8("PosTransRailNear"), double(-40), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailFarReady,
                           QObject::trUtf8("PosTransRailFarReady"), double(-39), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosRailFar,
                           QObject::trUtf8("PosTransRailFar"), double(-40), false,
                           Variant::TOXML);

    //涂覆台抓晶圆过渡
    m_Variants.add_Variant(Var_Process_Trans_PosVCoatFinish,
                           QObject::trUtf8("PosTransVCoatFinish"), double(-70), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosVCoatFinishLow,
                           QObject::trUtf8("PosTransVCoatFinishLow"), double(-75), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosTransVCoat,
                           QObject::trUtf8("PosTransVCoat"), double(-80), false,
                           Variant::TOXML);

    //清洗台抓晶圆过渡
    m_Variants.add_Variant(Var_Process_Trans_PosVCleanFinish,
                           QObject::trUtf8("PosTransVCleanFinish"), double(-75), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Trans_PosTransVClean,
                           QObject::trUtf8("PosTransVClean"), double(-80), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosHCoat,
                           QObject::trUtf8("PosTransHCoat"), double(-100), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosHClean,
                           QObject::trUtf8("PosTransHClean"), double(-700), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Trans_StepSleepTime,
                           QObject::trUtf8("StepSleepTime"), int(0), false,
                           Variant::TOXML);


    m_Variants.add_Variant(Var_Process_Claw_PosWaferExistCheck,
                           QObject::trUtf8("PosClawWaferExistCheck"), double(-900), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosScanBarcode,
                           QObject::trUtf8("PosClawBarcode"), double(-800), false,
                           Variant::TOXML);
    //上料
    m_Variants.add_Variant(Var_Process_Load_PosVWait,
                           QObject::trUtf8("PosLoadVWait"), double(0), false,
                           Variant::TOXML);
    //上料抓晶圆结束位置
    m_Variants.add_Variant(Var_Process_Load_PosVCoatFinish,
                           QObject::trUtf8("PosLoadVCoatFinish"), double(-20), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosVCoatFinishLow,
                           QObject::trUtf8("PosLoadVCoatFinishLow"), double(-20), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosVRail,
                           QObject::trUtf8("PosLoadVRail"), double(-200), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosVWT,
                           QObject::trUtf8("PosLoadVWT"), double(-20), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosHWait,
                           QObject::trUtf8("PosLoadHWait"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosHCoat,
                           QObject::trUtf8("PosLoadHCoat"), double(200), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Load_PosHWT,
                           QObject::trUtf8("PosLoadHWT"), double(140), false,
                           Variant::TOXML);

    //下料点位
    m_Variants.add_Variant(Var_Process_Unload_PosVWait,
                           QObject::trUtf8("PosUnoadVWait"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Unload_PosVRail,
                           QObject::trUtf8("PosUnoadVRail"), double(-20), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Unload_PosVWT,
                           QObject::trUtf8("PosUnoadVWT"), double(-20), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Unload_PosHWait,
                           QObject::trUtf8("PosUnoadHWait"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Unload_PosHClean,
                           QObject::trUtf8("PosUnoadHClean"), double(200), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Unload_PosHWT,
                           QObject::trUtf8("PosUnoadHWT"), double(140), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Trans_GrapVOffset,
                           QObject::trUtf8("GrapVOffset"), double(0), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosLocationReady,
                           QObject::trUtf8("PosClawLocationReady"), double(-650), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosLocationPushPrepare,
                           QObject::trUtf8("PosClawLocationPushPrepare"), double(-670), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Claw_PosLocation,
                           QObject::trUtf8("PosClawLock"), double(-690), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosCassOutReady,
                           QObject::trUtf8("PosClawCassOutReady"), double(-1080), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Trans_PosTransHLock,
                           QObject::trUtf8("PosTransHLock"), double(-760), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosPutRail,
                           QObject::trUtf8("UnloadRail"), double(-660), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Claw_PosPushReadyUnload,
                           QObject::trUtf8("PushReadyUnload"), double(-700), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Trans_CleanGetWaferWaitTimeMs,
                           QObject::trUtf8("CleanGetWaferWaitTimeMS"), int(0), false,
                           Variant::TOXML);


    m_pSlotGrab = 0;
    m_pSlotRailNear = 0;
    m_pSlotTrans = 0;
    m_pSlotCoat = 0;
    m_pSlotLoad = 0;
    m_pSlotWT = 0;
    m_pSlotUnLoad = 0;
    m_pSlotClean = 0;
    m_pSlotCheckBox = 0;
    m_pSlotRailNear = 0;
    m_pSlotRailFar = 0;

    //m_pSlotRailNear = new CASSSLOT();
    //m_pSlotClean = new CASSSLOT();
    //m_pSlotRailNear->WPstatus = WPUNCUT;
}

CProcess_Trans::~CProcess_Trans()
{

}

QString CProcess_Trans::GetMsgName(int id)
{
    QString sMsgName = QObject::tr("Transfer msg id:%1").arg(id);
    switch (id)
    {
    case kTransScanCass:
        sMsgName = QObject::tr("TransScanCass");
        break;
    case kTransCassToRailNear:
        sMsgName = QObject::tr("TransCassToRailNear");
        break;
    case kTransRailNearToCoat:
        sMsgName = QObject::tr("kTransRailNearToCoat");
        break;
    case kTransRailNearToCheckBox:
        sMsgName = QObject::tr("kTransRailNearToCheckBox");
        break;
    case kTransRailNearToWorktable:
        sMsgName = QObject::tr("kTransRailNearToWorktable");
        break;
    case kTransRailNearToClean:
        sMsgName = QObject::tr("kTransRailNearToClean");
        break;
    case kTransRailNearToCass:
        sMsgName = QObject::tr("kTransRailNearToCass");
        break;
    case kTransRailFarToRailNear:
        sMsgName = QObject::tr("kTransRailFarToRailNear");
        break;
    case kTransRailFarToCoat:
        sMsgName = QObject::tr("kTransRailFarToCoat");
        break;
    case kTransRailFarToWorktable:
        sMsgName = QObject::tr("kTransRailFarToWorktable");
        break;
    case kTransCheckBoxToCass:
        sMsgName = QObject::tr("kTransCheckBoxToCass");
        break;
    case kTransCheckBoxToRailNear:
        sMsgName = QObject::tr("kTransCheckBoxToRailNear");
        break;
    case kTransCleanToRailNear:
        sMsgName = QObject::tr("kTransCleanToRailNear");
        break;
    case kTransCoatToRailFar:
        sMsgName = QObject::tr("kTransCoatToRailFar");
        break;
    case kTransWorktableToRailNear:
        sMsgName = QObject::tr("kTransWorktableToRailNear");
        break;
    case kTransRailNearLocation:
        sMsgName = QObject::tr("kTransRailNearLocation");
        break;
    case kTransRailNearLocationManual:
        sMsgName = QObject::tr("kTransRailNearLocationManual");
        break;
    case kAbortTrans:
        sMsgName = QObject::tr("kAbortTrans");
        break;
    case kAbortUnload:
        sMsgName = QObject::tr("kAbortUnload");
        break;
    case kAbortLoad:
        sMsgName = QObject::tr("kAbortLoad");
        break;
    case kTransCheckboxToCoat:
        sMsgName = QObject::tr("kTransCheckboxToCoat");
        break;
    case kTransCheckboxToClean:
        sMsgName = QObject::tr("kTransCheckboxToClean");
        break;
    case kTransCoatToWt:
        sMsgName = QObject::tr("kTransCoatToWt");
        break;
    case kTransWtToClean:
        sMsgName = QObject::tr("kTransWtToClean");
        break;
    case kTransCleanToCass:
        sMsgName = QObject::tr("kTransCleanToCass");
        break;
    case kMoveInitPos:
        sMsgName = QObject::tr("kMoveInitPos");
        break;
    case kResetSlot:
        sMsgName = QObject::tr("kResetSlot");
        break;
    case kAbortWafer:
        sMsgName = QObject::tr("kAbortWafer");
        break;
    case kTransRailNearToFar:
        sMsgName = QObject::tr("kTransRailNearToFar");
        break;
    case kTransCoatToRailNear:
        sMsgName = QObject::tr("kTransCoatToRailNear");
        break;
    case kTransCoatToCheckbox:
        sMsgName = QObject::tr("kTransCoatToCheckbox");
        break;
    case kTransCleanToCheckbox:
        sMsgName = QObject::tr("kTransCleanToCheckbox");
        break;
    case kTransCheckboxToWt:
        sMsgName = QObject::tr("kTransCheckboxToWt");
        break;
    case kTransWtToCheckbox:
        sMsgName = QObject::tr("kTransWtToCheckbox");
        break;
    default:
        break;
    }
    return sMsgName;
}

/*!
 * \brief CProcess_Trans::ClawRelease
 * 夹抓打开
 */
void CProcess_Trans::ClawRelease(bool bWait)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->set_cylinder(OUT_CLAW_CLOSED, IN_CLAW_Opend, FALSE);
}

/*!
 * \brief CProcess_Trans::ClawClaw
 * 夹抓闭合
 */
void CProcess_Trans::ClawGrabed(bool bWait/*=true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    //pDriver->set_cylinder(OUT_CLAW,IN_CLAWCLOSE_BACK,TRUE);
    //HACK:因为没法检查闭合状态，所以传递-1不检测反馈
    pDriver->set_cylinder(OUT_CLAW_CLOSED, -1, TRUE);
    if (true == bWait)
        MSleep(200);
}

void CProcess_Trans::UnloadPos()
{
    //下料位
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);

    pWorkTableDriver->UnLoadPos(WORKTABLE);

}

void CProcess_Trans::LoadPos()
{
    //上料位
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);

    pWorkTableDriver->LoadPos(WORKTABLE);

}

void CProcess_Trans::ManualLoadPos()
{
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);

    pWorkTableDriver->ManualLoadPos(WORKTABLE);
}

bool CProcess_Trans::IsCurPosLower(double dCurPos, int varId)
{
    return IsPosLess(dCurPos, varId);
}

bool CProcess_Trans::IsMotorPosLower(int iMotorId, int varId)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    double dCurPos = pDriver->get_posdata(iMotorId, true);
    return IsCurPosLower(dCurPos, varId);
}

bool CProcess_Trans::IsPosBigger(double dTargetPos, int varId)
{
    double dPos = m_Variants.get_VData(varId)->toDouble();
    if (dTargetPos - 0.01 > dPos)
    {
        return true;
    }

    return false;
}

bool CProcess_Trans::IsPosInRange(double dTargetPos, int varId, double dOffset /*= 1.0*/)
{
    double dPos = m_Variants.get_VData(varId)->toDouble();
    return dTargetPos > dPos - dOffset && dTargetPos < dPos + dOffset;
}

bool CProcess_Trans::IsMotorInRange(int iMotorId, int varId, double dOffset /*= 1.0*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    double dCurPos = pDriver->get_posdata(iMotorId, true);
    return IsPosInRange(dCurPos, varId, dOffset);
}

bool CProcess_Trans::IsPosLess(double dTargetPos, int varId)
{
    double dPos = m_Variants.get_VData(varId)->toDouble();
    if (dTargetPos + 0.01 < dPos)
    {
        return true;
    }

    return false;
}

bool CProcess_Trans::IsPosUpper(double dTargetPos, int varId)
{
    double dPos = m_Variants.get_VData(varId)->toDouble();
    if (dTargetPos - 0.01 > dPos)
    {
        return true;
    }

    return false;
}

bool CProcess_Trans::IsCurPosNearCass(double dCurPos, int varId)
{
    return IsPosLess(dCurPos, varId);
}

void CProcess_Trans::IonBlowOn(IonPos eIonPos/* = IonEntrance*/)
{
    if (eIonPos == IonCoat || eIonPos == IonClean)
    {
        return;
    }
    IonBlowControl(eIonPos, true);
}

void CProcess_Trans::IonBlowOff(IonPos eIonPos/* = IonEntrance*/)
{
    IonBlowControl(eIonPos, false);
}

void CProcess_Trans::IonBlowControl(IonPos eIonPos, bool bOn)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    if (bOn && eIonPos != IonEntrance && eIonPos != IonWt)
    {
        pDriver->setio(IO_OUTPUT, OUT_POWER_ELECT_Other, bOn);
    }
    Q_ASSERT(pDriver);
    switch (eIonPos)
    {
    case CProcess_Trans::IonEntrance:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Entry, bOn);
        pDriver->setio(IO_OUTPUT, OUT_POWER_ELECT_ENTRY, bOn);
        break;
    case CProcess_Trans::IonWt:
        pDriver->setio(IO_OUTPUT, OUT_POWER_ELECT_WT, bOn);
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Wt, bOn);
        break;
    case CProcess_Trans::IonTrans:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Transfer, bOn);
        break;
    case CProcess_Trans::IonLoad:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Load, bOn);
        break;
    case CProcess_Trans::IonUnload:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Unload, bOn);
        break;
    case CProcess_Trans::IonClean:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Clean, bOn);
        break;
    case CProcess_Trans::IonCoat:
        pDriver->setio(IO_OUTPUT, OUT_ELECT_Coat, bOn);
        break;
    default:
        break;
    }
}

//检查规整台，即合拢的轴上有无晶圆状态是否正常
//bassertexist true检查有  不一致抛异常
bool CProcess_Trans::AssertRailNearHasWafer(bool bAssertExist, QString sTransInfo, int iAlarmCode/*=ALARM_TRANS_SAFE_PROTECT*/)
{
    bool bExist = false;
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true) ||
            pDriver->get_iodata(IO_INPUT, IN_Rail_NearLoc_HasWafer, true);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTransInfo + " " + QObject::trUtf8("RailNear do not has wafer.")));
        }
        else
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTransInfo + " " + QObject::trUtf8("RailNear has wafer.")));
        }
    }
    return bExist;
}

bool CProcess_Trans::AssertRailNearCassHasWafer(bool bAssertExist, int iAlarmCode/* = ALARM_TRANS_SAFE_PROTECT*/)
{
    if (m_gSystem.IsSimulator())
    {
        return bAssertExist;
    }
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    bool bHas = pDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true);
    //检查有晶圆但是没有就抛异常
    if (bAssertExist && !bHas)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailNearCass_WaferError, QObject::trUtf8("Near cass,rail do not has wafer."));
    }
    //检查没晶圆但是有就抛异常
    if (!bAssertExist && bHas)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailNearCass_WaferError, QObject::trUtf8("Near cass,rail has wafer."));
    }
    return bHas;
}

bool CProcess_Trans::AssertRailNearLocationHasWafer(bool bAssertExist, int iAlarmCode/* = ALARM_TRANS_SAFE_PROTECT*/)
{
    if (m_gSystem.IsSimulator())
    {
        return bAssertExist;
    }
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    bool bHas = pDriver->get_iodata(IO_INPUT, IN_Rail_NearLoc_HasWafer, true);
    //检查有晶圆但是没有就抛异常
    if (bAssertExist && !bHas)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailWaferFailed_NotExists, QObject::trUtf8("Near coat worktable,rail do not has wafer."));
    }
    //检查没晶圆但是有就抛异常
    if (!bAssertExist && bHas)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailWaferFailed_NotExists, QObject::trUtf8("Near coat worktable,rail has wafer."));
    }
    return bHas;
}

bool CProcess_Trans::AssertRailFarHasWafer(bool bAssertExist, QString sTitleInfo, int iAlarmCode /*= ALARM_TRANS_SAFE_PROTECT*/)
{
    bool bExist = false;
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_Rail_FarCass_HasWafer, true);
    }

    if (bAssertExist != bExist)
    {
        //检查有晶圆但是没有就抛异常
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailWaferFailed_NotExists, QObject::trUtf8("Near coat worktable,Rail(Far) do not has wafer."));
        }
        else
        {
            //检查没晶圆但是有就抛异常
            MQT_THROW_CODESTR(ALARM_TRANS_ERROR_RailWaferFailed_NotExists, QObject::trUtf8("Near coat worktable,Rail(Far) has wafer."));
        }
    }
    return bExist;
}

//CheckBox有无晶圆检查
//bassertexist true表示有 不一致抛异常
bool CProcess_Trans::AssertCheckBoxhasCell(bool bAssertExist, QString sTransInfo, int iAlarmCode)
{
    bool bExist = false;

    //如果逻辑中未记录到Wafer
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_CHECKBOX_HAS_WAFER_LEFT, true);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cupboard do not has wafer."));
        }
        else
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cupboard has wafer."));
        }
    }
    return bExist;
}

bool CProcess_Trans::AssertLoadHasWafer(bool bAssertExist, QString sTransInfo, int iAlarmCode)
{
    bool bExist = false;

    //如果逻辑中未记录到Wafer
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_LOAD_VACUUM, true);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            //上料手没有晶圆
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("load grab wafer failed."));
        }
        else
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("load has wafer."));
        }
    }
    return bExist;
}

void CProcess_Trans::AssertUnloadHasWafer(bool bAssertExist, QString sTransInfo, int iAlarmCode)
{
    bool bExist = false;
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_UNLOAD_VACUUM, true);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            //下料手没有晶圆
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("unload grab has no wafer."));
        }
        else
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("unload has wafer."));
        }
    }
}

bool CProcess_Trans::AssertTransHasWafer(bool bAssertExist, QString sTitleInfo, int iAlarmCode)
{
    bool bExist = false;

    //如果逻辑中未记录到Wafer
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pDriver);
        bExist = pDriver->get_iodata(IO_INPUT, IN_TRANS_VACUUM, true);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            //转移抓手没有晶圆
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, sTitleInfo + "\n" +  QObject::trUtf8("transfer grab has no wafer."));
        }
        else
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, sTitleInfo + "\n" + QObject::trUtf8("transfer has wafer."));
        }
    }
    return bExist;
}

void CProcess_Trans::AssertGrabHasWafer(QString sTransInfo, 
                                        int iAlarmCode /*= ALARM_TRANS_SAFE_PROTECT*/)
{
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    bool bTriger = pMotorDriver->get_iodata(IO_INPUT, IN_CLAW_Closed, true);
    if (bTriger)
    {
        ClawRelease();
        MQT_THROW_CODESTR(iAlarmCode, sTransInfo + "\n" + QObject::tr("Grab has not Wafer"));
    }
}

void CProcess_Trans::AssertCoatWaferHasWater(QString sTransInfo, int iAlarmCode /*= ALARM_TRANS_SAFE_PROTECT*/)
{
    QMutexLocker l(&m_slotMutex);
    if (!m_pSlotCoat)
    {
        return;
    }

    if (m_pSlotCoat->bHasWater)
    {
        //涂覆台没有水
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, sTransInfo + "\n" + QObject::trUtf8("CoatTable wafer must dry at first."));
    }
}

void CProcess_Trans::AssertCleanWaferHasWater(QString sTransInfo, int iAlarmCode /*= ALARM_TRANS_SAFE_PROTECT*/)
{
    QMutexLocker l(&m_slotMutex);
    if (!m_pSlotClean)
    {
        return;
    }
    if (m_pSlotClean->bHasWater)
    {
        //涂覆台没有水
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, sTransInfo + "\n" + QObject::trUtf8("CleanTable wafer must dry at first."));
    }
}

//移动转移的轴到准备位置，移动前先检查是否有位置冲突
void CProcess_Trans::MoveTransInitPos()
{
    CMotorDriver_Base* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver_Base);
    Q_ASSERT(pDriver);

    //检查下上料轴的位置是否在最左边
    //pDriver->get_motor_area_type();
    double dCurPosA = pDriver->get_posdata(MOTORA_CLAW, true);
	double dCurPosD = pDriver->get_posdata(MOTORD_TRANS, true);
	if (IsCurPosLower(dCurPosD, Var_Process_Trans_PosPutdownWafer))
	{
		MoveTransVNearPull();
	}

    //如果夹抓在抓晶圆位置，先把夹抓移动到扫描位置，再升起Z轴
    if (IsCurPosLower(dCurPosA, Var_Process_Claw_PosScanBarcode))
    {
        MoveHGrabBarcode();
    }
    MoveVTransWait();
    MoveHGrabWait();
}

//移动上料轴到准备位置
void CProcess_Trans::MoveLoadInitPos()
{
    MoveVLoadWait();
    MoveHLoadWait(true);
}
//移动下料轴到准备位置
void CProcess_Trans::MoveUnLoadInitPos()
{
    MoveVUnloadWait();
    MoveHUnloadWait();
}
//上下料转移移动到准备位置
void CProcess_Trans::MoveInitPos()
{
    //上料下料移动到准备位置
    //先把垂直轴移动到Wait位置
    //再把水平轴移到到平台位置

    //转移夹抓移到安全位置
    MoveLoadInitPos();
    MoveUnLoadInitPos();
    MoveTransInitPos();
}

//夹抓移动到准备位置
void CProcess_Trans::MoveHGrabWait(bool bWait)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosWait)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos, bWait);
}

//夹抓移动到取晶圆准备位置
void CProcess_Trans::MoveHGrabPickUpReadySpd(bool bWait)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosCassOutReady)
        ->toDouble();

    double dCurPos = pDriver->get_posdata(MOTORA_CLAW, true);

    bool bHalfSpeed = false;
    if (IsCurPosNearCass(dCurPos, Var_Process_Claw_PosCassOutReady))
    {
        bHalfSpeed = true;
        //靠近操作员方向,在慢速区域
        CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
        double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)
            ->toDouble();

        pDriver->setspeed(MOTORA_CLAW, MOTORA_CLAW_HALFSPD * dDefaultSpd, 0, 0, 0, 0);
    }

    try
    {
        pDriver->absmove(MOTORA_CLAW, dPos, bWait);
        if (bWait)
        {
            pDriver->setdefaultspeed(MOTORA_CLAW);
        }
    }
    catch (const QString& ex)
    {
        pDriver->setdefaultspeed(MOTORA_CLAW);
        throw ex;
    }
}

//夹抓移动到取晶圆位置
void CProcess_Trans::MoveHGrabPickUpCassSpd()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosCassOut)
        ->toDouble();

    //设置半速
    CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
    double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)
        ->toDouble();
    pDriver->setspeed(MOTORA_CLAW, MOTORA_CLAW_HALFSPD * dDefaultSpd, 0, 0, 0, 0);

    try
    {
        pDriver->absmove(MOTORA_CLAW, dPos);
        pDriver->setdefaultspeed(MOTORA_CLAW);
    }
    catch (const QString& ex)
    {
        pDriver->setdefaultspeed(MOTORA_CLAW);
        throw ex;
    }
}

//到检查晶圆有无位置
void CProcess_Trans::MoveHGrabWaferExistCheck(bool bOffset/* = false*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosWaferExistCheck)
        ->toDouble();
    if (bOffset)
    {
        dPos -= 5;
    }
    pDriver->absmove(MOTORA_CLAW, dPos);
}

void CProcess_Trans::MoveHGrabBarcode()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosScanBarcode)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos);
}

void CProcess_Trans::MoveHGrabLocationNearReady()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosLocationReady)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos);
}

void CProcess_Trans::MoveHGrabLocationNearPushPrepare()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosLocationPushPrepare)
        ->toDouble();

    CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
    pDriver->absmove(MOTORA_CLAW, dPos);
}

//夹抓移动到涂敷的位置
//void CProcess_Trans::MoveToPosGrabCoat(bool bOffset)
//{
//    CMotorDriver* pDriver=GET_CARD(MOTOR_DRIVER,CMotorDriver);
//    Q_ASSERT(pDriver);
//    double dPos=m_Variants.get_VData(Var_Process_Trans_PosClawCoat)
//            ->toDouble();
//    if(bOffset)
//    {
//        dPos+=m_Variants.get_VData(Var_Process_Trans_DisClawLockOffset)
//                ->toDouble();
//    }
//    pDriver->absmove(MOTORA_CLAW,dPos);
//}

#if 0
//bOffset 往回拉 bOffsetOneMM 多往回拉10mm
//夹抓规整操作
//
void CProcess_Trans::MoveToPosGrabLock(bool bOffset, bool bOffsetOneMM/*=false*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosLocation)
        ->toDouble();
    if (bOffset)
    {
        dPos -= m_Variants.get_VData(Var_Process_Claw_Offset_DisClawLocation)
            ->toDouble();
    }
    if (bOffsetOneMM)
    {
        dPos -= 15;
    }

    CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
    double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)
        ->toDouble();
    pDriver->setspeed(MOTORA_CLAW, 0.5 * dDefaultSpd, 0, 0, 0, 0);

    pDriver->absmove(MOTORA_CLAW, dPos);

    pDriver->setspeed(MOTORA_CLAW, dDefaultSpd, 0, 0, 0, 0);
}
#endif
//往料盒放时，靠近时使速度降为默认速度的一半
void CProcess_Trans::GrabToPos2Spd(double dPos)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->absmove(MOTORA_CLAW, dPos, false);

    int iState = pDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true);
    bool bFirstPos = false;
    bool bSetPos = false;
    while (!pDriver->is_move_finished(MOTORA_CLAW))
    {
        MSleep(10);
        if (bSetPos == false)
        {
            double dPos = pDriver->get_posdata(MOTORA_CLAW, true);
            double dTargetPos = m_Variants.get_VData(Var_Process_Claw_PosScanBarcode)->toDouble();
            if (dPos > dTargetPos)
            {
                bFirstPos = true;
            }
        }

        if (true == bFirstPos)
        {
            //接近时按半速运动
            CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
            double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)
                ->toDouble();
            pDriver->setspeed(MOTORA_CLAW, 0.5 * dDefaultSpd, 0, 0, 0, 0);
            bFirstPos = false;
            bSetPos = true;
        }

        int iCur = pDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true);
        if (!iCur && iState)
        {
            //接近时按1/3速运动
            CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
            double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)
                ->toDouble();
            pDriver->setspeed(MOTORA_CLAW, 0.3 * dDefaultSpd, 0, 0, 0, 0);
        }
        else
        {
            iState = iCur;
        }

        //夹抓防撞检测
        int clawCheck = pDriver->get_iodata(IO_INPUT, IN_CLAW_Collision_Detection_Push, true);
        if (clawCheck == 0)
        {
            pDriver->stopmove(MOTORA_CLAW);
            pDriver->setdefaultspeed(MOTORA_CLAW);
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Glaw strike sensor triggerd"));
        }

    }
    pDriver->setdefaultspeed(MOTORA_CLAW);
}

//夹抓推Wafer到料盒，快推进时半速运动
void CProcess_Trans::MoveHGrabPutDownToCassSpd()
{
    double dPos =
        m_Variants.get_VData(Var_Process_Claw_PosCassOut)
        ->toDouble() +
        m_Variants.get_VData(Var_Process_Claw_Offset_DisCassUnLoad)
        ->toDouble();
    GrabToPos2Spd(dPos);
}

void CProcess_Trans::MoveHGrabPickUpCheckbox()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosCheckBoxOut)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos);

}

void CProcess_Trans::MoveHGrabPutDownToCheckBoxSpd()
{
    double dPos =
        m_Variants.get_VData(Var_Process_Claw_PosCheckBoxOut)
        ->toDouble() +
        m_Variants.get_VData(Var_Process_Claw_Offset_DisCassUnLoad)
        ->toDouble();
    GrabToPos2Spd(dPos);
}

//规整台打开
void CProcess_Trans::MoveRailNearOpen(bool bWait/*=true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_RailNear_PosOpen)
        ->toDouble();
    pDriver->absmove(MOTORB1_LOCK, dPos, bWait);
}

//规整台闭合
void CProcess_Trans::MoveRailNearClose()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_RailNear_PosClose)
        ->toDouble();
    pDriver->absmove(MOTORB1_LOCK, dPos);
}

void CProcess_Trans::MoveRailNearReadyClose()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    /*double dPos=m_Variants.get_VData(Var_Process_Trans_PosArrangeClose)
    ->toDouble() + 1;*/
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosRailCloseReady)
        ->toDouble();

    pDriver->absmove(MOTORB1_LOCK, dPos);
}

void CProcess_Trans::MoveRailNearPullClose()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    /*double dPos=m_Variants.get_VData(Var_Process_Trans_PosArrangeClose)
        ->toDouble() + 1.6;*/
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosRailClosePull)
        ->toDouble();
    pDriver->absmove(MOTORB1_LOCK, dPos);
}

void CProcess_Trans::MoveRailNearPullOpen()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosRailOpenPull)
        ->toDouble();
    //double dPos = -9;
    pDriver->absmove(MOTORB1_LOCK, dPos);
}

//规整台开到最大
void CProcess_Trans::MoveRailNearOpenMax(bool bWait/*=true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_RailNear_PosOpenMax)
        ->toDouble();
    pDriver->absmove(MOTORB1_LOCK, dPos, bWait);
}

//中转垂直等待位,也是安全位置
void CProcess_Trans::MoveVTransWait()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosVWait)
        ->toDouble();

    CMotor* pMotorD = GET_CHDIRECT(MOTORD_TRANS, CMotor);
    double dDefaultSpd = pMotorD->m_Variants.get_VData(Var_Motor_Default_speed_ID)
        ->toDouble();
    pDriver->setspeed(MOTORD_TRANS, dDefaultSpd * DEFAULTSPD_MOTORD_TRANS_SCALE, 0, 0, 0, 0);

    pDriver->absmove(MOTORD_TRANS, dPos);

    pDriver->setdefaultspeed(MOTORD_TRANS);
}

void CProcess_Trans::MoveTransVNearPull()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosPutdownWafer)
        ->toDouble();

    pDriver->absmove(MOTORD_TRANS, dPos);
}

//中转垂直方向抓取上料偏移位
/*
void CProcess_Trans::MoveToPosTransOffsetVGrap()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = fabs(m_Variants.get_VData(Var_Process_Trans_GrapVOffset)
                       ->toDouble());

    if (dPos > -1) {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("move position error."));
    }

    pDriver->relmove(MOTORD_TRANS, dPos);
}
*/
//清洗平台下料时,准备推晶元的位置
void CProcess_Trans::MoveHGrabPutDownPrepare()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosPushReadyUnload)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos);
}

//清洗平台下料时,不在涂覆位置下料
//void CProcess_Trans::MoveVTransRailNear()
//{
//    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
//    Q_ASSERT(pDriver);
//    double dPos = m_Variants.get_VData(Var_Process_Trans_PosPutArrange)
//        ->toDouble();
//    pDriver->absmove(MOTORA_CLAW, dPos);
//}

//中转轴到抓晶圆位置
void CProcess_Trans::MoveVTransPickUpWafer()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosPickupWafer)
        ->toDouble();

    pDriver->absmove(MOTORD_TRANS, dPos);
}

void CProcess_Trans::MoveVTransRailNear(bool bWait/* = true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Trans_PosRailNear)
        ->toDouble();

    pDriver->absmove(MOTORD_TRANS, dPos);
}

void CProcess_Trans::MoveVTransRailFarReady(bool bWait)
{
    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosRailFarReady, false, bWait);
}

void CProcess_Trans::MoveVTransRailFar(bool bWait/*=true*/)
{
    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosRailFar, false, bWait);
}

void CProcess_Trans::MoveVTransRailNearReady(bool bWait)
{
    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosRailNearReady, false, bWait);
}


void CProcess_Trans::MoveVTransCoatReadySpd(bool bHalfspeed/*=true*/)
{
    if (false == bHalfspeed)
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        double dPos = pDriver->get_posdata(MOTORD_TRANS, true);
        if (IsPosLess(dPos, Var_Process_Trans_PosVCoatFinish))
        {
            bHalfspeed = true;
        }
    }
    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosVCoatFinish, bHalfspeed);
}

void CProcess_Trans::MoveVTransCoatUpABitSpd(bool bHalfspeed/*=true*/)
{
    if (false == bHalfspeed)
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        double dPos = pDriver->get_posdata(MOTORD_TRANS, true);
        if (IsPosLess(dPos, Var_Process_Trans_PosVCoatFinishLow))
        {
            bHalfspeed = true;
        }

    }
    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosVCoatFinishLow, bHalfspeed);
}

void CProcess_Trans::MoveVTransCleanReady(bool bHalfspeed/*=true*/)
{
    if (false == bHalfspeed)
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        double dPos = pDriver->get_posdata(MOTORD_TRANS, true);
        double dTargetPos = m_Variants.get_VData(Var_Process_Trans_PosVCleanFinish)->toDouble();
        if (IsPosLess(dTargetPos, Var_Process_Trans_PosVCleanFinish))
        {
            bHalfspeed = true;
        }
    }

    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosVCleanFinish, bHalfspeed);

}

void CProcess_Trans::MoveVTransCoatSpd(bool bHalfspeed/*=true*/)
{
    //CMotorDriver* pDriver=GET_CARD(MOTOR_DRIVER,CMotorDriver);
    //Q_ASSERT(pDriver);
    //double dPos=m_Variants.get_VData(Var_Process_Trans_PosTransVCoat)
    //        ->toDouble();
    //pDriver->absmove(MOTORD_TRANS,dPos);

    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosTransVCoat, bHalfspeed);
}

void CProcess_Trans::MoveVTransClean(bool bHalfspeed/*=true*/)
{
    //CMotorDriver* pDriver=GET_CARD(MOTOR_DRIVER,CMotorDriver);
    //Q_ASSERT(pDriver);
    //double dPos=m_Variants.get_VData(Var_Process_Trans_PosTransVClean)
    //        ->toDouble();
    //pDriver->absmove(MOTORD_TRANS,dPos);

    MoveMotorToPos(MOTORD_TRANS, Var_Process_Trans_PosTransVClean, bHalfspeed);
}


void CProcess_Trans::MoveTransPickUpWaferFromCoat()
{
    //闭合夹抓
    ClawGrabed(false); //下降前闭合夹抓

    //全速移动到准备位置 如果在Finish位置下方，则不移动
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    double dCurPos = pDriver->get_posdata(MOTORD_TRANS, true);
    if (IsPosUpper(dCurPos, Var_Process_Trans_PosVCoatFinish))
    {
        MoveVTransCoatReadySpd(false);
    }

    //半速移动
    MoveVTransCoatSpd(true);

    //真空操作如果失败了,重入的时候上边操作还会执行
    VaccumCoatToTrans();

    //先上提一下,再降一下，将卡子松掉
    MoveVTransCoatUpABitSpd(true);
    MoveVTransCoatSpd(true);

    //慢速回到准备位置
    MoveVTransCoatReadySpd(true);

    //检查是否有晶圆
    AssertTransHasWafer(true, QObject::tr("Trans pickup wafer from Coattable"));

    //成功了才交换
    SlotTransfer(&m_pSlotCoat, &m_pSlotTrans);
}

void CProcess_Trans::MoveTransPickUpWaferFromClean()
{
    //闭合夹抓
    ClawGrabed(false);

    //全速移动到准备位置,如果在Finish位置下方，则仍然是慢速移动
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    double dCurPos = pDriver->get_posdata(MOTORD_TRANS, true);
    if (IsPosUpper(dCurPos, Var_Process_Trans_PosVCleanFinish))
    {
        MoveVTransCleanReady(false);
    }

    //半速移动到清洗台
    MoveVTransClean(true);

    //真空操作
    VaccumCleanToTrans();
    
    int sleepTimeMs = m_Variants.get_VData(Var_Process_Trans_CleanGetWaferWaitTimeMs)->toInt();
    if (sleepTimeMs > 0)
    {
        MSleep(sleepTimeMs);
    }

    //慢速回到准备位置
    MoveVTransCleanReady();

    //检查是否有晶圆
    AssertTransHasWafer(true, QObject::tr("Trans pickup wafer from Cleantable"));

    //成功了再交换数据
    SlotTransfer(&m_pSlotClean, &m_pSlotTrans);
}


void CProcess_Trans::MoveTransPutDownWafterToCoat()
{
    //下降到COAT
    ClawGrabed(false); //下降前闭合夹抓
    MoveVTransCoatReadySpd(false);
    MoveVTransCoatSpd();

    //TODO:如果开真空失败，这里有问题
    //VaccumTransToCoat();
}

void CProcess_Trans::MoveTransPutDownWaferToClean()
{
    //TODO:
    ClawGrabed(false); //下降前闭合夹抓
    MoveVTransCleanReady(false);
    MoveVTransClean(true);
}

//从规整台取晶圆的夹抓位置
//void CProcess_Trans::MoveToPosTransHLock()
//{
//	CMotorDriver* pDriver=GET_CARD(MOTOR_DRIVER,CMotorDriver);
//	Q_ASSERT(pDriver);
//	double dPos=m_Variants.get_VData(Var_Process_Trans_PosTransHLock)
//		->toDouble();
//	pDriver->absmove(MOTORA_CLAW,dPos);
//}


void CProcess_Trans::MoveHGrabLocationNearSpd()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosLocation)
        ->toDouble();

    CMotor* pMotorA = GET_CHDIRECT(MOTORA_CLAW, CMotor);
    double dDefaultSpd = pMotorA->m_Variants.get_VData(Var_Motor_Default_speed_ID)->toDouble();
    pDriver->setspeed(MOTORA_CLAW, 0.5 * dDefaultSpd, 0, 0, 0, 0);

    pDriver->absmove(MOTORA_CLAW, dPos);

    pDriver->setspeed(MOTORA_CLAW, dDefaultSpd, 0, 0, 0, 0);
}

//水平涂敷位
void CProcess_Trans::MoveHGrabToCoat(bool bWait/*=true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosHCoat)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos, bWait);
}

void CProcess_Trans::MoveHGrabToClean(bool bWait/* = true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dPos = m_Variants.get_VData(Var_Process_Claw_PosHClean)
        ->toDouble();
    pDriver->absmove(MOTORA_CLAW, dPos, bWait);
}

//移动加载轴上下到准备位置
void CProcess_Trans::MoveVLoadWait()
{
    CMotor* pMotor = GET_CHDIRECT(MOTORH1_UPDOWN, CMotor);
    double dDefaultSpd = pMotor->m_Variants.get_VData(Var_Motor_Default_speed_ID)
        ->toDouble();
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->setspeed(MOTORH1_UPDOWN, dDefaultSpd * DEFAULTSPD_MOTORHJ_UPDOWN_SCALE, 0, 0, 0, 0);

    MoveLoadVToPos(Var_Process_Load_PosVWait);

    pDriver->setdefaultspeed(MOTORH1_UPDOWN);
}

void CProcess_Trans::MoveToPosLoadVCoatFinish(bool bHalfspeed/*=true*/)
{
    if (false == bHalfspeed)
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        double dPos = pDriver->get_posdata(MOTORH1_UPDOWN, true);
        double dTargetPos = m_Variants.get_VData(Var_Process_Load_PosVCoatFinish)->toDouble();
        if (dPos + 0.01 > dTargetPos)
        {
            bHalfspeed = true;
        }
    }
    //设置半速
    MoveLoadVToPos(Var_Process_Load_PosVCoatFinish, bHalfspeed);
}

void CProcess_Trans::MoveToPosLoadVCoatFinishLow(bool bHalfspeed/*=true*/)
{
    if (false == bHalfspeed)
    {
        CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        double dPos = pDriver->get_posdata(MOTORH1_UPDOWN, true);
        double dTargetPos = m_Variants.get_VData(Var_Process_Load_PosVCoatFinishLow)->toDouble();
        if (dPos + 0.01 > dTargetPos)
        {
            bHalfspeed = true;
        }
    }
    //设置半速
    MoveLoadVToPos(Var_Process_Load_PosVCoatFinishLow, bHalfspeed);
}

void CProcess_Trans::MoveVLoadRailFar(bool bHalfSpeed/*=false*/)
{
    MoveLoadVToPos(Var_Process_Load_PosVRail, bHalfSpeed);
}

void CProcess_Trans::MoveVLoadWT()
{
    MoveLoadVToPos(Var_Process_Load_PosVWT);
}

void CProcess_Trans::MoveHLoadRailFar()
{
    MoveHLoadToPos(Var_Process_Load_PosHCoat);
}

//移动加载轴左右到准备位置
void CProcess_Trans::MoveHLoadWT()
{
    MoveHLoadToPos(Var_Process_Load_PosHWT);
}

void CProcess_Trans::MoveHLoadWait(bool bWait)
{
    MoveHLoadToPos(Var_Process_Load_PosHWait, bWait);
}

void CProcess_Trans::MoveVUnloadWait()
{
    CMotor* pMotor = GET_CHDIRECT(MOTORJ1_UPDOWN, CMotor);
    double dDefaultSpd = pMotor->m_Variants.get_VData(Var_Motor_Default_speed_ID)
        ->toDouble();
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->setspeed(MOTORJ1_UPDOWN, dDefaultSpd * DEFAULTSPD_MOTORHJ_UPDOWN_SCALE, 0, 0, 0, 0);

    MoveUnloadVToPos(Var_Process_Unload_PosVWait);

    pDriver->setdefaultspeed(MOTORJ1_UPDOWN);
}

void CProcess_Trans::MoveVUnloadRailNear()
{
    MoveUnloadVToPos(Var_Process_Unload_PosVRail);
}

void CProcess_Trans::MoveVUnLoadWT()
{
    MoveUnloadVToPos(Var_Process_Unload_PosVWT);
}

void CProcess_Trans::MoveHUnloadRailNear(bool bWait/*=true*/)
{
    MoveUnloadHToPos(Var_Process_Unload_PosHClean, bWait);
}

void CProcess_Trans::AssertSlotExists(bool bAssertExist, CASSSLOT** pSlot, QString sInfo)
{
    bool bExist = false;
    if (*pSlot)
    {
        bExist = true;
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::tr("%1 require %2 has wafer,but not exist").arg(sInfo).arg(GetWaferName(pSlot)));
        }
        else
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::tr("%1 require %2 has not wafer,but exist").arg(sInfo).arg(GetWaferName(pSlot)));
        }
    }
}

void CProcess_Trans::MoveHUnloadWT(bool bWait/*=true*/)
{
    MoveUnloadHToPos(Var_Process_Unload_PosHWT, bWait);
}

void CProcess_Trans::MoveHUnloadWait()
{
    MoveUnloadHToPos(Var_Process_Unload_PosHWait);
}

void CProcess_Trans::TransScanCass(int iStep, bool bIsAutoMode)
{
	if (0 == iStep) {

		FUNC_START("");

		QString sTransInfo = QObject::tr("Trans scan Cass");
		AssertAcuireRes(SM_TRANS, kResCassete | kResTransfer, sTransInfo);
	}

    CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                       SM_TRANS, CProcess_Scan);
    Q_ASSERT(pScan);
    pScan->CassScan(CASSETTE, iStep);

	/*CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
	Q_ASSERT(pCass);*/

	if (290 == iStep) {
		ReleaseRes(SM_TRANS, kResCassete | kResTransfer);
	}
}
#if 0
//转移到涂敷台
void CProcess_Trans::TransCassToCoat(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotGrab && !m_pSlotRailNear &&
        !m_pSlotTrans && !m_pSlotCoat &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        AssertRailNearHasWafer(false);
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass to CT,Transfer has wafer "));
        }
        if (m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass to CT,CoatTable has wafer "));
        }
        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        Q_ASSERT(pCass);
        CASSSLOT* pSlotCass = pCass->GetFirstUnCutWafer();
        if (!pSlotCass)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass has no wafer"));
        }
        pSlotCass->WPstatus = TOGRAB;
        SlotTransfer(&pSlotCass, &m_pSlotGrab);
        SetWaferId(m_pSlotGrab, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransCasste2CoatStarted);
    }
    else if (iStep == 20)
    {
        //上下料要在等待位置，不然会撞机
        MoveLoadInitPos();
        MoveUnLoadInitPos();
        //TODO:这里如果夹抓不在安全位置会有问题
        MoveVTransPickUpWafer();
    }
    else if (iStep == 30)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS,
                                           CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, m_pSlotGrab->index);
    }
    else if (iStep == 40)    AssertRailNearHasWafer(false);	//规整台上无晶圆
    else if (iStep == 50)  MoveRailNearOpen();
    else if (iStep == 60)   ClawRelease();
    else if (iStep == 61)
    {
        //直接移动到Ready位置，中间不过渡了
        //MoveToPosGrabWaferExistCheck();		//
        MoveHGrabPickUpReadySpd(false);	//移动到取料准备位置
    }
    else if (iStep == 70)	 MoveHGrabPickUpCassSpd();			//移动到取料位置，半速移动
    else if (iStep == 80)   ClawGrabed();
    else if (iStep == 90)   IonBlowOn();			//静电消除器
    else if (iStep == 91)
    {
        m_pSlotGrab->bCanAbort = false;
        MoveHGrabPickUpReadySpd(true);
        //这一句相当于恢复了一下速度

        //先规则一下，再拉过去
        MoveHGrabWaferExistCheck();

        ClawRelease();
        MoveRailNearReadyClose();

        //MoveToPosLockClose();	//闭合进行规整
    }
    else if (iStep == 92)
    {
#ifdef __SIMULATOR__
#else
        //没有晶圆时不检查，直接置0，因为可能拉到了空晶圆
        AssertRailNearCassHasWafer(true);
        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
#endif // __SIMULATOR__
        //再关一次用于检查轴是否报警
        MoveRailNearReadyClose();

        if (m_pSlotGrab)
        {
            ClawGrabed();
        }
        //打开规整轴，再往规整位置拉
        //MoveToPosLockOpen();
        //MoveToPosLockClosePull();
        MoveRailNearPullOpen();
    }
    else if (iStep == 95)
    {
        //扫码
        MoveHGrabBarcode();
        g_SecsManager.SendEvent(EVENT_BarcodeScanStarted);

        m_pSlotGrab->bCanAbort = true;
        CBarCodeDriver* pBarcodeDriver = GET_CARD(BARCODE_DRIVER, CBarCodeDriver);
        try
        {
            //执行扫码
            pBarcodeDriver->GetBarCode(BARCODE);
        }
        catch (const QString& ex)
        {
            MQT_THROW_CODESTR(ALARM_SCAN_COMMUNICATION, QObject::tr("Scan wafter id failed."));
        }

        //更新Wafer ID信息
        m_pSlotGrab->WaferID = pBarcodeDriver->GetBarCode_String(BARCODE);
#ifdef __SIMULATOR__
        m_pSlotGrab->WaferID = QString("WaferId(%1)").arg(m_pSlotGrab->index + 1);
#endif // __SIMULATOR__

        m_pSlotGrab->BeginDate = QDateTime::currentDateTime();
        m_gSystem.SetWaferId(PROCESS_TRANS, m_pSlotGrab);
        SetWaferId(m_pSlotGrab, SVID_ScanWaferID);
        SetWaferId(m_pSlotGrab, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_BarcodeScanComplete);

        m_gSystem.AddProductInfo(m_pSlotGrab, QString("Lot:%1 Wafer ID:%2 \n%3 start trans casste to coattable SLOT:%4").arg(m_gSystem.GetLotId().c_str())
                                 .arg(m_pSlotGrab->WaferID).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(m_pSlotGrab->index + 1));
    }
    else if (iStep == 100)
    {	//准备规整
        MoveRailNearPullClose();
        //少往回拉10mm
        //规整位置--------------
        MoveToPosGrabLock(false, true); //到规整位置
    }
    else if (iStep == 110)  ClawRelease();
    else if (iStep == 115)
    {
        //规整操作
        MoveRailNearReadyClose();
        MoveRailNearClose();

        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_RailWaferFailed_NotExists);
        //检查规整异常
        MoveRailNearClose();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 120)
    {	//移到规整偏移位置,即退开
        MoveToPosGrabLock(true);
    }
    else if (iStep == 125)
    {
        //下降到推晶元位置
        MoveTransVNearPull();
    }
    else if (iStep == 130)
    {
        //规整操作
        MoveRailNearClose();
        MoveRailNearClose();

        //重新定位，移回规整位置
        MoveToPosGrabLock(false);

        //移到准备位置
        //MoveToPosGrabWait();
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 140)
    {
        AssertRailNearHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
        SlotTransfer(&m_pSlotGrab, &m_pSlotRailNear);
    }
    else if (iStep == 160)
    {
        //MoveToPosTransHLock();
        //从规整台取晶圆
        MoveVTransRailNear();
    }
    else if (iStep == 170)
    {
        MoveVTransRailNear(true);
        m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);
        SlotTransfer(&m_pSlotRailNear, &m_pSlotTrans);
        //MoveToPosTransVArrange(true);
        //AssertLockPoshasCell(false);
        //打开一点
        MoveRailNearOpen();
        //移动到上方
        MoveVTransWait();
    }
    else if (iStep == 200)
    {
        MoveRailNearOpenMax(false);
    }
    else if (iStep == 210)
    {
        MoveHGrabToCoat();
        MoveRailNearOpenMax(true);
    }
    else if (iStep == 220)
    {
        ClawGrabed(false);
        //主轴升起
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true);
        //有可能被关掉了，只有手动的情况下才可能
        //pCoat->CloseProtect(false);
        pCoat->SpindleUp(true);
    }
    else if (iStep == 230)
    {
        MoveTransPutDownWafterToCoat();
        SlotTransfer(&m_pSlotTrans, &m_pSlotCoat);
    }
    else if (iStep == 231)
    {
        //提起来
        MoveVTransCoatReadySpd();
        //升起
        MoveVTransWait();
        //打开夹抓
        ClawRelease();
    }
    else if (iStep == 260)
    {
        //TODO:降下主轴可以在这里处理,同时处理
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->SpindleUp(false, true);

        //转移完后回准备点等待
        MoveHGrabWait();

        //检查主轴降下
        pCoat->SpindleUpCheck(false);

        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to coattable")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCasste2CoatComplete);

        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        MqDebug() << "Transfer Finished";

    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}
//涂敷台转移到平台
void CProcess_Trans::TransCoatToWT(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotCoat && !m_pSlotLoad && !m_pSlotWT)
    {
        return;
    }
    if (iStep == 0)
    {
        LOG(INFO) << "TransCoatToWT Start";
#ifdef __SIMULATOR__
        /*if(!m_pSlotCoat){
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to WT,CoatTable has no Wafer"));
        }*/
#else
        AssertRailNearHasWafer(false);
        if (!m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to WT,CoatTable has no Wafer"));
        }
        if (m_gSystem.IsVaccumOn(OUT_LOAD_VACUUM, IN_LOAD_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to WT,Load has  Wafer"));
        }
        if (m_gSystem.CellExist(OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to WT,WorkTable has  Wafer"));
        }
#endif // __SIMULATOR__
        SetWaferId(m_pSlotCoat, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransCoat2WTStarted);
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 start trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 10)  MoveInitPos();
    else if (iStep == 11)
    {
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        //主轴移动到准备位置
        pCoat->MoveSpindleInitPos();
        //手动的情况下有可能被关掉了，则报警提示，然后手动打开即可
        //pCoat->CloseProtect(false);
        //主轴生起
        pCoat->SpindleUp(true);
    }
    else if (iStep == 12)
    {
        LoadPos();
    }
    else if (iStep == 20)  AssertRailNearHasWafer(false);
    else if (iStep == 30)
    {
        MoveRailNearOpenMax(false);
    }
    else if (iStep == 40)
    {
        MoveHLoadRailFar();
        MoveRailNearOpenMax(true);
    }
    else if (iStep == 50)
    {
        //到取晶圆位置
        MoveVLoadRailFar(false);

        VaccumCoatToLoad();

        MoveToPosLoadVCoatFinishLow();
        MoveVLoadRailFar(true);
        //移动到准备位置
        MoveToPosLoadVCoatFinish(true);
        //检查真空状态，如果没有说明取失败
        AssertLoadHasWafer(true);


        SlotTransfer(&m_pSlotCoat, &m_pSlotLoad);


    }
    else if (iStep == 51)
    {
        //移动到准备位置
        MoveVLoadWait();
    }
    //    else if(iStep==100)  LoadPos();
    else if (iStep == 110)  MoveHLoadWT();
    else if (iStep == 120)
    {
        MoveVLoadWT();
        VaccumLoadToWT();
        SlotTransfer(&m_pSlotLoad, &m_pSlotWT);
        MoveVLoadWait();
        MoveHLoadWait(true);
        g_SecsManager.SendEvent(EVENT_TransCoat2WTComplete);

        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 finish trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        LOG(INFO) << "TransCoatToWT Finished";
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}
//从工作转移到清洗台
void CProcess_Trans::TransWTToClean(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotWT && !m_pSlotUnLoad && !m_pSlotClean)
    {
        return;
    }
    if (iStep == 0)
    {
        LOG(INFO) << "TransWTToClean Start";
#ifdef __SIMULATOR__
        if (!m_pSlotWT)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("WT to Clean,WorkTable has no Wafer"));
        }
#else
        if (!m_gSystem.CellExist(OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("WT to Clean,WorkTable has no Wafer"));
        }
        if (m_gSystem.IsVaccumOn(OUT_UNLOAD_VACUUM, IN_UNLOAD_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("WT to Clean,UnLoad has  Wafer"));
        }
        if (m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("WT to Clean,CleanTable has  Wafer"));
        }
#endif
        SetWaferId(m_pSlotWT, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransWT2CleanStarted);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 start trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)  MoveInitPos();
    else if (iStep == 10)  UnloadPos();
    else if (iStep == 15)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, false);
        pClean->CloseProtect(FALSE, false);	//打开防水帘
    }
    else if (iStep == 20)  MoveHUnloadWT();
    else if (iStep == 25)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->Wait_Spindle_finish();
        pClean->SpindleUp(true);
    }
    else if (iStep == 30)
    {
        MoveVUnLoadWT();
        VaccumWtToUnLoad();
        SlotTransfer(&m_pSlotWT, &m_pSlotUnLoad);
        MoveVUnloadWait();

        //HACK:交换方向	

    }
    else if (iStep == 35)
    {
        //TODO:检查是否取晶圆成功
        m_gSystem.IsVaccumOn(OUT_UNLOAD_VACUUM, IN_UNLOAD_VACUUM);
    }
    else if (iStep == 100)  MoveHUnloadRailNear();
    else if (iStep == 110)
    {
        MoveVUnloadRailNear();
        VaccumUnLoadToClean();
        SlotTransfer(&m_pSlotUnLoad, &m_pSlotClean);
        MoveVUnloadWait();
    }
    else if (iStep == 120)
    {
        MoveHUnloadWait();
    }
    else if (iStep == 130)
    {
        //TODO:清洗降下主轴可以在这里同时处理
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->SpindleUp(false, true);

        LoadPos();

        pClean->SpindleUpCheck(false);

        g_SecsManager.SendEvent(EVENT_TransWT2CleanComplete);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 finish trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        LOG(INFO) << "TransWTToClean Finished";
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}
//清洗台到料盒
void CProcess_Trans::TransCleanToCass(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotClean && !m_pSlotTrans && !m_pSlotRailNear)
    {
        //如果Clean Trans Arrange都没有料
        return;
    }
    if (iStep == 0)
    {
        LOG(INFO) << "TransCleanToCass Start";
#ifdef __SIMULATOR__
#else
        if (!m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to Cass,CleanTable has no Wafer"));
        }
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to Cass,Trans has  Wafer"));
        }
        AssertRailNearHasWafer(false);
#endif
        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 start trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransClean2CassteStarted);
    }
    else if (iStep == 5)  MoveInitPos();
    else if (iStep == 10)  AssertRailNearHasWafer(false);
    else if (iStep == 15)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        //      pClean->MoveSpindleInitPos();
              //pClean->SpindleUp(true);
        pClean->MoveSpindleInitPos(true, false);
        pClean->CloseProtect(FALSE, false);	//打开防水帘
    }
    else if (iStep == 20)
    {
        ClawGrabed(false);
        MoveHGrabToClean();
    }
    else if (iStep == 25)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->Wait_Spindle_finish();
        pClean->SpindleUp(true);
    }
    else if (iStep == 30)
    {
        LOG(INFO) << "Clean To Trans Start";

        MoveTransPickUpWaferFromClean();

        SlotTransfer(&m_pSlotClean, &m_pSlotTrans);

        LOG(INFO) << "Clean To Trans Finish";
    }
    else if (iStep == 40)
    {
        int timeMs = m_Variants.get_VData(Var_Process_Trans_CleanGetWaferWaitTimeMs)->toInt();
        if (timeMs > 0)
        {
            MSleep(timeMs);
        }
    }
    else if (iStep == 50)
    {
        LOG(INFO) << "Trans To Wait Pos";

        MoveVTransWait();
        ClawRelease();//TODO:夹抓打开

        LOG(INFO) << "Trans To Wait Pos Finish";
    }
    else if (iStep == 100)  MoveVTransRailNear();
    else if (iStep == 110)  MoveRailNearOpen();
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM);
        m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
        MoveVTransWait();
    }
    //不检查有没有晶圆
    else if (iStep == 130)
    {
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
        AssertRailNearHasWafer(true, ALARM_TRANS_ERROR_TransPutWaferFailed_NotExists);
    }
    //else if(iStep==140) MoveToPosGrabWait();
    else if (iStep == 140)
    {
        //移动到准备下料的位置，然后往前推
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 150) MoveTransVNearPull();
    else if (iStep == 160) ClawRelease(); //再次打开夹抓
    else if (iStep == 170)
    {
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
    }
    else if (iStep == 180)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, m_pSlotRailNear->index);
    }
    else if (iStep == 190)
    {
        MoveHGrabBarcode();
        MoveRailNearClose();
    }
    else if (iStep == 195)
    {
        MoveHGrabPutDownToCassSpd();
    }
    else if (iStep == 200)
    {
        //        MoveToPosGrabWait();
        //        MoveToPosTransVWait();
                 //MoveToPosGrabWaferExistCheck();
        MoveVTransRailNear();
    }
    else if (iStep == 210)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotGrab);
        CASSSLOT* pSlot = m_pSlotGrab;
        int iSlotID = pSlot->index + 1;
        pSlot->EndDate = QDateTime::currentDateTime();

        m_gSystem.m_iTotalCuttedWafer++;
        QTime tmpTime;
        tmpTime.setHMS(0, 0, 0, 0);                                       //初始化数据，时 分 秒 毫秒
        int secsCount = pSlot->BeginDate.secsTo(pSlot->EndDate);
        QString str = QObject::trUtf8("WaferID:%4,DID:%2,TM:%3,DNo:%1")
            .arg(m_gSystem.GetCurFile())
            .arg(iSlotID)
            .arg(tmpTime.addSecs(secsCount).toString("hh:mm:ss"))
            .arg(pSlot->WaferID);
        m_gSystem.EvtLog(QString::fromUtf8("JOB"), str);
        m_pSlotGrab = 0;

        g_SecsManager.SendEvent(EVENT_TransClean2CassteComplete);
        m_gSystem.AddProductInfo(pSlot, QString("%1 finish trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

        m_gSystem.AddProductInfo(pSlot, QString("Job finish %1\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

        LOG(INFO) << "TransCleanToCass Finished";
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCleanToCheckBox(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotClean && !m_pSlotTrans && !m_pSlotRailNear)
    {
        return;
    }
    if (iStep == 0)
    {

        LOG(INFO) << "TransCleanToCheckBox Start";
#ifdef __SIMULATOR__
#else
        if (!m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to CheckBox,CleanTable has no Wafer"));
        }
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to CheckBox,Trans has  Wafer"));
        }
        AssertRailNearHasWafer(false);
        AssertCheckBoxhasCell(false);
#endif // __SIMULATOR__
        SetWaferId(m_pSlotClean, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransClean2CupboardStarted);
        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 start trans wafer cleantable to cupboard").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)
    {
        MoveInitPos();
    }
    else if (iStep == 10)  AssertRailNearHasWafer(false);
    else if (iStep == 11)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos();
        pClean->SpindleUp(true);
    }
    else if (iStep == 20)
    {
        ClawGrabed(false);
        MoveHGrabToClean();
    }
    else if (iStep == 30)
    {
        LOG(INFO) << "Clean To Trans Start";
        MoveTransPickUpWaferFromClean();

        SlotTransfer(&m_pSlotClean, &m_pSlotTrans);

        LOG(INFO) << "Clean To Trans Finished";
    }
    else if (iStep == 40)
    {
        int timeMs = m_Variants.get_VData(Var_Process_Trans_CleanGetWaferWaitTimeMs)->toInt();
        if (timeMs > 0)
        {
            MSleep(timeMs);
        }
    }
    if (iStep == 50)
    {
        LOG(INFO) << "Trans To Wait Pos";

        MoveVTransWait();
        ClawRelease();

        LOG(INFO) << "Trans To Wait Pos Finished";
    }
    else if (iStep == 100)  MoveVTransRailNear();
    else if (iStep == 110)  MoveRailNearOpen();
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM);
        m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
        ClawRelease();
        MoveVTransWait();
    }
    else if (iStep == 130)
    {
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
        AssertRailNearHasWafer(true, ALARM_TRANS_ERROR_TransPutWaferFailed_NotExists);
    }
    //else if(iStep==140) MoveToPosGrabWait();
    else if (iStep == 140)
    {
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 150) MoveVTransPickUpWafer();
    else if (iStep == 160) ClawRelease();
    else if (iStep == 170)
    {
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
    }
    else if (iStep == 180)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, -1);
    }
    else if (iStep == 181)
    {
        MoveHGrabBarcode();
        MoveRailNearClose();
    }
    else if (iStep == 185) MoveHGrabPickUpReadySpd(false);
    else if (iStep == 190) MoveHGrabPutDownToCassSpd();
    else if (iStep == 200)
    {
        //        MoveToPosGrabWait();
        //        MoveToPosTransVWait();

                //MoveToPosGrabWaferExistCheck();
        MoveVTransRailNear();
    }
    else if (iStep == 210)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotCheckBox);
        if (m_pSlotCheckBox->bNeedCheckCut)
        {
            m_pSlotCheckBox->CheckStatus = CHECKCUTING;
            SetWaferIdEmpty(SVID_TransWaferID);
            SetWaferId(m_pSlotCheckBox, SVID_CuttingCheckWaferID);
        }

        CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                           CProcess_Scan);
        pCass->CassUp(CASSETTE);

        m_gSystem.AddProductInfo(m_pSlotCheckBox, QString("%1 finish trans wafer cleantable to cupboard").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransClean2CupboardComplete);

        LOG(INFO) << "TransCleanToCheckBox Finished";
    }

    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}


void CProcess_Trans::TransCoatToCheckBox(int iStep)
{
    //从涂覆台转移到料盒
    bool bemptystep = false;
    if (!m_pSlotCoat && !m_pSlotTrans && !m_pSlotRailNear)
    {
        return;
    }
    if (iStep == 0)
    {
        LOG(INFO) << "TransCoatToCheckBox Start";
        //检查轨道是否有晶圆
        AssertRailNearHasWafer(false);
        AssertCheckBoxhasCell(false);
#ifdef __SIMULATOR__
#else
        //检查涂覆台是否有晶圆
        if (!m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,CoatTable has no Wafer"));
        }
        //检查转移平台是否有晶圆
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,Trans has  Wafer"));
        }
#endif // __SIMULATOR__
        SetWaferId(m_pSlotCoat, SVID_TransWaferID);
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 start trans wafer coat to cupboard").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)
    {
        //转移的相关轴都移动到安全位置
        MoveInitPos();
    }
    else if (iStep == 10)  AssertRailNearHasWafer(false);
    else if (iStep == 15)
    {
        //主轴升起
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos();
        //手动的情况下有可能被关掉了，则手动打开即可
        //pCoat->CloseProtect(false);
        pCoat->SpindleUp(true);
    }
    else if (iStep == 20)
    {
        MoveRailNearOpenMax(false);
        ClawGrabed(false);
        MoveHGrabToCoat();
    }
    else if (iStep == 25) MoveRailNearOpenMax(true);
    else if (iStep == 30)
    {
        MoveTransPickUpWaferFromCoat();

        SlotTransfer(&m_pSlotCoat, &m_pSlotTrans);
    }
    else if (iStep == 50)
    {
        MoveVTransWait();

        AssertTransHasWafer(true);
        ClawRelease();
    }
    //else if(iStep==100)  MoveToPosTransHCoat();
    else if (iStep == 100) MoveVTransRailNear();
    else if (iStep == 110)  MoveRailNearOpen();
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);
        m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
        MoveVTransWait();
    }
    //不检查有没有晶圆
    else if (iStep == 130)
    {
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
        AssertRailNearHasWafer(true, ALARM_TRANS_ERROR_TransPutWaferFailed_NotExists);
    }
    else if (iStep == 140)
    {
        //MoveToPosGrabWait();
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 145)
    {
        MoveRailNearReadyClose();
    }
    else if (iStep == 150) MoveTransVNearPull();
    else if (iStep == 160) ClawRelease();
    else if (iStep == 170)
    {
        MoveHGrabBarcode();
        MoveRailNearClose();
    }
    else if (iStep == 180)
    {
        //料盒到位
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN, SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, -1);
    }
    else if (iStep == 190)
    {
        //放到料盒中
        MoveHGrabPutDownToCassSpd();
    }
    else if (iStep == 200)
    {
        //MoveToPosGrabWaferExistCheck();
        MoveVTransRailNear();
    }
    else if (iStep == 210)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotCheckBox);
        if (m_pSlotCheckBox->bNeedCheckCoat)
        {
            m_pSlotCheckBox->CheckStatus = CHECKCOATING;
            SetWaferIdEmpty(SVID_TransWaferID);
            SetWaferId(m_pSlotCheckBox, SVID_CoatingQualityCheckWaferID);
        }
        CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                           CProcess_Scan);
        pCass->CassUp(CASSETTE);

        m_gSystem.AddProductInfo(m_pSlotCheckBox, QString("%1 finish trans wafer coat to cupboard").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

        LOG(INFO) << "TransCoatToCheckBox Finished";
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCoatToCass(int iStep)
{
    //从涂覆台转移到料盒
    bool bemptystep = false;
    //TODO:判定条件？？？
    if (!m_pSlotCoat && !m_pSlotTrans && !m_pSlotRailNear)
    {
        return;
    }
    if (iStep == 0)
    {
        //检查轨道是否有晶圆
        AssertRailNearHasWafer(false);
        //检查涂覆台是否有晶圆
        if (!m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,CoatTable has no Wafer"));
        }
        //检查转移平台是否有晶圆
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,Trans has  Wafer"));
        }
    }
    else if (iStep == 5)
    {
        //转移的相关轴都移动到安全位置
        MoveInitPos();
    }
    else if (iStep == 10)  AssertRailNearHasWafer(false);
    else if (iStep == 15)
    {
        //主轴升起
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos();
        //手动的情况下有可能被关掉了，则手动打开即可
        //pCoat->CloseProtect(false);
        pCoat->SpindleUp(true);
    }
    else if (iStep == 20)
    {
        ClawGrabed(false);
        MoveRailNearOpenMax(false);
        MoveHGrabToCoat();
    }
    else if (iStep == 25) MoveRailNearOpenMax(true);
    else if (iStep == 30)
    {
        MoveTransPickUpWaferFromCoat();

        SlotTransfer(&m_pSlotCoat, &m_pSlotTrans);

    }
    else if (iStep == 50)
    {
        MoveVTransWait();
        AssertTransHasWafer(true);
        ClawRelease();
    }
    //else if(iStep==100)  MoveToPosTransHCoat();
    else if (iStep == 100) MoveVTransRailNear();
    else if (iStep == 110)  MoveRailNearOpen();
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);
        m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
        MoveVTransWait();
    }
    //检查有没有晶圆
    else if (iStep == 130)
    {
        AssertRailNearHasWafer(true, ALARM_TRANS_ERROR_TransPutWaferFailed_NotExists);
    }
    else if (iStep == 140)
    {
        //MoveToPosGrabWait();
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 150) MoveTransVNearPull();
    else if (iStep == 160) ClawRelease();
    else if (iStep == 170) MoveRailNearClose();
    else if (iStep == 180)
    {
        //料盒到位
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN, SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, m_pSlotRailNear->index);
    }
    else if (iStep == 190)
    {
        //放到料盒中
        MoveHGrabPutDownToCassSpd();
    }
    else if (iStep == 200)
    {
        //MoveToPosGrabWaferExistCheck();
        MoveVTransRailNear();
    }
    else if (iStep == 210)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotGrab);
        CASSSLOT* pSlot = m_pSlotGrab;
        int iSlotID = pSlot->index + 1;
        pSlot->EndDate = QDateTime::currentDateTime();

        m_gSystem.m_iTotalCuttedWafer++;
        QTime tmpTime;
        tmpTime.setHMS(0, 0, 0, 0);                                       //初始化数据，时 分 秒 毫秒
        int secsCount = pSlot->BeginDate.secsTo(pSlot->EndDate);
        QString str = QObject::trUtf8("WaferID:%4,DID:%2,TM:%3,DNo:%1")
            .arg(m_gSystem.GetCurFile())
            .arg(iSlotID)
            .arg(tmpTime.addSecs(secsCount).toString("hh:mm:ss")
                 .arg(pSlot->WaferID));
        m_gSystem.EvtLog(QString::fromUtf8("JOB"), str);

        m_pSlotGrab = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCoatToClean(int iStep)
{
    //从涂覆台转移到料盒
    bool bemptystep = false;
    //TODO:判定条件？？？
    if (!m_pSlotCoat && !m_pSlotTrans && !m_pSlotClean)
    {
        return;
    }
    if (iStep == 0)
    {
#ifdef __SIMULATOR__
#else
        //检查轨道是否有晶圆
        AssertRailNearHasWafer(false);
        //检查涂覆台是否有晶圆
        if (!m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,CoatTable has no Wafer"));
        }
        //检查转移平台是否有晶圆
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Cass,Trans has  Wafer"));
        }
        //检查清洗平台是否有晶圆
        if (m_gSystem.IsVaccumOn(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat to Clean,CleanTable has  Wafer"));
        }
#endif // __SIMULATOR__
    }
    else if (iStep == 5)
    {
        //转移的相关轴都移动到安全位置
        MoveInitPos();
    }
    else if (iStep == 10)  AssertRailNearHasWafer(false);
    else if (iStep == 14)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, false);
        pClean->CloseProtect(FALSE, false);	//打开防水帘
    }
    else if (iStep == 15)
    {
        //主轴升起
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos();
        //手动的情况下有可能被关掉了，则手动打开即可
        pCoat->CloseProtect(false);
        pCoat->SpindleUp(true);
    }
    else if (iStep == 20)
    {
        ClawGrabed(false);
        MoveRailNearOpenMax(false);
        MoveHGrabToCoat();
    }
    else if (iStep == 21)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->Wait_Spindle_finish();
        pClean->SpindleUp(true);
    }
    else if (iStep == 25) MoveRailNearOpenMax(true);
    else if (iStep == 30)
    {
        MoveTransPickUpWaferFromCoat();

        SlotTransfer(&m_pSlotCoat, &m_pSlotTrans);
    }
    else if (iStep == 35)
    {
        //提起来
        MoveVTransWait();
        //ClawRelease();
    }
    else if (iStep == 100)  MoveHGrabToCoat();
    //else if(iStep==110)  MoveToPosLockOpen();
    //else if(iStep==120) 
    //{
    //	//晶圆已经提起来了
    //	MoveToPosTransVWait();	
    //}
    else if (iStep == 130)
    {
        ClawGrabed(false);
        MoveHGrabToClean();	//移动到放料位置
    }
    else if (iStep == 135)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos();
        pClean->CloseProtect(FALSE);	//打开防水帘
    }
    else if (iStep == 140)
    {
        //闭合夹抓
        ClawGrabed(false);

        //全速移动到准备位置,如果在Finish位置下方，则仍然是慢速移动
        MoveVTransCleanReady(false);

        //半速移动到清洗台
        MoveVTransClean(true);

        //真空操作
        VaccumTransToClean();

        //慢速回到准备位置
        MoveVTransCleanReady();


        SlotTransfer(&m_pSlotTrans, &m_pSlotClean);
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
        ClawRelease();
    }
    else if (iStep == 200)
    {
        MoveHGrabWait();
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCheckBoxToCoat(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotGrab && !m_pSlotRailNear &&
        !m_pSlotTrans && !m_pSlotCoat && !m_pSlotCheckBox
        && iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
#ifdef __SIMULATOR__
#else
        AssertCheckBoxhasCell(true);
        AssertRailNearHasWafer(false);
#endif // __SIMULATOR__
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass to CT,Transfer has wafer "));
        }
        if (m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass to CT,CoatTable has wafer "));
        }

        if (m_pSlotRailNear)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Arrange status has wafer"));
        }
        if (m_pSlotGrab)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Grab status has wafer"));
        }
        if (m_pSlotTrans)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Trans status has wafer"));
        }
        if (m_pSlotCoat)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Coat status has wafer"));
        }

        //检查料盒有没有料
        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        Q_ASSERT(pCass);
        if (!m_pSlotCheckBox)
        {

            CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
            Q_ASSERT(pDriver);
            bool bhas = pDriver->get_iodata(IO_INPUT, IN_CHECKBOX_HAS_WAFER_LEFT, true);
            if (bhas)
            {
                m_pSlotCheckBox = new CASSSLOT();
                m_pSlotCheckBox->bEnableCut = false;
            }
            else
            {
                m_gSystem.m_SysMsg.SetMsg(QObject::tr("check box do not has wafer."));
                return;
            }
        }

        m_pSlotCheckBox->WPstatus = TOGRAB;
        SlotTransfer(&m_pSlotCheckBox, &m_pSlotGrab);
        m_gSystem.AddProductInfo(m_pSlotGrab, QString("%1 start trans wafer cupboard to coat").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 20)
    {
        //上下料要在等待位置，不然会撞机
        MoveLoadInitPos();
        MoveUnLoadInitPos();
        MoveVTransPickUpWafer();
    }
    else if (iStep == 30)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS,
                                           CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, -1);
    }
    else if (iStep == 40)    AssertRailNearHasWafer(false);	//规整台上无晶圆
    else if (iStep == 50)  MoveRailNearOpen();
    else if (iStep == 60)   ClawRelease();
    else if (iStep == 61)
    {
        //直接移动到Ready位置，中间不过渡了
        //MoveToPosGrabWaferExistCheck();		//
        MoveHGrabPickUpReadySpd(false);	//移动到取料准备位置
    }
    else if (iStep == 70)	 MoveHGrabPickUpCassSpd();			//移动到取料位置，半速移动
    else if (iStep == 80)   ClawGrabed();
    else if (iStep == 90)   IonBlowOn();			//静电消除器
    else if (iStep == 91)
    {
        m_pSlotGrab->bCanAbort = false;
        MoveHGrabPickUpReadySpd(true);
        //这一句相当于恢复了一下速度
        MoveHGrabPickUpReadySpd(false);

        //先规则一下，再拉过去
        MoveHGrabWaferExistCheck();

        ClawRelease();
        MoveRailNearReadyClose();
        //MoveToPosLockClose();	//闭合进行规整
    }
    else if (iStep == 92)
    {
#ifdef __SIMULATOR__
#else
        //从CheckBox拉，一定是有晶圆的，因为前面已经检查过了
        AssertRailNearCassHasWafer(true);
        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
#endif // __SIMULATOR__
        //处理轴报警的情况
        MoveRailNearReadyClose();
        if (m_pSlotGrab)
        {
            ClawGrabed();
        }
        //打开规整轴，再往规整位置拉
        //MoveToPosLockOpen();
        //MoveToPosLockClosePull();
        MoveRailNearPullOpen();
    }
    else if (iStep == 93)
    {

    }
    else if (iStep == 94)
    {
        //扫码
        MoveHGrabBarcode();

        m_pSlotGrab->bCanAbort = true;

        if (m_pSlotGrab->CheckStatus != CHECKCOATFINISHED)
        {
            //执行
            CBarCodeDriver* pBarcodeDriver = GET_CARD(BARCODE_DRIVER, CBarCodeDriver);
            pBarcodeDriver->GetBarCode(BARCODE);

            //更新Wafer ID信息
            m_pSlotGrab->WaferID = pBarcodeDriver->GetBarCode_String(BARCODE);
        }
        else
        {

            //执行
            CBarCodeDriver* pBarcodeDriver = GET_CARD(BARCODE_DRIVER, CBarCodeDriver);
            pBarcodeDriver->GetBarCode(BARCODE);
#ifdef __SIMULATOR__
#else
            if (m_pSlotGrab->WaferID != pBarcodeDriver->GetBarCode_String(BARCODE))
            {
                MQT_THROW_CODESTR(ALARM_TRANS_ERROR_CHECKBOX_WAFERID_NotConsistent, QObject::tr("The wafer id in Checkbox was inconsistent with the scan,please check Wafer direction."));
            }
#endif // __SIMULATOR__		
        }
    }
    //拉到规整位置
    else if (iStep == 100)
    {
        MoveRailNearPullClose();
        //少往回拉10mm
        MoveToPosGrabLock(false, true); //到规整位置
    }
    else if (iStep == 110)  ClawRelease();
    else if (iStep == 115)
    {
        MoveRailNearClose();
        MoveRailNearClose();

        //如果第二个传感器没信号就报警
        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_RailWaferFailed_NotExists);
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 120)
    {	//移到规整偏移位置,即退开
        MoveToPosGrabLock(true);
    }
    else if (iStep == 125)
    {
        //下降到推晶元位置
        MoveTransVNearPull();
    }
    else if (iStep == 130)
    {
        //规整操作
        MoveRailNearClose();

        //重新定位
        MoveToPosGrabLock(false);

        //移到准备位置
        //MoveToPosGrabWait();
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 140)
    {
#ifndef __IGNORE_PUTWAFER_CHECKED__
        AssertRailNearHasWafer(true);
#endif
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
        SlotTransfer(&m_pSlotGrab, &m_pSlotRailNear);
    }
    else if (iStep == 160)
    {
        //MoveToPosTransHLock();
        //从规整台取晶圆
        MoveVTransRailNear();
        //MoveToPosTransHCoat();
    }
    else if (iStep == 170)
    {
        MoveVTransRailNear();
        m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);
        SlotTransfer(&m_pSlotRailNear, &m_pSlotTrans);
        //MoveToPosTransVArrange(true);
        //AssertLockPoshasCell(false);
        //打开一点
        MoveRailNearOpen();
        //移动到上方
        MoveVTransWait();
    }
    else if (iStep == 200)
    {
        ClawGrabed(false);
        MoveRailNearOpenMax(false);
    }
    else if (iStep == 210)
    {
        MoveHGrabToCoat();
        MoveRailNearOpenMax(true);
    }
    else if (iStep == 220)
    {
        //主轴升起
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true);
        //有可能被关掉了，只有手动的情况下才可能
        //pCoat->CloseProtect(false);
        pCoat->SpindleUp(true);
    }
    else if (iStep == 230)
    {
        MoveTransPutDownWafterToCoat();
        SlotTransfer(&m_pSlotTrans, &m_pSlotCoat);
    }
    else if (iStep == 240)
    {
        if (m_pSlotCoat->CheckStatus == CHECKCOATFINISHED)
        {
            m_pSlotCoat->WPstatus = WPCOATFINISH;
        }
        //升起
        MoveVTransWait();
        //打开夹抓
        ClawRelease();
    }
    else if (iStep == 260)
    {
        if (m_pSlotCoat->WPstatus != WPCOATFINISH)
        {
            //TODO:降下主轴可以在这里处理,同时处理
            CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
            pCoat->SpindleUp(false, true);
        }

        //转移完后回准备点等待
        MoveHGrabWait();
        if (m_pSlotCoat->WPstatus != WPCOATFINISH)
        {
            //检查主轴降下
            CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
            pCoat->SpindleUpCheck(false);
        }

        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer cupboard to coat").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}
#endif
void CProcess_Trans::TransCheckBoxToCass(int iStep, bool bIsAutoMode)
{
    //从CheckBox料盒取料
    bool bemptystep = false;
    if (!m_pSlotCheckBox && !m_pSlotRailNear && !m_pSlotGrab)
    {
        if (iStep == 0)
        {
            m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("No wafer to transfer")
                                      .arg(m_sName));
            MSleep(500);
        }
        return;
    }
    if (iStep == 0)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, "not surpport this operation");
        LOG_INFO("TransCheckBoxToCass Start");
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM))
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass to CheckBox,Trans has  Wafer"));
        }

        QString sTransInfo = QObject::tr("Trans Checkbox to Cass");
        AssertRailNearHasWafer(false, sTransInfo);
        AssertCheckBoxhasCell(true, sTransInfo);

        if (m_pSlotCheckBox == nullptr)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("check box do not has wafer."));
        }

        SetWaferId(m_pSlotCheckBox, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransCupboard2CassteStarted);

        m_gSystem.AddProductInfo(m_pSlotCheckBox, QString("%1 start trans wafer cupboard to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

		IonBlowOn(IonTrans);	//D中转静电消除开
		IonBlowOn(IonEntrance);	//入口静电消除开
    }
    else if (iStep == 5)
    {
        //MoveInitPos();
        MoveLoadInitPos();
        MoveUnLoadInitPos();
    }
    else if (iStep == 20)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, -1);
    }
    else if (iStep == 30)  MoveRailNearOpen();
    else if (iStep == 40)  AssertRailNearHasWafer(false, QObject::tr("Trans Checkbox to Cass"));
    else if (iStep == 41) MoveHGrabWaferExistCheck(); //先移动到过渡位置
    else if (iStep == 45) MoveVTransPickUpWafer();			//降下来
    else if (iStep == 46)
    {
        MoveHGrabPickUpReadySpd(false);
    }
    else if (iStep == 50)
    {
        //取晶圆位置
        MoveHGrabPickUpCassSpd();	//慢速
    }
    else if (iStep == 60)  ClawGrabed();
    else if (iStep == 61)
    {
        SlotTransfer(&m_pSlotCheckBox, &m_pSlotGrab);
    }
    else if (iStep == 65)
    {
        m_pSlotGrab->bCanAbort = false;
        MoveHGrabPickUpReadySpd(true);
        //这一句相当于恢复了一下速度
        MoveHGrabPickUpReadySpd(false);

        //先规则一下，再拉过去,移动到中间传感器位置
        MoveHGrabWaferExistCheck();

        //打开夹抓，规整
        ClawRelease();

        //MoveToPosLockClose();	//闭合进行规整
        MoveRailNearReadyClose();

        //等一下,规整需要花时间
        MSleep(500);
    }
    else if (iStep == 66)
    {
        //规整后没发现晶圆，则报警
        AssertRailNearCassHasWafer(true);
        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);

        MoveRailNearReadyClose();

        ClawGrabed();

        //打开规整轴，再往后面拉
        //MoveToPosLockOpen();
        MoveRailNearPullOpen();
        //MoveToPosLockClosePull();
    }
    else if (iStep == 70)
    {
        //到扫码位置再夹紧一点再往后拉
        MoveHGrabBarcode();
        MoveRailNearPullClose();
    }
    else if (iStep == 75)
    {
        //不需要拉到规整位置
        MoveHGrabBarcode();
        //MoveToPosGrabLock(false, true);
    }
    else if (iStep == 80)
    {
        ClawRelease();
        MoveRailNearReadyClose();
        MoveRailNearReadyClose();
        //MoveToPosLockClose();
        //AssertLockPoshasCell(true, ALARM_TRANS_ERROR_RailWaferFailed_NotExists);
        AssertRailNearLocationHasWafer(true);

        SlotTransfer(&m_pSlotGrab, &m_pSlotRailNear);
    }
    else if (iStep == 90)
    {
        //到规整准备位置,退开
        //MoveToPosGrabLock(true);
    }
    else if (iStep == 95)
    {
        //到推晶圆位置
        MoveTransVNearPull();
    }
    else if (iStep == 100)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, m_pSlotRailNear->index);
    }
    else if (iStep == 105)
    {
        //降到推晶圆位置，打开夹抓往前推
        ClawRelease();
        //MoveToPosGrabLock(true);
        MoveTransVNearPull();
        //MoveToPosLockClose();
    }
    else if (iStep == 106)
    {
        MoveHGrabBarcode();
        MoveRailNearClose();
    }
    else if (iStep == 110)
    {
        MoveHGrabPutDownToCassSpd();
    }
    else if (iStep == 115)
    {
        //MoveToPosGrabWaferExistCheck(); 
        MoveVTransRailNear();//到轨道放晶圆的位置准备
    }
    else if (iStep == 120)
    {
		IonBlowOff(IonEntrance);	//入口静电消除关
		IonBlowOff(IonTrans);		//D中转静电消除关

        SlotTransfer(&m_pSlotRailNear, &m_pSlotGrab);
        CASSSLOT* pSlot = m_pSlotGrab;

        //首片检查完毕
        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        if (pCass->IsSlotFirstInCass(pSlot))
        {
            pCass->SetFirstCheckFinished(true);
        }
        int iSlotID = pSlot->index + 1;
        pSlot->EndDate = QDateTime::currentDateTime();

        m_gSystem.m_iTotalCuttedWafer++;
        QTime tmpTime;
        tmpTime.setHMS(0, 0, 0, 0);                                       //初始化数据，时 分 秒 毫秒
        int secsCount = pSlot->BeginDate.secsTo(pSlot->EndDate);
        QString str = QObject::trUtf8("WaferID:%4,DID:%2,TM:%3,DNo:%1")
            .arg(m_gSystem.GetCurFile())
            .arg(iSlotID)
            .arg(tmpTime.addSecs(secsCount).toString("hh:mm:ss")
                 .arg(pSlot->WaferID));
        m_gSystem.EvtLog(QString::fromUtf8("JOB"), str);

        //结束
        m_pSlotGrab = 0;

        m_gSystem.AddProductInfo(pSlot, QString("%1 finish trans wafer cupboard to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        m_gSystem.AddProductInfo(pSlot, QString("Job finish %1\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCupboard2CassteComplete);
        LOG_INFO("TransCheckBoxToCass Finished");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}
void CProcess_Trans::AbortGrab(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotGrab)
    {
        //如果没有则直接返回了
        return;
    }
    //TODO:如果还没有从料盒拉出来，则可能在Step20有撞机风险
    //TODO:注意需要先退开，夹抓回到准备位置
    if (iStep == 0)
    {
        if (m_pSlotGrab->bCanAbort == false)
        {
            MQT_THROW_STR(QObject::trUtf8("current pos can't auto unload wafer, please check rail and cass"));
        }
        ClawRelease();
    }
    else if (iStep == 10) MoveRailNearClose();
    else if (iStep == 20)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, m_pSlotGrab->index);
    }
    else if (iStep == 40) MoveHGrabPutDownToCassSpd();
    else if (iStep == 50) MoveHGrabWait();
    else if (iStep == 60) MoveVTransWait();
    else if (iStep == 70)
    {
        m_pSlotGrab->WPstatus = WPABORT; m_pSlotGrab = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortArrange(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear)
    {
        return;
    }
    if (iStep == 0)        MoveInitPos();
    else if (iStep == 10)  MoveHGrabWait();
    else if (iStep == 20)  MoveVTransPickUpWafer();
    else if (iStep == 30)
    {
        m_pSlotGrab = m_pSlotRailNear; m_pSlotRailNear = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortTrans(int iStep)
{
    //转移平台上的直接放到轨道上
    bool bemptystep = false;
    if (!m_pSlotTrans && !m_pSlotRailNear 
        && iStep > 0)
    {
        return;
    }
	
	if (iStep == 0)
	{
		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailNear | kAreaClean | kAreaCoat, "");
		AssertRailNearHasWafer(false, QObject::tr("AbortTrans"));
		AssertTransHasWafer(true, QObject::tr("AbortTrans"));
	}
    else if (iStep == 10) MoveVTransWait();
    else if (iStep == 20) MoveHGrabToRailNear(true);
    else if (iStep == 30) MoveRailNearOpen();
    else if (iStep == 40) MoveVTransRailNear();
    else if (iStep == 50)
    {
        VaccumTransToRail();
        
    }
	else if (iStep == 80)
	{
		MoveVTransWait();
		MoveHGrabWait();
	}
    else if (iStep == 100)
    {
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
    }
	else if (iStep == 120)
	{
		ReleaseRes(SM_TRANS, kResTransfer | kResRailNear | kAreaClean | kAreaCoat);
	}
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortCoat(int iStep)
{
    return;
    //Coat就放到Trans上
    bool bemptystep = false;
    if (!m_pSlotCoat && !m_pSlotTrans)
    {
        return;
    }
    if (iStep == 0)       AssertRailNearHasWafer(false, QObject::tr("AbortCoat"));
    else if (iStep == 10)
    {
        MoveVTransWait();
        MoveRailNearOpenMax(false);
        ClawGrabed(false);
    }
    else if (iStep == 20) MoveHGrabToCoat();
    else if (iStep == 30) MoveRailNearOpenMax(true);
    else if (iStep == 40)
    {
        MoveTransPickUpWaferFromCoat();
        m_pSlotTrans = m_pSlotCoat;
    }
    else if (iStep == 50)
    {
        MoveVTransWait();
        ClawRelease();
    }
    //else if(iStep==60) {m_pSlotCoat=0;}
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortLoad(int iStep)
{
    //上料平台就放到WT上
    bool bemptystep = false;
    if (!m_pSlotLoad && !m_pSlotRailFar && iStep > 0)
    {
        return;
    }

	if (iStep == 0)
	{
		AssertAcuireRes(SM_TRANS, kResLoad | kResTransfer | kAreaCoat | kResRailFar, "");
		AssertRailFarHasWafer(false, QObject::tr("AbortLoad"));
		AssertLoadHasWafer(true, QObject::tr("AbortLoad"));
	}
    else if (iStep == 10) MoveVLoadWait();
    else if (iStep == 20) MoveHLoadWait(true);
    else if (iStep == 40) MoveHLoadRailFar();
    else if (iStep == 50)
    {
    }
	else if (iStep == 60)
	{
        MoveRailFarOpen(false);
        MoveHLoadRailFar();
	}
	else if (iStep == 80)
	{
        MoveRailFarOpen(true);
	}
	else if (iStep == 100)
	{
        MoveVLoadRailFar();
	}
    else if (iStep == 120)
    {
        VaccumTransToRail();
        SlotTransfer(&m_pSlotUnLoad, &m_pSlotRailFar);
    }
	else if (iStep == 150)
	{
    }
    else if(iStep == 160)
    {
        MoveVLoadWait();
        MoveHLoadWait(true);
        ReleaseRes(SM_TRANS, kResLoad | kResTransfer | kAreaCoat | kResRailFar);
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortWT(int iStep)
{
    //平台上由Load取走
    bool bemptystep = false;
    if (!m_pSlotWT)
    {
        return;
    }
    if (iStep == 0)       MoveLoadInitPos();
    else if (iStep == 10) MoveUnLoadInitPos();
    else if (iStep == 20) LoadPos();
    else if (iStep == 30) MoveVLoadWT();
    else if (iStep == 40)
    {
        VaccumWTToLoad();
        MoveVLoadWait();
    }
    else if (iStep == 50)
    {
        m_pSlotLoad = m_pSlotWT; m_pSlotWT = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortUnLoad(int iStep)
{
    //下料平台直接放到Near上
    bool bemptystep = false;
    if (!m_pSlotUnLoad && !m_pSlotRailNear 
        && iStep > 0)
    {
        return;
    }

	if (iStep == 0)
	{
		AssertAcuireRes(SM_TRANS, kResTransfer | kResUnload | kResRailNear | kAreaClean, "");
		AssertRailNearHasWafer(false, QObject::tr("AbortUnload"));
		AssertUnloadHasWafer(true, QObject::tr("AbortUnload"));
	}
    else if (iStep == 10)  MoveVUnloadWait();
    else if (iStep == 20) MoveHUnloadRailNear();
    else if (iStep == 30) MoveRailNearOpen();
	else if (iStep == 40)
    {
		MoveVUnloadRailNear();
		VaccumUnloadToRail();
		SlotTransfer(&m_pSlotUnLoad, &m_pSlotRailNear);
    }
	else if (iStep == 60) MoveVUnloadWait();
	else if (iStep == 80) MoveHUnloadWait();
    else if (iStep == 100)
    {
    }
	else if (iStep == 120)
	{
		ReleaseRes(SM_TRANS, kResTransfer | kResUnload | kResRailNear | kAreaClean);
	}
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortClean(int iStep)
{
    //Clean平台直接放到Trans上
    bool bemptystep = false;
    if (!m_pSlotWT)
    {
        return;
    }
    if (iStep == 0)       MoveInitPos();
    else if (iStep == 10) MoveHGrabToClean();
    else if (iStep == 20) MoveVTransClean();
    else if (iStep == 30)
    {
        VaccumCleanToTrans();
        MoveVTransWait();
    }
    else if (iStep == 40)
    {
        m_pSlotTrans = m_pSlotClean; m_pSlotClean = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::AbortCheckBox(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotCheckBox)
    {
        return;
    }
    if (iStep == 0)       AssertRailNearHasWafer(false, QObject::tr("AbortCheckbox"));
    else if (iStep == 10) MoveVTransPickUpWafer();
    else if (iStep == 20) MoveRailNearOpen();
    else if (iStep == 30)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, -1);
    }
    else if (iStep == 40) MoveHGrabPutDownToCheckBoxSpd(); //放料到CheckBox中
    //TODO:没有打开夹抓
    else if (iStep == 50) MoveHGrabBarcode();  //退回
    else if (iStep == 70)
    {
        m_pSlotGrab = m_pSlotCheckBox; m_pSlotCheckBox = 0;
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::do_msg(int iID, QVariantList& vlInput, V_MsgOutput* pvlOutput)
{
    int32_t isize = vlInput.size();
    switch (iID)
    {
    case TRANSSCANCASS:
        if (isize >= 1)
        {
            TransScanCass(vlInput[0].toInt(), vlInput[1].toBool());
        }
        break;
    case RESETSLOT:
    {
        if (isize >= 1)
        {
            CASSSLOT** ppSlot = (CASSSLOT**)vlInput[0].toULongLong();
            if (ppSlot)
            {
                ResetSlot(ppSlot);
            }
            else
            {
                ResetAllSlot();
            }
        }
        break;
    }
    case MOVEINITPOS:
    {
        if (isize >= 0)
        {
            MoveInitPos();
        }
        break;
    }
    case ABORTWAFER:
    {
        if (isize >= 2)
        {
            uint64_t abortID = vlInput[0].toULongLong();
            int iStep = vlInput[1].toInt();
            if (abortID == (uintptr_t)m_pSlotGrab)
            {
                AbortGrab(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotRailNear)
            {
                AbortArrange(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotTrans)
            {
                AbortTrans(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotCoat)
            {
                AbortCoat(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotLoad)
            {
                AbortLoad(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotWT)
            {
                AbortWT(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotUnLoad)
            {
                AbortUnLoad(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotClean)
            {
                AbortClean(iStep);
            };
            if (abortID == (uintptr_t)m_pSlotCheckBox)
            {
                AbortCheckBox(iStep);
            };
        }
        break;
    }
    case kTransCassToRailNear:
        TransCassToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToCoat:
        TransNearToCoat(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToCheckBox:
        TransNearToCheckbox(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToWorktable:
        TransNearToWt(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToClean:
        TransNearToClean(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToCass:
        TransNearToCass(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearToFar:
        TransNearToFar(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailFarToRailNear:
        TransFarToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailFarToCoat:
        TransFarToCoat(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailFarToWorktable:
        TransRailFarToWt(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransCheckBoxToCass:
        TransCheckBoxToCass(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransCheckBoxToRailNear:
        TransCheboxToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransCleanToRailNear:
        TransCleanToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransCoatToRailFar:
        TransCoatToFar(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransCoatToRailNear:
        TransCoatToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransWorktableToRailNear:
        TransWtToNear(vlInput[0].toInt(), vlInput[1].toBool());
        break;
    case kTransRailNearLocation:
        TransRailNearWaferLocation(vlInput[0].toInt());
        break;
    case kTransRailNearLocationManual:
        TransRailNearWaferLocationManual(vlInput[0].toInt());
        break;
	case kAbortTrans:
		AbortTrans(vlInput[0].toInt());
		break;
	case kAbortLoad:
		AbortLoad(vlInput[0].toInt());
		break;
	case kAbortUnload:
		AbortUnLoad(vlInput[0].toInt());
		break;
    default:
        break;
    }
    CMProcess::do_msg(iID, vlInput, pvlOutput);
}

void CProcess_Trans::ResetAllSlot()
{
    ResetSlot(&m_pSlotGrab);
    ResetSlot(&m_pSlotRailNear);
    ResetSlot(&m_pSlotRailFar);
    ResetSlot(&m_pSlotTrans);
    ResetSlot(&m_pSlotCoat);
    ResetSlot(&m_pSlotLoad);
    ResetSlot(&m_pSlotWT);
    ResetSlot(&m_pSlotUnLoad);
    ResetSlot(&m_pSlotClean);
    ResetSlot(&m_pSlotCheckBox);

    m_gSystem.SetWaferIdEmpty(PROCESS_CUT);
    m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);
    m_gSystem.SetWaferIdEmpty(PROCESS_COAT);
    m_gSystem.SetWaferIdEmpty(PROCESS_CLEAN);
}


void CProcess_Trans::ResetSlot(CASSSLOT** ppSlot)
{
    Q_ASSERT(ppSlot);
    if (*ppSlot)
    {
        //TODO:如果有片子，则Reset失败
        //检查相应位置是否能重置
        CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        if (ppSlot == &m_pSlotCoat)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_COAT_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort coatable wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotClean)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_CLEAN_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort cleantable wafer status, has wafer"));
            }

        }
        else if (ppSlot == &m_pSlotLoad)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_LOAD_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort load arm wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotUnLoad)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_UNLOAD_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort unload arm wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotTrans)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_TRANS_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort transfer arm wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotWT)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_WT_WAFER_VACUUM, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort worktable wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotCheckBox)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_CHECKBOX_HAS_WAFER_LEFT, true)
                || pMotorDriver->get_iodata(IO_INPUT, IN_CHECKBOX_HAS_WAFER_RIGHT, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort cupboard wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotRailNear)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true)
                || pMotorDriver->get_iodata(IO_INPUT, IN_Rail_NearLoc_HasWafer, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort raile near wafer status, has wafer"));
            }
        }
        else if (ppSlot == &m_pSlotRailFar)
        {
            if (pMotorDriver->get_iodata(IO_INPUT, IN_Rail_FarCass_HasWafer, true))
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Can't abort rail far wafer status, has wafer"));
            }
        }

        bool bChecking = false;
        if (m_pSlotCheckBox && *ppSlot == m_pSlotCheckBox)
        {
            if (m_pSlotCheckBox->CheckStatus == CHECKCOATING || m_pSlotCheckBox->CheckStatus == CHECKCOATFINISHED)
            {
                LOG_INFO(fmt::format("Reset CheckBox {}", m_pSlotCheckBox->WaferID.toLocal8Bit().data()));

                //下一片需要设定为bEnableCut
                CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
                Q_ASSERT(pCass);
                pCass->SetNextUnCutWaferChecked();

                m_gSystem.AddProductInfo(m_pSlotCheckBox->WaferID, QString("Reset CheckBox at %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")), true);
                bChecking = true;
            }
        }

        bool bAbort = false;
        (*ppSlot)->Reset();

        if (bChecking)
        {
            m_pSlotCheckBox->WPstatus = WPABORT;
        }
        else
        {
            (*ppSlot)->WPstatus = WPABORT;
        }


        if (*ppSlot == m_pSlotCoat)
        {
            m_gSystem.SetWaferIdEmpty(PROCESS_COAT);
        }
        else if (*ppSlot == m_pSlotClean)
        {
            m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);
        }
        else if (*ppSlot == m_pSlotWT)
        {
            m_gSystem.SetWaferIdEmpty(PROCESS_CUT);
        }
        else
        {
            m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);
        }

        if (*ppSlot)
            m_gSystem.AddProductInfo((*ppSlot)->WaferID, QString("Reset Status ").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")), true);
    }
    else
    {
        CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        if (ppSlot == &m_pSlotCoat)
        {
            if (m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM))
            {
                CreateAndBindToSlot(m_pSlotCoat);
                return;
            }
        }
        else if (ppSlot == &m_pSlotClean)
        {
            if (m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM))
            {
                CreateAndBindToSlot(m_pSlotClean);
                return;
            }
        }
        else if (ppSlot == &m_pSlotLoad)
        {
            if (pMotorDriver->get_iodata(IO_OUTPUT, IN_LOAD_VACUUM, true))
            {
                CreateAndBindToSlot(m_pSlotLoad);
                return;
            }
        }
        else if (ppSlot == &m_pSlotUnLoad)
        {
            if (pMotorDriver->get_iodata(IO_OUTPUT, IN_UNLOAD_VACUUM, true))
            {
                CreateAndBindToSlot(m_pSlotUnLoad);
                return;
            }
        }
        else if (ppSlot == &m_pSlotTrans)
        {
            if (pMotorDriver->get_iodata(IO_OUTPUT, IN_TRANS_VACUUM, true))
            {
                CreateAndBindToSlot(m_pSlotTrans);
                return;
            }
        }
        else if (ppSlot == &m_pSlotWT)
        {
            if (m_gSystem.CellExist(OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM))
            {
                //TODO:有片子，则Reset失败
                CreateAndBindToSlot(m_pSlotWT);
                return;
            }
        }
        else if (ppSlot == &m_pSlotCheckBox)
        {
            if (pMotorDriver->get_iodata(IO_OUTPUT, IN_Rail_NearCass_HasWafer, true)
                || pMotorDriver->get_iodata(IO_OUTPUT, IN_Rail_NearLoc_HasWafer, true))
            {
                CreateAndBindToSlot(m_pSlotCheckBox);
                return;
            }
        }
    }

    CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
    Q_ASSERT(pCass);

    //如果不是cassette的wafer,则是New出来的需要删除
    //防止内存泄露
    if (!pCass->IsCasseteWafer(*ppSlot) && *ppSlot)
    {
        delete *ppSlot;
    }
    
    *ppSlot = 0;
}

void CProcess_Trans::SlotTransfer(CASSSLOT** ppSlotSource,
                                  CASSSLOT** ppSlotDest)
{
    QMutexLocker l(&m_slotMutex);
    if (*ppSlotSource)
    {
        //grab -> arrange
        if (ppSlotSource == &m_pSlotGrab && ppSlotDest == &m_pSlotRailNear)
        {
            (*ppSlotSource)->WPstatus = TOCOAT;
        }
        //trans -> coat
        if (ppSlotSource == &m_pSlotTrans && ppSlotDest == &m_pSlotCoat)
        {
            (*ppSlotSource)->WPstatus = WPCOAT;
            /*SetWaferIdEmpty(SVID_TransWaferID);*/
            SetWaferId(m_pSlotTrans, SVID_CoatingWaferID);
            m_gSystem.SetWaferId(PROCESS_COAT, m_pSlotTrans);
        }
        //coat -> load
        if (ppSlotSource == &m_pSlotCoat && ppSlotDest == &m_pSlotLoad)
        {
            //SetWaferIdEmpty(SVID_CoatingWaferID);
            (*ppSlotSource)->WPstatus = TOCUT;
        }
        //load -> wt
        if (ppSlotSource == &m_pSlotLoad && ppSlotDest == &m_pSlotWT)
        {
            (*ppSlotSource)->WPstatus = WPCUT;
            /*SetWaferIdEmpty(SVID_TransWaferID);*/
            SetWaferId(m_pSlotLoad, SVID_CuttingWaferID);
            m_gSystem.SetWaferId(PROCESS_LEVELING, m_pSlotLoad);
        }
        //wt -> unload
        if (ppSlotSource == &m_pSlotWT && ppSlotDest == &m_pSlotUnLoad)
        {
            /*SetWaferIdEmpty(SVID_CuttingCheckWaferID);
            SetWaferId(m_pSlotWT, SVID_TransWaferID);*/
            (*ppSlotSource)->WPstatus = TOCLEAN;
        }
        //unload -> clean
        if (ppSlotSource == &m_pSlotUnLoad && ppSlotDest == &m_pSlotClean)
        {
            (*ppSlotSource)->WPstatus = WPCLEAN;
            /*SetWaferIdEmpty(SVID_TransWaferID);*/
            SetWaferId(m_pSlotUnLoad, SVID_CleaningWaferID);
            m_gSystem.SetWaferId(PROCESS_CLEAN, m_pSlotUnLoad);
        }
        //clean ->trans
        if (ppSlotSource == &m_pSlotClean && ppSlotDest == &m_pSlotTrans)
        {
            /*SetWaferIdEmpty(SVID_CleaningWaferID);
            SetWaferId(m_pSlotClean, SVID_CleaningWaferID);*/
            (*ppSlotSource)->WPstatus = TOUNLOAD;
        }
        //TODO:trans->arrange ??没改状态
        //arrange -> grab
        if (ppSlotSource == &m_pSlotRailNear && ppSlotDest == &m_pSlotGrab)
        {
            (*ppSlotSource)->WPstatus = WPCUTTED;
        }
        //arrange -> checkbox
        if (ppSlotSource == &m_pSlotRailNear && ppSlotDest == &m_pSlotCheckBox)
        {
            (*ppSlotSource)->WPstatus = WPCHECKING;
        }
        //unload -> WT
        if (ppSlotSource == &m_pSlotUnLoad && ppSlotDest == &m_pSlotWT)
        {
            /*SetWaferIdEmpty(SVID_TransWaferID);*/
            //SetWaferId(m_pSlotLoad, SVID_CuttingWaferID);
            //m_gSystem.SetWaferId(PROCESS_LEVELING, m_pSlotLoad);
        }
        if (ppSlotSource == &m_pSlotRailNear && ppSlotDest == &m_pSlotClean)
        {
            (*ppSlotSource)->WPstatus = WPCOAT;
        }
    }
    else
    {
        MqDebug() << "*ppSlotSource=0";
    }

    *ppSlotDest = *ppSlotSource;
    *ppSlotSource = 0;

    WriteRecoveredData();

    CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
    Q_ASSERT(pCass);
    pCass->WriteRecoveredData();

}

bool CProcess_Trans::IsAllUnLoad()
{
    bool bAllUnLoad = m_pSlotGrab == 0
        && m_pSlotRailNear == 0 && m_pSlotRailFar == 0
        && m_pSlotTrans == 0 && m_pSlotCoat == 0 &&
        m_pSlotLoad == 0 && m_pSlotWT == 0 &&
        m_pSlotUnLoad == 0 && m_pSlotClean == 0;

    if (m_pSlotCheckBox != 0 && m_pSlotCheckBox->index != -1)
    {
        return false;
    }
    else
    {
        return bAllUnLoad;
    }
}

//真空转移放到涂敷台
void CProcess_Trans::VaccumTransToCoat()
{
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, IN_COAT_VACUUM);

    IonBlowOff(IonTrans);
}

void CProcess_Trans::VaccumCoatToLoad()
{
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_COAT_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_COAT_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, IN_LOAD_VACUUM);
}

void CProcess_Trans::VaccumLoadToWT()
{
    //HACK:是否吸铁环
    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_WT_RING_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_LOAD_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_WT_RING_VACUUM, IN_WT_RING_VACUUM);
    m_gSystem.VaccumBreak(OUT_LOAD_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM);

    IonBlowOn(IonWt);
    IonBlowOff(IonLoad);
}

void CProcess_Trans::VaccumWtToUnLoad()
{
    m_gSystem.VacuumSet(true, OUT_UNLOAD_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_WT_RING_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_UNLOAD_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_WT_WAFER_VACUUM_BREAK);
    m_gSystem.VaccumBreak(OUT_WT_RING_VACUUM_BREAK);
    //TODO:执行两次破真空
    m_gSystem.VaccumBreak(OUT_WT_WAFER_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_UNLOAD_VACUUM, IN_UNLOAD_VACUUM);

    IonBlowOn(IonUnload);
    IonBlowOff(IonWt);
}

void CProcess_Trans::VaccumUnLoadToClean()
{
    m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_UNLOAD_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_UNLOAD_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);
}

void CProcess_Trans::VaccumCleanToTrans()
{
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_CLEAN_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_CLEAN_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);

    IonBlowOn(IonTrans);
    IonBlowOff(IonClean);
}

void CProcess_Trans::VaccumCoatToTrans()
{
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_COAT_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_COAT_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);

    IonBlowOn(IonTrans);
    IonBlowOff(IonCoat);

}

void CProcess_Trans::VaccumLoadToCoat()
{
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_LOAD_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_LOAD_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_COAT_VACUUM, IN_COAT_VACUUM);

    IonBlowOn(IonCoat);
    IonBlowOff(IonLoad);
}

void CProcess_Trans::VaccumWTToLoad()
{
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_WT_RING_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_WT_WAFER_VACUUM_BREAK);
    m_gSystem.VaccumBreak(OUT_WT_RING_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, IN_LOAD_VACUUM);

    IonBlowOn(IonLoad);
    IonBlowOff(IonWt);
}

void CProcess_Trans::VaccumTransToClean()
{
    m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, -1);
    m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);
    m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);

    IonBlowOn(IonClean);
    IonBlowOff(IonTrans);
}

void CProcess_Trans::VaccumTransToRail()
{
    m_gSystem.VacuumSet(false, OUT_TRANSFER_VACUUM);
    m_gSystem.VaccumBreak(OUT_TRANSFER_VACUUM_BREAK);

    IonBlowOff(IonTrans);

}

void CProcess_Trans::VaccumRailToTrans()
{
    m_gSystem.VacuumSet(true, OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM);
    IonBlowOn(IonTrans);
}

void CProcess_Trans::VaccumRailToLoad()
{
    m_gSystem.VacuumSet(true, OUT_LOAD_VACUUM, IN_LOAD_VACUUM);
    IonBlowOn(IonLoad);
}

void CProcess_Trans::VaccumRailToUnLoad()
{
    m_gSystem.VacuumSet(true, OUT_UNLOAD_VACUUM, IN_UNLOAD_VACUUM);
    IonBlowOn(IonUnload);
}

void CProcess_Trans::VaccumUnloadToRail()
{
    m_gSystem.VacuumSet(false, OUT_UNLOAD_VACUUM, -1);
    m_gSystem.VaccumBreak(OUT_UNLOAD_VACUUM_BREAK);
    IonBlowOff(IonUnload);
}

void CProcess_Trans::VaccumUnloadToWt()
{
    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_WT_RING_VACUUM, -1);

    m_gSystem.VacuumSet(false, OUT_UNLOAD_VACUUM, -1);

    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, -1);
    m_gSystem.VacuumSet(true, OUT_WT_RING_VACUUM, IN_WT_RING_VACUUM);

    m_gSystem.VaccumBreak(OUT_UNLOAD_VACUUM_BREAK);

    m_gSystem.VacuumSet(true, OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM);

    IonBlowOff(IonUnload);
    IonBlowOn(IonWt);
}

bool CProcess_Trans::IsMotorLoadVAtWait()
{
    return MotorInRange(MOTORH1_UPDOWN, Var_Process_Load_PosVWait);
}

bool CProcess_Trans::IsMotorLoadHAtWait()
{
    return MotorInRange(MOTORH2_TRANS, Var_Process_Load_PosHWait);
}

bool CProcess_Trans::IsMotorLoadVAtWT()
{
    return MotorInRange(MOTORH1_UPDOWN, Var_Process_Load_PosVWT);
}

bool CProcess_Trans::IsMotorLoadVAtRail()
{
    return MotorInRange(MOTORH1_UPDOWN, Var_Process_Load_PosVRail);
}

bool CProcess_Trans::IsMotorUnloadVAtWait()
{
    return MotorInRange(MOTORJ1_UPDOWN, Var_Process_Unload_PosVWait);
}
bool CProcess_Trans::IsMotorUnloadVAtWT()
{
    return MotorInRange(MOTORJ1_UPDOWN, Var_Process_Unload_PosVWT);
}
bool CProcess_Trans::IsMotorUnloadHAtWT()
{
    return MotorInRange(MOTORJ1_UPDOWN, Var_Process_Unload_PosHWT);
}

bool CProcess_Trans::IsMotorUnloadVAtRail()
{
    return MotorInRange(MOTORJ1_UPDOWN, Var_Process_Unload_PosVRail);
}

bool CProcess_Trans::IsMotorLoadHAtCoat()
{
    return true;
}
bool CProcess_Trans::IsMotorUnloadHAtClean()
{
    return true;
}

void CProcess_Trans::SetWaferId(CASSSLOT* pCass, _SVID svid)
{
    LOG_INFO(fmt::format("Set SVID:{}", (int)svid));
    if (nullptr == pCass)
    {
        LOG_ERR("Set wafer id nullptr");
        return;
    }

    g_SecsManager.SetVariable(svid, pCass->WaferID.toStdString());
}

void CProcess_Trans::SetWaferIdEmpty(_SVID svid)
{
    g_SecsManager.SetVariable(svid, "");
}

bool CProcess_Trans::IsMotorUnloadHAtWait()
{
    return MotorInRange(MOTORJ2_TRANS, Var_Process_Unload_PosHWait);
}

bool CProcess_Trans::MotorInRange(int motorId, int posId)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);

    pDriver->freshHomeStatus(motorId);

    CMotor* pMotor = (CMotor*)GET_CHDIRECT(motorId, CMotor);
    Q_ASSERT(pMotor);
    //如果没回原点，则检测无效
    bool homed = pMotor->m_Variants.get_VData(Var_Motor_Hashome_ID)->toInt() == 1;
    if (false == homed)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Motor %1 is not homed")
                          .arg(pMotor->m_sName));
    }

    double dPos = m_Variants.get_VData(posId)
        ->toDouble();

    if (RTN_SUCCESS1 != pDriver->freshpos(motorId))
    {
        return false;
    }


    double dCurPos = pMotor->m_Variants.get_VData(Var_Motor_Pos_ID)->toDouble();
    return INRANGE(dCurPos, dPos - 1, dPos + 1);
}

void CProcess_Trans::MoveMotorToPos(int motorId, int posId, bool isHalfSpeed/*=false*/, bool bWait/* = true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (isHalfSpeed)
    {
        CMotor* pMotor = GET_CHDIRECT(motorId, CMotor);
        double dDefaultSpd = pMotor->m_Variants.get_VData(Var_Motor_Default_speed_ID)
            ->toDouble();

        //设置速度为半速
        pDriver->setspeed(motorId, 0.4 * dDefaultSpd, 0, 0, 0, 0);
    }

    double dPos = m_Variants.get_VData(posId)
        ->toDouble();
    pDriver->absmove(motorId, dPos, bWait);
    if (isHalfSpeed)
    {
        //执行完后恢复速度
        pDriver->setdefaultspeed(motorId);
    }
}

void CProcess_Trans::MoveLoadVToPos(int posId, bool bHalfSpeed/*=false*/)
{
    MoveMotorToPos(MOTORH1_UPDOWN, posId, bHalfSpeed);
}

void CProcess_Trans::MoveHLoadToPos(int posId, bool bWait/*=true*/)
{
    MoveMotorToPos(MOTORH2_TRANS, posId, false, bWait);
}

void CProcess_Trans::MoveUnloadVToPos(int posId)
{
    MoveMotorToPos(MOTORJ1_UPDOWN, posId);
}

void CProcess_Trans::MoveUnloadHToPos(int posId, bool bWait/*=true*/)
{
    MoveMotorToPos(MOTORJ2_TRANS, posId, false, bWait);
}

void CProcess_Trans::TransCassToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotGrab && !m_pSlotRailNear && !m_pSlotTrans &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
		//请求安全资源
		AssertAcuireRes(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean, QObject::tr("Trans Cass to RailNear"));

        QString sTransInfo = QObject::tr("Trans Cass to RailNear");
        //安全检查
        AssertRailNearHasWafer(false, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);

        AssertSlotExists(false, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);

        //检查近轨或转移是否有料
        if (m_pSlotRailNear)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Rail has wafer."));
        }

        if (m_pSlotTrans)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Trans has wafer."));
        }

        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        Q_ASSERT(pCass);
        CASSSLOT* pSlotCass = pCass->GetFirstUnCutWafer();
        if (!pSlotCass)
        {
            MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cass has no wafer"));
        }

        pSlotCass->WPstatus = TOGRAB;
        pSlotCass->bNeedRelocation = true;
        SlotTransfer(&pSlotCass, &m_pSlotGrab);
        SetWaferId(m_pSlotGrab, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransCasste2RailNearStarted);

        IonBlowOff(IonTrans);	//打开D中转静电消除器
    }
    else if (iStep == 20)
    {
        //trans 移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
    }
    else if (iStep == 30)
    {
        //料盒移动到取料位置
        ResManager().Acquire(SM_TRANS, kResCassete);
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS,
                                           CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, m_pSlotGrab->index);
    }
    else if (iStep == 40)
    {
    }
    else if (iStep == 45)
    {
        MoveRailNearOpen();
    }
    else if (iStep == 50)
    {
        AssertRailNearHasWafer(false, QObject::tr("Trans Cass to RailNear"));

        ClawRelease(false);
        MoveHGrabPickUpReadySpd(false);	//移动到取料准备位置

        MoveVTransPickUpWafer();        //同时移动

        //等待移动到位
        ClawRelease(true);
        MoveHGrabPickUpReadySpd(true);

    }
    else if (iStep == 60)
    {
    }
    else if (iStep == 65)
    {

    }
    else if (iStep == 70)
    {
        MoveHGrabPickUpCassSpd();			//移动到取料位置，半速移动
    }
    else if (iStep == 80)
    {
        ClawGrabed(true);   //抓料
    }
    else if (iStep == 90)
    {
        IonBlowOn(IonEntrance);			//静电消除器
        //IonBlowOn(IonTrans);
    }
    else if (iStep == 91)
    {
        m_pSlotGrab->bCanAbort = false;
        MoveHGrabPickUpReadySpd(true);

        //先规则一下，再拉过去
        MoveHGrabWaferExistCheck();

        ClawRelease();
        MoveRailNearReadyClose();

        //等一下,规整需要花时间
        MSleep(500);

        MoveHGrabWaferExistCheck(true);

        //MoveToPosLockClose();	//闭合进行规整
    }
    else if (iStep == 92)
    {
        AssertRailNearCassHasWafer(true);

        //再关一次用于检查轴是否报警
        MoveRailNearReadyClose();

        if (m_pSlotGrab)
        {
            ClawGrabed();
        }
        //打开规整轴到拉的程度，再往规整位置拉
        MoveRailNearPullOpen();
    }
    else if (iStep == 95)
    {
        //扫码
        MoveHGrabBarcode();
        
        ClawGrabed();
        AssertGrabHasWafer(GetMsgName(kTransCassToRailNear) + QObject::tr("Scan barcode pos"));
        g_SecsManager.SendEvent(EVENT_BarcodeScanStarted);

        m_pSlotGrab->bCanAbort = true;
        CBarCodeDriver* pBarcodeDriver = GET_CARD(BARCODE_DRIVER, CBarCodeDriver);
        try
        {
            //执行扫码
            pBarcodeDriver->GetBarCode(BARCODE);
        }
        catch (const QString& ex)
        {
            MQT_THROW_CODESTR(ALARM_SCAN_COMMUNICATION, QObject::tr("Scan wafter id failed."));
        }

        //更新Wafer ID信息
        m_pSlotGrab->WaferID = pBarcodeDriver->GetBarCode_String(BARCODE);
        if (m_gSystem.IsSimulator())
        {
            m_pSlotGrab->WaferID = QString("WaferId(%1)").arg(m_pSlotGrab->index + 1);
        }

        m_pSlotGrab->BeginDate = QDateTime::currentDateTime();
        m_gSystem.SetWaferId(PROCESS_TRANS, m_pSlotGrab);
        SetWaferId(m_pSlotGrab, SVID_ScanWaferID);
        SetWaferId(m_pSlotGrab, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_BarcodeScanComplete);

        m_gSystem.AddProductInfo(m_pSlotGrab, QString("Lot:%1 Wafer ID:%2 \n%3 start trans casste to coattable SLOT:%4").arg(m_gSystem.GetLotId().c_str())
                                 .arg(m_pSlotGrab->WaferID).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(m_pSlotGrab->index + 1));

        IonBlowOff(IonEntrance);
        //IonBlowOff(IonTrans);
    }
    else if (iStep == 100)
    {
        //准备规整
        MoveRailNearPullClose();
        MoveHGrabLocationNearReady(); //到规整准备位置
    }
    else if (iStep == 110)
    {
        ClawGrabed(true);   //检查料片是否到位
        AssertGrabHasWafer(GetMsgName(kTransCassToRailNear));
        ClawRelease();
    }
    else if (iStep == 115)
    {
        //规整操作
        MoveRailNearReadyClose();
        MoveRailNearClose();

        //检查规整异常
        MoveRailNearClose();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 120)
    {	//移到规整偏移位置,即退开
        MoveHGrabLocationNearPushPrepare();
    }
    else if (iStep == 125)
    {
        //下降到推晶元位置
        MoveTransVNearPull();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 130)
    {
        MoveRailNearClose();
        //规整操作，多次执行，防止轴报警异常
        MoveRailNearClose();

        //重新定位，移回规整位置
        MoveHGrabLocationNearSpd();

        //移到准备位置 即退开
        MoveHGrabLocationNearPushPrepare();
    }
    else if (iStep == 140)
    {
        AssertRailNearLocationHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
    }
    else if (iStep == 150)
    {
        MoveHGrabWait(true);
        MoveVTransWait();
        //准直完毕
        m_pSlotGrab->bNeedRelocation = false;
        SlotTransfer(&m_pSlotGrab, &m_pSlotRailNear);
    }
    else if (iStep == 260)
    {
        //转移完后回准备点等待
        MoveHGrabWait();

        IonBlowOff(IonTrans);	//D中转静电消除关

        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to rail near")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCasste2RailNearComplete);

        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        //MqDebug() << "-----" << __FUNCTION__ << " Finished";
        ReleaseRes(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransNearToCoat(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear && !m_pSlotCoat &&
        !m_pSlotTrans &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");

        QString sTransInfo = QObject::tr("Trans RailNear to Coat");

		AssertAcuireRes(SM_TRANS, kResTransfer | kResCoat | kResRailFar | kResRailNear | kResDoorOpen | kAreaClean | kAreaCoat, sTransInfo);
        AssertRailNearLocationHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
        AssertRailFarHasWafer(false, sTransInfo);
        AssertCoatHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotRailFar, sTransInfo);
        AssertSlotExists(false, &m_pSlotCoat, sTransInfo);

        g_SecsManager.SendEvent(EVENT_TransNear2CoatStarted);
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
    }
    else if (iStep == 160)
    {
        //到近轨道取晶圆位置
        MoveHGrabToRailNear(true);
    }
    else if (iStep == 165)
    {
        //降下并取片
        MoveVTransRailNear();
        VaccumRailToTrans();
        SlotTransfer(&m_pSlotRailNear, &m_pSlotTrans);
    }
    else if (iStep == 170)
    {
        //打开一点
        MoveRailNearOpen();
        //移动到等待位置
        MoveVTransWait();
    }
    else if (iStep == 175)
    {
        MoveHGrabToCoat(false);
        OpenCoatCurtain(false);
        MoveRailFarOpenMax(false);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, false);
    }
    else if (iStep == 180)
    {
        MoveHGrabToCoat(true);
        ReleaseRes(SM_TRANS, kResRailNear | kAreaClean);
    }
    else if (iStep == 200)
    {
    }
    else if (iStep == 210)
    {
        MoveRailFarOpenMax(true);
        OpenCoatCurtain(true);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, true);
    }
    else if (iStep == 230)
    {
        MoveTransPutDownWafterToCoat();
    }
    else if (iStep == 235)
    {
        VaccumTransToCoat();
        SlotTransfer(&m_pSlotTrans, &m_pSlotCoat);
    }
    else if (iStep == 240)
    {
        //TODO:这里可以先运动到离开位置
        MoveVTransRailFarReady(true);
        CloseCoatCurtain(false);
    }
    else if (iStep == 250)
    {
        //移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
        CloseCoatCurtain(true);
    }
    else if (iStep == 260)
    {
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to coattable")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransNear2CoatComplete);

        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        FUNC_END("");

        ReleaseRes(SM_TRANS, kResTransfer | kResCoat | kResRailFar | kResRailNear | kResDoorOpen | kAreaClean | kAreaCoat);
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }

}

void CProcess_Trans::TransNearToFar(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear && !m_pSlotRailFar &&
        !m_pSlotTrans &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans RailNear to Far");

		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailFar | kResRailNear | kAreaClean | kAreaCoat, sTransInfo);
        AssertRailNearLocationHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
        AssertRailFarHasWafer(false, sTransInfo);
        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotRailFar, sTransInfo);
        g_SecsManager.SendEvent(EVENT_TransNear2FarStarted);
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
    }
    else if (iStep == 160)
    {
        //到近轨道取晶圆位置
        MoveHGrabToRailNear(true);
    }
    else if (iStep == 165)
    {
        //降下并取片
        MoveVTransRailNear();
        VaccumRailToTrans();
        SlotTransfer(&m_pSlotRailNear, &m_pSlotTrans);
    }
    else if (iStep == 170)
    {
        //打开一点
        MoveRailNearOpen();
        //移动到等待位置
        MoveVTransWait();
    }
    else if (iStep == 175)
    {
        MoveHGrabToRailFar(false);
        MoveRailFarOpen(false);
    }
    else if (iStep == 180)
    {
        MoveHGrabToRailFar(true);
        ReleaseRes(SM_TRANS, kResRailNear | kAreaClean);
    }
    else if (iStep == 200)
    {
    }
    else if (iStep == 210)
    {
        MoveRailFarOpen(true);
    }
    else if (iStep == 230)
    {

    }
    else if (iStep == 235)
    {
        MoveVTransRailFar();
        VaccumTransToRail();
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailFar);
        AssertRailFarHasWafer(true, "Trans Rail(Near) to Rail(Far) put wafer from Transfer to Rail(Far) failed");
    }
    else if (iStep == 240)
    {
        //TODO:这里可以先运动到离开位置
        MoveVTransRailFarReady(true);
    }
    else if (iStep == 250)
    {
        //移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
    }
    else if (iStep == 260)
    {
        g_SecsManager.SendEvent(EVENT_TransNear2FarComplete);
        ReleaseRes(SM_TRANS, kResTransfer | kResRailFar | kResRailNear | kAreaClean | kAreaCoat);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransNearToCheckbox(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotTrans && !m_pSlotRailNear && !m_pSlotCheckBox 
        && iStep > 0)
    {
        //如果Clean Trans Arrange都没有料
        return;
    }
    if (iStep == 0)
    {
        FUNC_START("");
        /*
        if (!m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM)) {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to Cass,CleanTable has no Wafer"));
        }
        if (m_gSystem.IsVaccumOn(OUT_TRANSFER_VACUUM, IN_TRANS_VACUUM)) {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Clean to Cass,Trans has  Wafer"));
        }
        */
        QString sTransInfo = QObject::tr("Trans RailNear to Checkbox");

		AssertAcuireRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean, sTransInfo);
        AssertRailNearHasWafer(true, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);
        AssertCheckBoxhasCell(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);
        AssertSlotExists(false, &m_pSlotCheckBox, sTransInfo);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 start trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransNear2CheckBox2Started);

		IonBlowOn(IonTrans);	//打开D中转静电消除
		IonBlowOn(IonEntrance);	//打开入口转静电消除
    }
    else if (iStep == 20)
    {
		
    }
    else if (iStep == 30)
    {
    }
    else if (iStep == 40)
    {
    }
    else if (iStep == 50)
    {
        LOG_INFO("Trans To Wait Pos");
        MoveVTransWait();
    }
    else if (iStep == 140)
    {
        //移动到准备下料的位置，然后往前推
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 150)
    {
        MoveTransVNearPull();
    }
    else if (iStep == 160)
    {
        ClawRelease(); //再次打开夹抓
    }
    else if (iStep == 170)
    {
        MoveRailNearPullOpen();
        //MoveToPosLockClose();
    }
    else if (iStep == 180)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, -1);
    }
    else if (iStep == 190)
    {
        MoveHGrabBarcode();
        MoveRailNearPullClose();
    }
    else if (iStep == 195)
    {
        MoveHGrabPutDownToCheckBoxSpd();
    }
    else if (iStep == 196)
    {
        MoveHGrabPickUpReadySpd(true);
    }
    else if (iStep == 197)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotCheckBox);
    }
    else if (iStep == 198)
    {
        MoveHGrabWait(false);
        CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                           CProcess_Scan);
        pCass->CassUp(CASSETTE);
    }
    else if (iStep == 200)
    {
        //回到安全位置
        MoveVTransRailNear(false);
        MoveVTransRailNear(true);
        MoveVTransWait();
        MoveHGrabWait(true);
    }
    else if (iStep == 280)
    {
		IonBlowOff(IonEntrance);	//入口静电消除关闭
		IonBlowOff(IonTrans);		//D中转静电消除关闭

        if (m_pSlotCheckBox->bCoatFinished && !m_pSlotCheckBox->bCutFinished
            && m_pSlotCheckBox->bNeedCheckCoat && !m_pSlotCheckBox->bCheckCoatFinished)
        {
            m_pSlotCheckBox->CheckStatus = CHECKCOATING;

#if __SIMULATOR__
            m_pSlotCheckBox->CheckStatus = CHECKCOATFINISHED;
            m_pSlotCheckBox->bCheckCoatFinished = true;
#endif

            SetWaferIdEmpty(SVID_TransWaferID);
            SetWaferId(m_pSlotCheckBox, SVID_CoatingQualityCheckWaferID);
        }

        if (m_pSlotCheckBox->bCutFinished
            && m_pSlotCheckBox->bNeedCheckCut && !m_pSlotCheckBox->bCheckCutFinished)
        {
            m_pSlotCheckBox->CheckStatus = CHECKCUTING;
            SetWaferIdEmpty(SVID_TransWaferID);
            SetWaferId(m_pSlotCheckBox, SVID_CuttingCheckWaferID);
        }

        m_gSystem.AddProductInfo(m_pSlotCheckBox, QString("%1 finish trans wafer cleantable to cupboard").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransNear2CheckBox2Complete);

        ReleaseRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    } if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransNearToWt(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear && !m_pSlotUnLoad && !m_pSlotWT
        && iStep > 0)
    {
        return;
    }

    if (iStep > 1 && iStep < 115)
    {
        //在此区间都是需要上锁
        QString sTransInfo = QObject::tr("Trans RailNear to Worktable");
        AssertAcuireRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean, sTransInfo);
    }else if(iStep > 115 && iStep < 280){
        //已经释放了不需要其他锁了
        QString sTransInfo = QObject::tr("Trans RailNear to Worktable");
        AssertAcuireRes(SM_WTUnload, kResUnload | kResWt, sTransInfo);
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans RailNear to Worktable");

		AssertAcuireRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean, sTransInfo);
        AssertRailNearHasWafer(true, sTransInfo);
        AssertWtHasWafer(false, sTransInfo);
        AssertUnloadHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotWT, sTransInfo);
        AssertSlotExists(false, &m_pSlotUnLoad, sTransInfo);

        SetWaferId(m_pSlotCoat, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransNear2WTStarted);
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 start trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

    }
    else if (iStep == 20)
    {
        MoveVUnloadWait();
    }
    else if (iStep == 30)
    {
        MoveHUnloadRailNear(false);

        UnloadPos();

    }
    else if (iStep == 40)
    {
        MoveHUnloadRailNear(true);
    }
    else if (iStep == 45)
    {
        //到取晶圆位置
        MoveVUnloadRailNear();
        VaccumRailToUnLoad();

        MoveRailNearPullOpen();

        //TODO:真空吸住了,往上拉
        //QString sInfo = "XXX";
        //AssertUnloadHasWafer(true, sInfo);

        MoveVUnloadWait();

        //检查片子有没有掉
        QString sInfo = QObject::tr("Unload grab wafer failed..");
        AssertUnloadHasWafer(true, sInfo, ALARM_RESERVED);

        //打开轨道
        SlotTransfer(&m_pSlotRailNear, &m_pSlotUnLoad);
    }
    else if (iStep == 50)
    {
        //移动到准备位置
        MoveVUnloadWait();
    }
    else if (iStep == 110)
    {
        MoveHUnloadWT();
    }
    else if (iStep == 115)
    {
        ReleaseRes(SM_WTUnload, kAreaClean | kResRailNear);
    }
    else if (iStep == 120)
    {
        MoveVUnLoadWT();
        VaccumUnloadToWt();
        SlotTransfer(&m_pSlotUnLoad, &m_pSlotWT);
        m_pSlotWT->WPstatus = TOCUT;
    }
    else if (iStep == 250)
    {
        MoveVUnloadWait();
        MoveHUnloadWait();
    }
    else if (iStep == 280)
    {
        g_SecsManager.SendEvent(EVENT_TransNear2WTComplete);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 finish trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        ReleaseRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransNearToClean(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotClean && !m_pSlotRailNear && !m_pSlotTrans 
        && iStep > 0)
    {
        return;
    }
    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("RailNear to CleanTable");

		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailNear | kResClean | kAreaClean | kResDoorOpen, sTransInfo);
        AssertCleanHasWafer(false, sTransInfo);
        AssertRailNearLocationHasWafer(true);
        AssertTransHasWafer(false, sTransInfo);

        AssertSlotExists(false, &m_pSlotClean, sTransInfo);
        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);

        SetWaferId(m_pSlotWT, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransNear2CleanStarted);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 start trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)
    {
        MoveVTransWait();
        MoveHGrabToRailNear(false);
    }
    else if (iStep == 10)
    {
        OpenCleanCurtain(false);

        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, false);
        MoveHGrabToRailNear(true);
    }
    else if (iStep == 15)
    {
        MoveVTransRailNearReady(true);
    }
    else if (iStep == 20)
    {
        MoveVTransRailNear(true);
    }
    else if (iStep == 21)
    {
        VaccumRailToTrans();
        SlotTransfer(&m_pSlotRailNear, &m_pSlotTrans);
    }
    else if (iStep == 22)
    {
        MoveRailNearPullOpen();
        MoveVTransRailNearReady(true);
        MoveRailNearOpenMax(false);
        MoveHGrabToClean(false);
    }
    else if (iStep == 23)
    {
        MoveVTransRailNearReady(true);
        MoveRailNearOpenMax(true);
        MoveHGrabToClean(true);
    }
    else if (iStep == 25)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, true);
        OpenCleanCurtain(true);
    }
    else if (iStep == 30)
    {
        MoveTransPutDownWaferToClean();
    }
    else if (iStep == 35)
    {
        VaccumTransToClean();
        SlotTransfer(&m_pSlotTrans, &m_pSlotClean);
    }
    else if (iStep == 100)
    {
        MoveVTransRailNearReady(true);
        CloseCleanCurtain(false);
    }
    else if (iStep == 110)
    {
        MoveVTransWait();
    }
    else if (iStep == 120)
    {
		MoveHGrabWait();
        CloseCleanCurtain(true);
        ReleaseRes(SM_TRANS, kResDoorOpen | kResClean);
    }
    else if (iStep == 200)
    {
        //MoveHGrabWait();
    }
    else if (iStep == 250)
    {
        g_SecsManager.SendEvent(EVENT_TransNear2CleanComplete);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 finish trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        ReleaseRes(SM_TRANS, kResTransfer | kResRailNear | kResClean | kAreaClean | kResDoorOpen);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransNearToCass(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotTrans && !m_pSlotRailNear && !m_pSlotGrab
        && iStep > 0)
    {
        //如果Clean Trans Arrange都没有料
        return;
    }
    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans RailNear to Cass");
		AssertAcuireRes(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean, sTransInfo);

        AssertRailNearHasWafer(true, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 start trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransNear2CassteStarted);

		IonBlowOn(IonTrans);	//打开中转静电消除
		IonBlowOn(IonEntrance);	//打开入口静电消除
    }
    else if (iStep == 20)
    {

    }
    else if (iStep == 30)
    {
    }
    else if (iStep == 40)
    {
    }
    else if (iStep == 50)
    {
        LOG_INFO("Trans To Wait Pos");
        MoveVTransWait();
    }
    else if (iStep == 140)
    {
        //移动到准备下料的位置，然后往前推
        MoveHGrabPutDownPrepare();
    }
    else if (iStep == 150)
    {
        MoveTransVNearPull();
    }
    else if (iStep == 160)
    {
        ClawRelease(); //再次打开夹抓
    }
    else if (iStep == 170)
    {
        MoveRailNearPullOpen();
        //MoveToPosLockClose();
    }
    else if (iStep == 180)
    {
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS, CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotUnLoadPos(CASSETTE, m_pSlotRailNear->index);
    }
    else if (iStep == 190)
    {
        MoveHGrabBarcode();
        MoveRailNearPullClose();
    }
    else if (iStep == 195)
    {
        MoveHGrabPutDownToCassSpd();
    }
    else if (iStep == 196)
    {
        MoveHGrabPickUpReadySpd(true);
    }
    else if (iStep == 197)
    {
        SlotTransfer(&m_pSlotRailNear, &m_pSlotGrab);

    }
    else if (iStep == 198)
    {
        MoveHGrabWaferExistCheck();
    }
    else if (iStep == 200)
    {
        MoveVTransRailNear(false);
        MoveHGrabWait(false);
        MoveVTransRailNear(true);
        MoveVTransWait();
        MoveHGrabWait(true);
    }
    else if (iStep == 280)
    {
		IonBlowOff(IonEntrance);	//入口静电消除关闭
		IonBlowOff(IonTrans);	//中转静电消除关闭

        CASSSLOT* pSlot = m_pSlotGrab;
        int iSlotID = pSlot->index + 1;
        pSlot->EndDate = QDateTime::currentDateTime();

        m_gSystem.m_iTotalCuttedWafer++;
        QTime tmpTime;
        tmpTime.setHMS(0, 0, 0, 0);                                       //初始化数据，时 分 秒 毫秒
        int secsCount = pSlot->BeginDate.secsTo(pSlot->EndDate);
        QString str = QObject::trUtf8("WaferID:%4,DID:%2,TM:%3,DNo:%1")
            .arg(m_gSystem.GetCurFile())
            .arg(iSlotID)
            .arg(tmpTime.addSecs(secsCount).toString("hh:mm:ss"))
            .arg(pSlot->WaferID);
        m_gSystem.EvtLog(QString::fromUtf8("JOB"), str);
        m_pSlotGrab = 0;
        g_SecsManager.SendEvent(EVENT_TransNear2CassteComplete);
        m_gSystem.AddProductInfo(pSlot, QString("%1 finish trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        m_gSystem.AddProductInfo(pSlot, QString("Job finish %1\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        ReleaseRes(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransFarToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailFar && !m_pSlotTrans && !m_pSlotRailNear
        && iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans RailFar to RailNear");

		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailNear | kResRailFar | kAreaCoat | kAreaClean, sTransInfo);
        AssertRailFarHasWafer(true, sTransInfo);
        AssertRailNearHasWafer(false, sTransInfo);
        AssertLoadHasWafer(false, sTransInfo);
        g_SecsManager.SendEvent(EVENT_TransFar2NearStarted);
    }
    else if (iStep == 20)
    {
        MoveVTransWait();
    }
    else if (iStep == 30)
    {
        MoveHGrabToRailFar(false);

        MoveVTransRailFarReady(true);

        MoveHGrabToRailFar(true);
    }
    else if (iStep == 40)
    {
        MoveVTransRailFar(true);
        VaccumRailToTrans();
        SlotTransfer(&m_pSlotRailFar, &m_pSlotTrans);
    }
    else if (iStep == 50)
    {
        //移动到准备位置
        MoveVTransWait();
    }
    else if (iStep == 110)
    {
        MoveRailNearOpen(false);
        MoveHGrabToRailNear(true);
        MoveRailNearOpen(true);
    }
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        VaccumTransToRail();
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
    }
    else if (iStep == 250)
    {
        //回安全位置
        MoveVTransWait();
        MoveHGrabWait(true);
    }
    else if (iStep == 280)
    {
        ReleaseRes(SM_TRANS, kResTransfer | kResRailNear | kResRailFar | kAreaCoat | kAreaClean);
        g_SecsManager.SendEvent(EVENT_TransFar2NearComplete);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransRailFarToWt(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailFar && !m_pSlotLoad && !m_pSlotWT
        && iStep > 0)
    {
        return;
    }

    //Notice:注意这里的Index必须正确
    //在115步释放了
    if (iStep >= 1 && iStep < 115)
    {
        QString sTransInfo = QObject::tr("Trans RailFar to Worktable");
        AssertAcuireRes(SM_WTLoad, kResLoad | kResRailFar | kResWt | kAreaCoat, sTransInfo);
    }
    else if (iStep > 115 && iStep < 280)
    {
        QString sTransInfo = QObject::tr("Trans RailFar to Worktable");
        AssertAcuireRes(SM_WTLoad, kResLoad | kResWt, sTransInfo);
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans RailFar to Worktable");

		AssertAcuireRes(SM_WTLoad, kResLoad | kResRailFar | kResWt | kAreaCoat, sTransInfo);
        AssertRailFarHasWafer(true, sTransInfo);
        AssertWtHasWafer(false, sTransInfo);
        AssertLoadHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotRailFar, sTransInfo);
        AssertSlotExists(false, &m_pSlotWT, sTransInfo);
        AssertSlotExists(false, &m_pSlotLoad, sTransInfo);

        //检查是否记录有晶圆
        if (!m_pSlotRailFar)
        {
            MQT_THROW_CODESTR(ALARM_RESERVED, (GetMsgName(kTransRailFarToWorktable) + QObject::tr("Rail Far Pos has not wafer")));
        }

        if (m_pSlotWT)
        {
            MQT_THROW_CODESTR(ALARM_RESERVED, (GetMsgName(kTransRailFarToWorktable) + QObject::tr("Worktable Pos has wafer")));
        }

        SetWaferId(m_pSlotCoat, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransFar2WTStarted);
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 start trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

    }
    else if (iStep == 20)
    {
        MoveVLoadWait();
    }
    else if (iStep == 30)
    {
        MoveHLoadWait(false);

        LoadPos();

        MoveHLoadWait(true);
    }
    else if (iStep == 40)
    {
        MoveHLoadRailFar();
    }
    else if (iStep == 45)
    {
        //到取晶圆位置
        MoveVLoadRailFar(true);
        VaccumRailToLoad();
        SlotTransfer(&m_pSlotRailFar, &m_pSlotLoad);
    }
    else if (iStep == 50)
    {
        //移动到准备位置
        MoveVLoadWait();
    }
    else if (iStep == 110)
    {
        MoveHLoadWT();
    }
    else if (iStep == 115)
    {
        MoveHLoadWT();
        ReleaseRes(SM_WTLoad, kAreaCoat | kResRailFar);
    }
    else if (iStep == 120)
    {
        MoveVLoadWT();
        VaccumLoadToWT();
        SlotTransfer(&m_pSlotLoad, &m_pSlotWT);
    }
    else if (iStep == 250)
    {
        MoveVLoadWait();
        MoveHLoadWait(true);
    }
    else if (iStep == 280)
    {
        g_SecsManager.SendEvent(EVENT_TransFar2WTComplete);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 finish trans wafer coattable to worktable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        ReleaseRes(SM_WTLoad, kResLoad | kResRailFar | kResWt | kAreaCoat);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCheboxToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotCheckBox && !m_pSlotRailNear && !m_pSlotGrab &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
        //安全检查
        QString sTransInfo = QObject::tr("Trans Checkbox to RailNear");

		//请求安全资源
		AssertAcuireRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean, sTransInfo);
        AssertRailNearHasWafer(false, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);

        AssertSlotExists(false, &m_pSlotRailNear, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);

        if (!m_pSlotCheckBox)
        {
            MQT_THROW_CODESTR(ALARM_RESERVED, (GetMsgName(kTransCassToRailNear) + QObject::tr("Checkbox has no wafer")));
        }

        if (m_pSlotRailNear)
        {
            MQT_THROW_CODESTR(ALARM_RESERVED, (GetMsgName(kTransCassToRailNear) + QObject::tr("Rail Near Pos has wafer")));
        }
        g_SecsManager.SendEvent(EVENT_TransCheckBox2NearStarted);
    }
    else if (iStep == 20)
    {
        //trans 移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
    }
    else if (iStep == 30)
    {
        //料盒移动到取料位置
        ResManager().Acquire(SM_TRANS, kResCassete);
        CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN,
                                           SM_TRANS,
                                           CProcess_Scan);
        Q_ASSERT(pScan);
        pScan->MoveSlotLoadPos(CASSETTE, -1);
    }
    else if (iStep == 40)
    {
    }
    else if (iStep == 45)
    {
        MoveRailNearOpen();
    }
    else if (iStep == 50)
    {
        AssertRailNearHasWafer(false, QObject::tr("Trans Checkbox to RailNear"));

        ClawRelease(false);
        MoveHGrabPickUpReadySpd(false);	//移动到取料准备位置

        MoveVTransPickUpWafer();

        ClawRelease(true);
        MoveHGrabPickUpReadySpd(true);

    }
    else if (iStep == 60)
    {
        m_pSlotCheckBox->bNeedRelocation = true;
        SlotTransfer(&m_pSlotCheckBox, &m_pSlotGrab);
    }
    else if (iStep == 65)
    {
        IonBlowOn(IonTrans);
    }
    else if (iStep == 70)
    {
        MoveHGrabPickUpCassSpd();			//移动到取料位置，半速移动
    }
    else if (iStep == 80)
    {
        ClawGrabed();
    }
    else if (iStep == 90)
    {
        IonBlowOn(IonEntrance);			//静电消除器
    }
    else if (iStep == 91)
    {
        m_pSlotGrab->bCanAbort = false;
        MoveHGrabPickUpReadySpd(true);

        //先规则一下，再拉过去
        MoveHGrabWaferExistCheck();

        ClawRelease();
        MoveRailNearReadyClose();

        //等一下,规整需要花时间
        MSleep(500);
        //MoveToPosLockClose();	//闭合进行规整
    }
    else if (iStep == 92)
    {
        AssertRailNearCassHasWafer(true);

        //再关一次用于检查轴是否报警
        MoveRailNearReadyClose();

        if (m_pSlotGrab)
        {
            ClawGrabed();
        }
        //打开规整轴，再往规整位置拉
        MoveRailNearPullOpen();
    }
    else if (iStep == 95)
    {
        //扫码
        MoveHGrabBarcode();
        g_SecsManager.SendEvent(EVENT_BarcodeScanStarted);

        m_pSlotGrab->bCanAbort = true;

        m_gSystem.SetWaferId(PROCESS_TRANS, m_pSlotGrab);
        SetWaferId(m_pSlotGrab, SVID_ScanWaferID);
        SetWaferId(m_pSlotGrab, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_BarcodeScanComplete);

        m_gSystem.AddProductInfo(m_pSlotGrab, QString("Lot:%1 Wafer ID:%2 \n%3 start trans casste to coattable SLOT:%4").arg(m_gSystem.GetLotId().c_str())
                                 .arg(m_pSlotGrab->WaferID).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(m_pSlotGrab->index + 1));
    }
    else if (iStep == 100)
    {	//准备规整
        MoveRailNearPullClose();
        MoveHGrabLocationNearReady(); //到规整准备位置
        IonBlowOff(IonEntrance);
    }
    else if (iStep == 110)
    {
        ClawGrabed();
        //报警时会打开,手动拖到相应位置
        AssertGrabHasWafer(QObject::tr("RailNear Location Again"));
        ClawRelease();
    }
    else if (iStep == 115)
    {
        //规整操作
        MoveRailNearReadyClose();
        MoveRailNearClose();

        //检查规整异常
        MoveRailNearClose();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 120)
    {	//移到规整偏移位置,即退开
        MoveHGrabLocationNearPushPrepare();
    }
    else if (iStep == 125)
    {
        //下降到推晶元位置
        MoveTransVNearPull();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 130)
    {
        MoveRailNearClose();
        //规整操作，多次执行，防止轴报警异常
        MoveRailNearClose();

        //重新定位，移回规整位置
        MoveHGrabLocationNearSpd();

        //移到准备位置 即退开
        MoveHGrabLocationNearPushPrepare();
    }
    else if (iStep == 140)
    {
        AssertRailNearLocationHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
        
    }
    else if (iStep == 150)
    {
        MoveHGrabWait(true);
        MoveVTransWait();
        SlotTransfer(&m_pSlotGrab, &m_pSlotRailNear);
        //准直完毕
        m_pSlotRailNear->bNeedRelocation = false;
    }
    else if (iStep == 260)
    {
        //转移完后回准备点等待
        MoveHGrabWait();

		IonBlowOff(IonEntrance);
        IonBlowOff(IonTrans);	//D中转静电消除关

        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to coattable")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCheckBox2NearComplete);

        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        ReleaseRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCleanToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotClean && !m_pSlotTrans && !m_pSlotRailNear
        && iStep > 0)
    {
        return;
    }
    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans Checkbox to RailNear");

		AssertAcuireRes(SM_TRANS, kResClean | kResRailNear | kResTransfer | kResDoorOpen | kAreaClean, sTransInfo);
        AssertCleanHasWafer(true, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);
        AssertRailNearHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotClean, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);
        AssertSlotExists(false, &m_pSlotRailNear, sTransInfo);

        AssertCleanWaferHasWater(sTransInfo);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 start trans wafer cleantable to casste").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransClean2NearStarted);

		IonBlowOn(IonTrans);	//D中转静电消除开
    }
    else if (iStep == 5)
    {
    }
    else if (iStep == 10)
    {
    }
    else if (iStep == 15)
    {
        OpenCleanCurtain(false);
    }
    else if (iStep == 20)
    {
        MoveVTransWait();
        MoveRailNearOpenMax(false);
        MoveHGrabToClean(false);
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, false);
    }
    else if (iStep == 21)
    {
        MoveVTransRailNearReady(true);
        MoveRailNearOpenMax(true);
        MoveHGrabToClean(true);
    }
    else if (iStep == 25)
    {
        CProcess_Clean* pClean = GET_PROCESS(PROCESS_CLEAN, SM_CLEAN, CProcess_Clean);
        pClean->MoveSpindleInitPos(true, true);
        OpenCleanCurtain(true);
    }
    else if (iStep == 30)
    {
        LOG_INFO("Clean To Trans Start");

        MoveTransPickUpWaferFromClean();

        LOG_INFO("Clean To Trans Finish");
    }
    else if (iStep == 40)
    {
        MoveVTransRailNearReady(true);
        CloseCleanCurtain(false);
    }
    else if (iStep == 50)
    {
        MoveRailNearOpen(true);
        ClawRelease();//TODO:夹抓打开
    }
    else if (iStep == 100)
    {
        //放下
        MoveHGrabToRailNear(true);
        MoveVTransRailNear();
    }
    else if (iStep == 120)
    {
        MoveVTransRailNear(true);
        VaccumTransToRail();
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
    }
    else if (iStep == 125)
    {
        MoveVTransRailNearReady(true);
        CloseCleanCurtain(true);
    }
    else if (iStep == 250)
    {
        MoveHGrabWait(false);
        MoveVTransWait();
        MoveHGrabWait(true);
    }
    else if (iStep == 130)
    {
    }
    else if (iStep == 210)
    {
		IonBlowOff(IonClean);	//清洗桶静电消除关

        CASSSLOT* pSlot = m_pSlotRailNear;
        int iSlotID = pSlot->index + 1;
        pSlot->EndDate = QDateTime::currentDateTime();

        QTime tmpTime;
        tmpTime.setHMS(0, 0, 0, 0);                                       //初始化数据，时 分 秒 毫秒
        int secsCount = pSlot->BeginDate.secsTo(pSlot->EndDate);
        QString str = QObject::trUtf8("WaferID:%4,DID:%2,TM:%3,DNo:%1")
            .arg(m_gSystem.GetCurFile())
            .arg(iSlotID)
            .arg(tmpTime.addSecs(secsCount).toString("hh:mm:ss"))
            .arg(pSlot->WaferID);
        //m_gSystem.EvtLog(QString::fromUtf8("JOB"), str);
        m_pSlotGrab = 0;

        g_SecsManager.SendEvent(EVENT_TransClean2NearComplete);
        m_gSystem.AddProductInfo(pSlot, QString("%1 finish trans wafer cleantable to rail near").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        //m_gSystem.AddProductInfo(pSlot, QString("Job finish %1\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

        ReleaseRes(SM_TRANS, kResClean | kResRailNear | kResTransfer | kResDoorOpen | kAreaClean);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCoatToFar(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailFar && !m_pSlotCoat && !m_pSlotTrans &&
        iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans Coat to RailFar");

		AssertAcuireRes(SM_TRANS, kAreaCoat | kResTransfer | kResCoat | kResRailFar | kResDoorOpen, sTransInfo);
        AssertRailFarHasWafer(false, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);
        AssertCoatHasWafer(true, sTransInfo);

        AssertSlotExists(false, &m_pSlotRailFar, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);
        AssertSlotExists(true, &m_pSlotCoat, sTransInfo);

        AssertCoatWaferHasWater(sTransInfo);

        g_SecsManager.SendEvent(EVENT_TransCoat2FarStarted);

		IonBlowOn(IonTrans);	//D中转静电消除开
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
    }
    else if (iStep == 160)
    {
        MoveRailFarOpenMax(false);
        OpenCoatCurtain(false);
        MoveHGrabToCoat(false);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, false);
    }
    else if (iStep == 165)
    {
        MoveRailFarOpenMax(true);
        OpenCoatCurtain(true);
        MoveHGrabToCoat(true);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, true);
    }
    else if (iStep == 170)
    {
        MoveTransPickUpWaferFromCoat();
    }
    else if (iStep == 235)
    {
    }
    else if (iStep == 240)
    {
        MoveVTransRailFar(true);
    }
    else if (iStep == 245)
    {
        MoveHGrabToRailFar(true);
        MoveVTransRailFarReady(true);
    }
    else if (iStep == 250)
    {
        MoveRailFarOpen();
        MoveVTransRailFar(true);
    }
    else if (iStep == 251)
    {
        VaccumTransToRail();
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailFar);
    }
    else if (iStep == 255)
    {
        CloseCoatCurtain(false);
        //移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
        CloseCoatCurtain(true);
    }
    else if (iStep == 260)
    {
		IonBlowOff(IonTrans);	//涂覆桶静电消除关
        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to coattable")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCoat2FarComplete);
        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        ReleaseRes(SM_TRANS, kAreaCoat | kResTransfer | kResCoat | kResRailFar | kResDoorOpen);
        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }

    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransCoatToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear && !m_pSlotCoat && !m_pSlotTrans
        && iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");
        QString sTransInfo = QObject::tr("Trans Coat to RailNear");

		AssertAcuireRes(SM_TRANS, kAreaCoat | kAreaClean | kResTransfer | kResCoat | kResRailFar | kResRailNear | kResDoorOpen, sTransInfo);
        AssertRailFarHasWafer(false, sTransInfo);
        AssertRailNearHasWafer(false, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);
        AssertCoatHasWafer(true, sTransInfo);

        AssertCoatWaferHasWater(sTransInfo);
        g_SecsManager.SendEvent(EVENT_TransCoat2NearStarted);

		IonBlowOn(IonTrans);	//D中转静电消除开
    }
    else if (iStep == 150)
    {
        MoveVTransWait();
    }
    else if (iStep == 160)
    {
        MoveRailFarOpenMax(false);
        MoveRailNearOpen(false);
        OpenCoatCurtain(false);
        MoveHGrabToCoat(false);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, false);
    }
    else if (iStep == 165)
    {
        MoveRailFarOpenMax(true);
        MoveRailNearOpen(true);
        OpenCoatCurtain(true);
        MoveHGrabToCoat(true);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, true);
    }
    else if (iStep == 170)
    {
        MoveTransPickUpWaferFromCoat();
    }
    else if (iStep == 235)
    {
    }
    else if (iStep == 240)
    {
        MoveVTransRailFar(true);
        MoveVTransWait();
        CloseCoatCurtain(false);
    }
    else if (iStep == 245)
    {
        //移动到近轨道
        MoveHGrabToRailNear(true);
        MoveVTransRailNearReady(true);
    }
    else if (iStep == 250)
    {
        MoveRailNearOpen(false);
        MoveVTransRailNear(true);
    }
    else if (iStep == 251)
    {
        VaccumTransToRail();
        SlotTransfer(&m_pSlotTrans, &m_pSlotRailNear);
    }
    else if (iStep == 255)
    {
        //移动到安全位置
        MoveVTransWait();
        MoveHGrabWait();
        CloseCoatCurtain(true);
    }
    else if (iStep == 260)
    {
		IonBlowOff(IonTrans);	//涂覆静电消除关

        m_gSystem.AddProductInfo(m_pSlotCoat, QString("%1 finish trans wafer casste to coattable")
                                 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        g_SecsManager.SendEvent(EVENT_TransCoat2NearComplete);
        m_gSystem.SetWaferIdEmpty(PROCESS_TRANS);

        ReleaseRes(SM_TRANS, kAreaCoat | kAreaClean | kResTransfer | kResCoat | kResRailFar | kResRailNear | kResDoorOpen);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }

    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransWtToNear(int iStep, bool bIsAutoMode)
{
    bool bemptystep = false;
    if (!m_pSlotWT && !m_pSlotUnLoad && !m_pSlotRailNear
        && iStep > 0)
    {
        return;
    }

    if (iStep > 1 && iStep < 130)
    {
        //在此区间都是需要上锁
        QString sTransInfo = QObject::tr("Trans Worktable to RailNear");
        AssertAcuireRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean, sTransInfo);
    }
    if (iStep == 0)
    {
        FUNC_START("");

        QString sTransInfo = QObject::tr("Trans Worktable to RailNear");

		AssertAcuireRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean, sTransInfo);
        AssertWtHasWafer(true, sTransInfo);
        AssertUnloadHasWafer(false, sTransInfo);
        AssertRailNearHasWafer(false, sTransInfo);

        AssertSlotExists(true, &m_pSlotWT, sTransInfo);
        AssertSlotExists(false, &m_pSlotUnLoad, sTransInfo);
        AssertSlotExists(false, &m_pSlotRailNear, sTransInfo);

        SetWaferId(m_pSlotWT, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransWT2NearStarted);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 start trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)
    {
        MoveVUnloadWait();
        MoveHUnloadWT(false);
    }
    else if (iStep == 10)
    {
        UnloadPos();
        MoveHUnloadWT(true);
    }
    else if (iStep == 20)
    {
    }
    else if (iStep == 30)
    {
        //冗余操作
        /*MoveVUnloadWait();
        MoveHUnloadWT(true);*/

        MoveVUnLoadWT();
        VaccumWtToUnLoad();
        MoveVUnloadWait();

        //从平台取晶圆失败
        QString sInfo = "Grab from worktable checked";
       
        try
        {
            AssertUnloadHasWafer(true, sInfo);
        }
        catch (...)
        {
            m_pSlotWT->bNeedRelocation = true;
            throw;
        }

        //TODO:如果失败了,要求RailNear重新定位
        SlotTransfer(&m_pSlotWT, &m_pSlotUnLoad);
    }
    else if (iStep == 35)
    {
    }
    else if (iStep == 40)
    {        
    }
    else if (iStep == 100)
    {
        MoveHUnloadRailNear();
    }
    else if (iStep == 110)
    {
        MoveVUnloadRailNear();
        VaccumUnloadToRail();
        SlotTransfer(&m_pSlotUnLoad, &m_pSlotRailNear);
    }
    else if (iStep == 115)
    {
        MoveVUnloadWait();
    }
    else if (iStep == 120)
    {
        MoveHUnloadWait();
    }
    else if (iStep == 130)
    {
        g_SecsManager.SendEvent(EVENT_TransWT2NearComplete);
        //操作的时候可以回上料位置
        //LoadPos();
        ReleaseRes(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 finish trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }

    if (!bemptystep)
    {
        StepSleep();
    }
}

void CProcess_Trans::TransFarToCoat(int iStep, bool bIsAutoMode)
{
    //HACK:在当前调度模式下不应该出现远轨道到涂覆台的情况
    bool bemptystep = false;
    if (!m_pSlotCoat && !m_pSlotRailFar && !m_pSlotTrans
        && iStep > 0)
    {
        return;
    }
    if (iStep == 0)
    {
        FUNC_START("");

        QString sTransInfo = QObject::tr("RailFar to CoatTable");

		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailFar | kResCoat | kAreaCoat | kResDoorOpen, sTransInfo);
        AssertCoatHasWafer(false, sTransInfo);
        AssertRailFarHasWafer(true, sTransInfo);
        AssertTransHasWafer(false, sTransInfo);

        AssertSlotExists(false, &m_pSlotCoat, sTransInfo);
        AssertSlotExists(true, &m_pSlotRailFar, sTransInfo);
        AssertSlotExists(false, &m_pSlotTrans, sTransInfo);

        SetWaferId(m_pSlotWT, SVID_TransWaferID);
        g_SecsManager.SendEvent(EVENT_TransFar2CoatStarted);
        m_gSystem.AddProductInfo(m_pSlotWT, QString("%1 start trans wafer rail far to coattable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
    }
    else if (iStep == 5)
    {
        MoveVTransWait();
        MoveHGrabToRailFar(false);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, false);
    }
    else if (iStep == 10)
    {
        OpenCoatCurtain(false);
        MoveHGrabToRailFar(true);

    }
    else if (iStep == 15)
    {
        MoveVTransRailFarReady(true);
    }
    else if (iStep == 20)
    {
        MoveVTransRailFar(true);
    }
    else if (iStep == 21)
    {
        VaccumRailToTrans();
        SlotTransfer(&m_pSlotRailFar, &m_pSlotTrans);
    }
    else if (iStep == 22)
    {
        MoveVTransRailFarReady(true);
        CProcess_Coat* pCoat = GET_PROCESS(PROCESS_COAT, SM_COAT, CProcess_Coat);
        pCoat->MoveSpindleInitPos(true, true);
        MoveRailFarOpenMax(false);
        MoveHGrabToCoat(false);
    }
    else if (iStep == 23)
    {
        MoveVTransRailFarReady(true);
        MoveRailFarOpenMax(true);
        MoveHGrabToCoat(true);
    }
    else if (iStep == 25)
    {

        OpenCoatCurtain(true);
    }
    else if (iStep == 30)
    {
        MoveTransPutDownWafterToCoat();
    }
    else if (iStep == 35)
    {
        VaccumTransToCoat();
        SlotTransfer(&m_pSlotTrans, &m_pSlotCoat);
    }
    else if (iStep == 100)
    {
        MoveVTransRailFarReady(true);
        CloseCoatCurtain(false);
    }
    else if (iStep == 110)
    {
        MoveVTransWait();
    }
    else if (iStep == 120)
    {
        CloseCoatCurtain(true);
        ReleaseRes(SM_TRANS, kResDoorOpen | kResCoat);
    }
    else if (iStep == 200)
    {
        MoveHGrabWait();
    }
    else if (iStep == 250)
    {
        g_SecsManager.SendEvent(EVENT_TransFar2CoatComplete);

        m_gSystem.AddProductInfo(m_pSlotClean, QString("%1 finish trans wafer worktable to cleantable").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));
        ReleaseRes(SM_TRANS, kResTransfer | kResRailFar | kResCoat | kAreaCoat | kResDoorOpen);

        FUNC_END("");
    }
    else
    {
        bemptystep = true;
    }
    if (!bemptystep)
    {
        StepSleep();
    }
}

bool CProcess_Trans::AssertCoatHasWafer(bool bAssertExist, QString sTitleInfo, int iAlarmCode /*= ALARM_RESERVED*/)
{
    bool bExist = false;

    //如果逻辑中未记录到Wafer,则使用真空检查
    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        bExist = m_gSystem.CellExist(OUT_COAT_VACUUM, IN_COAT_VACUUM);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::tr("Coatable has no wafer")));
        }
        else
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::tr("Coatable has wafer")));
        }
    }
    return bExist;
}

bool CProcess_Trans::AssertCleanHasWafer(bool bAssertExist, QString sTitleInfo, int iAlarmCode /*= ALARM_RESERVED*/)
{
    bool bExist = false;

    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        bExist = m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::trUtf8("CleanTable has no Wafer")));
        }
        else
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::trUtf8("CleanTable has Wafer")));
        }
    }
    return bExist;
}

bool CProcess_Trans::AssertWtHasWafer(bool bAssertExist, QString sTitleInfo, int iAlarmCode /*= ALARM_RESERVED*/)
{
    bool bExist = false;

    if (m_gSystem.IsSimulator())
    {
        bExist = bAssertExist;
    }
    else
    {
        bExist = m_gSystem.CellExist(OUT_WT_WAFER_VACUUM, IN_WT_WAFER_VACUUM);
    }

    if (bAssertExist != bExist)
    {
        if (bAssertExist)
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::tr("Worktable has no wafer")));
        }
        else
        {
            MQT_THROW_CODESTR(iAlarmCode, (sTitleInfo + " " + QObject::tr("Workable has wafer")));
        }
    }
    return bExist;
}

bool CProcess_Trans::AssertAcuireRes(int vsmId, uint resId, QString info)
{
    if (ResManager().NotAcquired(vsmId, resId))
    {
        MQT_THROW_CODESTR(ALARM_RESERVED, info + "\n" + QObject::tr("Acquire Resouce not acquired at first"));
    }

    if (false == ResManager().CanAcquire(vsmId, resId))
    {
        MQT_THROW_CODESTR(ALARM_RESERVED, info + "\n" + QObject::tr("Acquire Resouce failed"));
    }

    MqDebug() << "AssertAcuireRes" << vsmId << "res" << resId;
    return ResManager().Acquire(vsmId, resId);
}

bool CProcess_Trans::ReleaseRes(int vsmId, uint resId)
{
    MqDebug() << "ReleaseRes" << vsmId << "res" << resId;
    return ResManager().Release(vsmId, resId);
}

void CProcess_Trans::MoveHGrabToRailNear(bool bWait)
{
    MoveMotorToPos(MOTORA_CLAW, Var_Process_Claw_PosRailNear, false, bWait);
}

void CProcess_Trans::MoveHGrabToRailFar(bool bWait)
{
    MoveMotorToPos(MOTORA_CLAW, Var_Process_Claw_PosRailFar, false, bWait);
}

void CProcess_Trans::MoveRailFarOpen(bool bWait)
{
    MoveMotorToPos(MOTORB2_RAIL, Var_Process_RailFar_PosOpen, false, bWait);
}

void CProcess_Trans::MoveRailFarOpenMax(bool bWait)
{
    MoveMotorToPos(MOTORB2_RAIL, Var_Process_RailFar_PosOpenMax, false, bWait);
}

void CProcess_Trans::CloseCoatCurtain(bool bWait)
{
    if (bWait)
        ResManager().Release(SM_TRANS, kResDoorOpen);

    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (bWait)
    {
        pDriver->set_cylinder(OUT_COAT_CURTAIN_OPENED, IN_COAT_CURTAIN_CLOSED, FALSE);
    }
    else
    {
        pDriver->setio(IO_OUTPUT, OUT_COAT_CURTAIN_OPENED, FALSE);
    }

}

void CProcess_Trans::OpenCoatCurtain(bool bWait)
{
    ResManager().Acquire(SM_TRANS, kResDoorOpen);

    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (bWait)
    {
        pDriver->set_cylinder(OUT_COAT_CURTAIN_OPENED, IN_COAT_CURTAIN_OPENED, TRUE);
    }
    else
    {
        pDriver->setio(IO_OUTPUT, OUT_COAT_CURTAIN_OPENED, TRUE);
    }
}

void CProcess_Trans::CloseCleanCurtain(bool bWait)
{
    if (bWait)
        ResManager().Release(SM_TRANS, kResDoorOpen);

    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (bWait)
    {
        pDriver->set_cylinder(OUT_CLEAN_CURTAIN_OPENED, IN_CLEAN_CURTAIN_CLOSED, FALSE);
    }
    else
    {
        pDriver->setio(IO_OUTPUT, OUT_CLEAN_CURTAIN_OPENED, FALSE);
    }
}

void CProcess_Trans::OpenCleanCurtain(bool bWait)
{
    ResManager().Acquire(SM_TRANS, kResDoorOpen);
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (bWait)
    {
        pDriver->set_cylinder(OUT_CLEAN_CURTAIN_OPENED, IN_CLEAN_CURTAIN_OPENED, TRUE);
    }
    else
    {
        pDriver->setio(IO_OUTPUT, OUT_CLEAN_CURTAIN_OPENED, TRUE);
    }
}

QString CProcess_Trans::GetWaferName(CASSSLOT** ppSlot)
{
    if (ppSlot == &m_pSlotRailNear)
    {
        return QObject::tr("RailNear");
    }
    else if (ppSlot == &m_pSlotRailFar)
    {
        return QObject::tr("RailFar");
    }
    else if (ppSlot == &m_pSlotTrans)
    {
        return QObject::tr("TransClaw");
    }
    
    else if (ppSlot == &m_pSlotLoad)
    {
        return QObject::tr("LoadClaw");
    }
    else if (ppSlot == &m_pSlotCoat)
    {
        return QObject::tr("Coattable");
    }
    else if (ppSlot == &m_pSlotWT)
    {
        return QObject::tr("Worktable");
    }
    else if (ppSlot == &m_pSlotClean)
    {
        return QObject::tr("Cleanable");
    }
    else if (ppSlot == &m_pSlotCheckBox)
    {
        return QObject::tr("Cupboard");
    }
    else if (ppSlot == &m_pSlotUnLoad)
    {
        return QObject::tr("UnloadClaw");
    }
    else if (ppSlot == &m_pSlotGrab)
    {
        return QObject::tr("GrabClaw");
    }
    else
    {
        return QObject::tr("Unkown");
    }
}

bool CProcess_Trans::IsCheckboxWaferUsed()
{
    CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
    CASSSLOT* pSlotCheckBox = pCass->GetCheckBoxWafer();
    if (m_pSlotCheckBox == pSlotCheckBox
        || m_pSlotClean == pSlotCheckBox
        || m_pSlotGrab == pSlotCheckBox
        || m_pSlotLoad == pSlotCheckBox
        || m_pSlotRailFar == pSlotCheckBox
        || m_pSlotRailNear == pSlotCheckBox
        || m_pSlotTrans == pSlotCheckBox
        || m_pSlotUnLoad == pSlotCheckBox
        || m_pSlotWT == pSlotCheckBox)    
    {
        return true;
    }
    else
    {
        return false;
    }
}

CASSSLOT* CProcess_Trans::CreateOrBindToCheckbox()
{
    if (IsCheckboxWaferUsed())
    {
        CASSSLOT* pSlot = new CASSSLOT();
        pSlot->Reset();
        return pSlot;
    }
    else
    {
        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        return pCass->GetCheckBoxWafer();
    }
}

void CProcess_Trans::CreateAndBindToSlot(CASSSLOT* & pSlot)
{
    if (pSlot != nullptr)
    {
        MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::tr("CreateAndBindToSlot Slot not null"));
    }
    QMutexLocker l(&m_slotMutex);
    pSlot = CreateOrBindToCheckbox();
	pSlot->WPstatus = WPABORT;
	pSlot->WaferID = "Unkown";
	pSlot->index = -1;

    
}

void CProcess_Trans::StepSleep()
{
    int ims = m_Variants.get_VData(Var_Process_Trans_StepSleepTime)
        ->toInt();
    if (ims)
    {
        MSleep(ims);
    }
}

bool CProcess_Trans::WriteRecoveredData()
{
    try
    {
        QString filePath = m_gSystem.MakeRecoverPath("TransSlot.dat");
        QFile file(filePath);
        if (!file.open(QIODevice::WriteOnly))
        {
            LOG_ERR(fmt::format("create WriteRecoveredData file failed {}", filePath.toLocal8Bit().data()));
            return false;
        }

        QList<CASSSLOT*> slotList;
        slotList.push_back(m_pSlotGrab);
        slotList.push_back(m_pSlotRailNear);
        slotList.push_back(m_pSlotTrans);
        slotList.push_back(m_pSlotCoat);
        slotList.push_back(m_pSlotLoad);
        slotList.push_back(m_pSlotWT);
        slotList.push_back(m_pSlotUnLoad);
        slotList.push_back(m_pSlotClean);
        slotList.push_back(m_pSlotCheckBox);

        QDataStream stream(&file);
        for (int i = 0; i < slotList.size(); i++)
        {
            CASSSLOT* pSlot = slotList[i];
            if (pSlot)
            {
                stream << true;
                stream << (*pSlot);
            }
            else
            {
                stream << false;
            }
        }
        file.close();
        return true;
    }
    catch (std::exception ex)
    {
        LOG_ERR(fmt::format("create WriteRecoveredData failed"));
        m_gSystem.LogInfo("Write Recovered data success");
        return false;
    }

    /*CCassette* pCass=GET_CHDIRECT(CASSETTE,CCassette);
    pCass->WriteRecoveredData();*/
}

bool CProcess_Trans::ReadRecoveredData()
{
    try
    {
        QString filePath = m_gSystem.MakeRecoverPath("TransSlot.dat");
        QFile file(filePath);
        if (!file.open(QIODevice::ReadOnly))
        {
            LOG_ERR(fmt::format("create WriteRecoveredData file failed {}", filePath.toLocal8Bit().data()));
            return false;
        }

        CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
        pCass->ReadRecoveredData();

        QList<CASSSLOT**> slotList;
        slotList.push_back(&m_pSlotGrab);
        slotList.push_back(&m_pSlotRailNear);
        slotList.push_back(&m_pSlotTrans);
        slotList.push_back(&m_pSlotCoat);
        slotList.push_back(&m_pSlotLoad);
        slotList.push_back(&m_pSlotWT);
        slotList.push_back(&m_pSlotUnLoad);
        slotList.push_back(&m_pSlotClean);
        slotList.push_back(&m_pSlotCheckBox);

        QDataStream stream(&file);
        for (int i = 0; i < slotList.size(); i++)
        {
            CASSSLOT** pSlot = slotList[i];
            bool bHas;
            stream >> bHas;
            if (bHas)
            {
                CASSSLOT slot;
                stream >> slot;

                CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
                if (slot.index >= 0)
                {
                    pCass->vslots[slot.index] = slot;
                    *pSlot = &pCass->vslots[slot.index];
                }
                else
                {
                    //如果是-1就先取CheckWafer，否则就创建
                    CASSSLOT* pCassSlot = CreateOrBindToCheckbox();
                    *pCassSlot = slot;
                    *pSlot = pCassSlot;
                }
            }
            else
            {
                *pSlot = nullptr;
            }
        }
        file.close();
        m_gSystem.LogInfo("Read Recovered data success");
        return true;
    }
    catch (std::exception ex)
    {
        LOG_ERR("ReadRecoveredData Failed");
        return false;
    }
}

void CProcess_Trans::TransRailNearWaferLocation(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear 
        && iStep > 0)
    {
        return;
    }

    if (iStep == 0)
    {
        FUNC_START("");

        QString sTransInfo = QObject::tr("RailNear Location");

		//请求安全资源
		AssertAcuireRes(SM_TRANS, kResTransfer | kResRailNear | kAreaClean, sTransInfo);
        AssertRailNearHasWafer(true, sTransInfo);

		if (!m_pSlotRailNear) {
			MQT_THROW_CODESTR(ALARM_RESERVED, QString("RailNear not has wafer"));
		}

        //手动放料
        if (!m_pSlotRailNear)
        {
            CASSSLOT* pSlotCass = CreateOrBindToCheckbox();
            pSlotCass->WPstatus = TOGRAB;
            pSlotCass->index = -1;
            SlotTransfer(&pSlotCass, &m_pSlotRailNear);
            SetWaferId(m_pSlotRailNear, SVID_TransWaferID);
        }
    }
    else if (iStep == 20)
    {
        //trans 移动到安全位置
        //MoveVTransWait();
        //MoveHGrabWait();
        MoveTransInitPos();
        MoveTransVNearPull();
    }
    else if (iStep == 45)
    {
        MoveRailNearOpen();
    }
    else if (iStep == 50)
    {
        AssertRailNearHasWafer(true, QObject::tr("RailNear has not Wafer"));

        ClawRelease(false);
    }
    else if (iStep == 70)
    {
        ClawRelease(true);
        MoveRailNearPullOpen();
        
        MoveHGrabLocationNearReady();
        MoveHGrabLocationNearSpd();

		ClawGrabed(true);   //抓料

		MoveHGrabLocationNearReady();

		//检查抓到晶元
        AssertGrabHasWafer(QObject::tr("RailNear Location Again"));

		ClawRelease();

		//再关一次用于检查轴是否报警
		MoveRailNearReadyClose();
    }
    else if (iStep == 75)
    {
        
    }
    else if (iStep == 90)
    {
       
    }
    else if (iStep == 115)
    {
        //规整操作
        MoveRailNearReadyClose();
        MoveRailNearClose();

        //检查规整异常
        MoveRailNearClose();
        AssertRailNearLocationHasWafer(true);
    }
    else if (iStep == 120)
    {	//移到规整偏移位置,即退开
        MoveHGrabLocationNearPushPrepare();
    }
    else if (iStep == 125)
    {
        //下降到推晶元位置
        MoveTransVNearPull();
    }
    else if (iStep == 130)
    {
        MoveRailNearClose();
        //规整操作，多次执行，防止轴报警异常
        MoveRailNearClose();

        //重新定位，移回规整位置
        MoveHGrabLocationNearSpd();

        //移到准备位置 即退开
        MoveHGrabLocationNearPushPrepare();

    }
    else if (iStep == 140)
    {
        AssertRailNearLocationHasWafer(true, ALARM_TRANS_ERROR_GrabWaferFailed_NotExists);
    }
    else if (iStep == 150)
    {
        MoveHGrabWait();
        MoveVTransWait();
    }
    else if (iStep == 260)
    {
        //转移完后回准备点等待
        MoveHGrabWait();

        ReleaseRes(SM_TRANS, kResTransfer | kResRailNear | kAreaClean);

        FUNC_END("");
    }
}

void CProcess_Trans::TransRailNearWaferLocationManual(int iStep)
{
    bool bemptystep = false;
    if (!m_pSlotRailNear
        && iStep > 0)
    {
        return;
    }

    if (iStep > 1 && iStep < 260)
    {
		TransRailNearWaferLocation(iStep);
    }

    if (iStep == 0)
    {
        FUNC_START("");

        QString sTransInfo = QObject::tr("RailNear Location Manual");

		//请求安全资源
		AssertAcuireRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean, sTransInfo);
        AssertRailNearHasWafer(true, sTransInfo);

        //手动放料
        if (!m_pSlotRailNear)
        {
            /*if (m_pSlotCheckBox)
            {
                MQT_THROW_CODESTR(ALARM_RESERVED, sTransInfo + "\n" + QObject::tr("Checkbox has wafer"));
            }*/

            QMutexLocker l(&m_slotMutex);
            //手动生成一个Wafer
            m_pSlotRailNear = CreateOrBindToCheckbox();
            m_pSlotRailNear->WPstatus = WPUNCUT;
            m_pSlotRailNear->WaferID = "ManualWafer";
            m_pSlotRailNear->index = -1;
        }
    }
    else if (iStep == 260)
    {
        //转移完后回准备点等待
        MoveHGrabWait();

        ReleaseRes(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean);

        FUNC_END("");
    }
}

void CProcess_Trans::TransRailFarWaferLocation(int iStep)
{
    
}