
#include "logic.h"
#include "cmotordriver_acs.h"
#include "cprocess_clean.h"
#define  ACTION_LENGTH 7
const char* CleanName[] =
{
    "INIT",
    "WATER+AIR",
    "AIR",
    "SPIN",
    "WATER(SLOW)",
    "OPEN(Curtain)",
    "CLOSE(Curtain)"
};

CProcess_Clean::CProcess_Clean(const QString &name, int32_t id)
    :CProcess_CoatClean(name, id)
{

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

    m_Variants.add_Variant(Var_Clean_Arm_Spd,
                           QObject::trUtf8("Clean_Arm_Spd"), double(4), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Clean_Arm_WaitPos_ID,
                           QObject::trUtf8("Clean_Arm_WaitPos"), double(0.1), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Clean_Arm_Edge_Pos,
                           QObject::trUtf8("Clean_Arm_Edge_Pos"), double(1), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Clean_Arm_Center_Pos,
                           QObject::trUtf8("Clean_Arm_Center_Pos"), double(45), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Clean_Arm_PerparePos_ID,
                           QObject::trUtf8("Clean_Arm_PerparePos_ID"), double(0.1), false,
                           Variant::TOXML);

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

    m_Variants.add_Variant(Var_Clean_Protect_ClosePos_ID,
                           QObject::trUtf8("Clean_Protect_ClosePos"), double(0), false,
                           Variant::TOXML);
}

void CProcess_Clean::ReadWriteCleanTable(bool bWrite)
{
    QString sFilePath = CMakePath::make_config_path(PATH_CLEANTABLE_CLEAN);
    if (bWrite) {
        WriteCleanTable(sFilePath, m_vCleanTableStep);
    } else {
        ReadCleanTable(sFilePath, m_vCleanTableStep);
    }
}

void CProcess_Clean::Init_Pos()
{
    //关闭喷头
    nozzeloperator_clean(INIT_COAT);

    //回原点
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    
    SpindleStop();
    MoveSpindleInitPos(false, false);

    MoveCleanWaitPos();
    
    CloseProtect(true);   //防水帘

    MoveSpindleInitPos(false, true);
}

QString CProcess_Clean::GetActionName(int iActionID)
{
    if (iActionID < 0 || iActionID >= ACTION_LENGTH) { return QObject::trUtf8("N/A"); }
    return QObject::trUtf8(CleanName[iActionID]);
}

void CProcess_Clean::all_action_before(int iActionType, int iStep)
{
    if (iStep == 0) {
        AddProductData(QString("Clean start at :") + 
                       QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));

        AssertAcuireRes(SM_CLEAN, kResClean, "");

        if (iActionType == NORMAL_ACTION) {
            //开真空，清洗平台的操作
            m_gSystem.VacuumSet(true, OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);
            CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
            Q_ASSERT(pMotorDriver);
            //TODO:静电消除器
            //pMotorDriver->setio(IO_OUTPUT, OUT_ELECT_Clean, true);

        } else if (iActionType == CLEANTABLE_ACTION) {
            bool bExist = m_gSystem.CellExist(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);
            if (bExist) {
                MQT_THROW_CODESTR(ALARM_CLEAN_SAFE_PROTECT, QObject::trUtf8("take off wafer before clean clean table."));
            }
            CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
            Q_ASSERT(pMotorDriver);
            pMotorDriver->setio(IO_OUTPUT, OUT_CLEAN_VACUUM_BREAK, true);
        } else {
            Q_ASSERT(0);
        }

        //主轴降下
        SpindleUp(false);
        CloseProtect(true);   //防水帘

        m_gSystem.EvtLog(QObject::tr("CLEAN"), QObject::tr("WaferID:%1,CLEAN Starting").arg(m_gSystem.GetCleanWaferId().c_str()));
    }
    CProcess_CoatClean::all_action_before(iActionType, iStep);
}
/*!
 * \brief CProcess_Clean::single_action_before
 * 清洗操作前的动作
 * \param iActionType
 * \param iType
 * \param dTime
 * \param iRPM
 * \param iStep
 */
void CProcess_Clean::single_action_before(int iActionType, int32_t iType,
                                          double dTime, int iRPM, int iStep)
{
    UNUSED(dTime);
    UNUSED(iActionType);

    if (iStep == 0) {
        AddProductData(QString("Clean Step:%1\t%2").arg(GetActionName(iType)).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
        AddProductData(QString("\tRunTime:%1s RPM:%2").arg(dTime).arg(iRPM));
    }

    if (iType == OPEN_PROTECT
        || iType == CLOSE_PROTECT) {
        if (iStep == 1) {
            if (iType == CLOSE_PROTECT) {
                CloseProtect(true, false);   //防水帘
            } else {
                CloseProtect(false, false);   //防水帘
            }
            return CProcess_CoatClean::single_action_before(iActionType, iType, dTime, iRPM, iStep);
        } else {
            return CProcess_CoatClean::single_action_before(iActionType, iType, dTime, iRPM, iStep);
        }
    }

    if (iStep == 1) nozzeloperator_clean(INIT_CLEAN); //关闭所有阀体
    if (iStep == 5) SpindleUp(false);                   //主轴下降
    //if(iStep==10) CloseProtect( true);                //关闭保护罩
    if (iStep == 15) CleanArmUp(true);                  //TODO:
    if (iStep == 20) MoveCleanWaitPos();                //移动到等待位置 TODO:清洗有两个臂
    if (iStep == 25)
    {
        //旋转前需要检查真空是否OK
        if (iActionType == NORMAL_ACTION)
        {
            CheckVaccum();
        }
        SpindleSpin(iRPM);                  //主轴旋转
    }

    switch (iType) {
        case WASHING:
        {
            if (iStep == 30) MoveCleanEagePos();              //摆臂移动到清洗边缘
            if (iStep == 35) nozzeloperator_clean(WASHING);    //清洗操作
            if (iStep == 40) MoveCleanCyclic();               //手臂边缘到中心按设定速度的往复运动hack:往复运动中，一旦控制轴运动，则往复运动结束
            break;
        }
        case AIR:			//只开二流体气阀
        {
            if (iStep == 50) MoveCleanEagePos();
            if (iStep == 55) nozzeloperator_clean(AIR);
            if (iStep == 60) MoveCleanCyclic();
            break;
        }
        case WASH_NOAIR:
        {
            if (iStep == 50) MoveCleanEagePos();
            if (iStep == 55) nozzeloperator_clean(WASH_NOAIR);
            if (iStep == 60) MoveCleanCyclic();
            break;
        }
        case SPIN:
        {
            //if(iStep==70) MoveCleanWaitPos( );
            if (iStep == 75) nozzeloperator_clean(SPIN);     //只吹气
            //if(iStep==80) MoveCleanCyclic( );
            //if(iStep==80) MoveCleanCenterPos( );            //移动中心
            //if(iStep==85) MoveCleanEagePos( );              //移到边缘
            //if(iStep==90) MoveCleanCenterPos( );            //移动中心
            //if(iStep==95) MoveCleanEagePos( );              //移到边缘
            //if(iStep==100) nozzeloperator_clean(INIT_CLEAN);    //到初始状态
            //if(iStep==105) MoveCleanWaitPos( );             //手臂移动到等待位置
            break;
        }
    }
    //开始计时
    CProcess_CoatClean::single_action_before(iActionType, iType, dTime, iRPM, iStep);

}

/*!
 * \brief CProcess_Clean::single_action_wait
 * 清洗时的动作
 * \param iActionType 操作类型
 * \param iType 清洗类型
 * \param dTime 时间
 * \param iRPM 转速
 * \param iStep
 * \return
 */
bool CProcess_Clean::single_action_wait(int iActionType, int32_t iType,
                                        double dTime, int iRPM, int iStep)
{
    UNUSED(iStep);
    UNUSED(iRPM);
    if (iActionType == NORMAL_ACTION) {
        CheckVaccum();
    } else if (iActionType == CLEANTABLE_ACTION) {} else { Q_ASSERT(0); }

    switch (iType) {
        case WASHING:
        {
            CheckWater();
            break;
        }
        case WASH_NOAIR:
        {
            CheckWater();
            break;
        }
        case SPIN: //甩干主轴旋转
        {
            break;
        }
    }
    return    CProcess_CoatClean::single_action_wait(iActionType, iType, dTime, iRPM, iStep);

}

/*!
 * \brief CProcess_Clean::single_action_after
 * 结束时恢复状态
 * \param iActionType
 * \param iType
 * \param dTime
 * \param iRPM
 * \param iStep
 */
void CProcess_Clean::single_action_after(int iActionType, int32_t iType, double dTime, int iRPM, int iStep)
{
    if (iStep == 0) {
        AddProductData(QString("\tClean Step End:%1\t%2").arg(GetActionName(iType)).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
    }
    //恢复默认速度，计时器结束
    CProcess_CoatClean::single_action_after(iActionType, iType, dTime, iRPM, iStep);
    if (iStep == 1) m_COAT_CLEAN_TIME.StopTime();
    if (iStep == 5) nozzeloperator_clean(INIT_CLEAN); //IO恢复
    if (iStep == 15) MoveCleanWaitPos();          //手臂回等待位置

}

void CProcess_Clean::all_action_after(int iActionType, int iStep)
{
    CMotorDriver *pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);

    if (iStep == 1) m_COAT_CLEAN_TIME.StopTime();
    if (iStep == 5) {
        if (iActionType == NORMAL_ACTION) {
        } else if (iActionType == CLEANTABLE_ACTION) {
            CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
            Q_ASSERT(pMotorDriver);
            pMotorDriver->setio(IO_OUTPUT, OUT_CLEAN_VACUUM_BREAK, false);
        } else { Q_ASSERT(0); }

        //停止主轴旋转
        SpindleStop();

        //恢复轴的默认速度
        SetdefaultSpeed();
    }
    if (iStep == 15)MoveCleanWaitPos();//手臂回等待位置
    if (iStep == 25) {
        CloseProtect(true, false);					//关闭防水帘
        MoveSpindleInitPos(true, false);           //主轴回原点并到初始位置
    }
    if (iStep == 28) {
        Wait_Spindle_finish();
        CloseProtect(true, true);
    }
    if (iStep == 30)CleanArmUp(false);
    if (iStep == 35)SpindleUp(true);       //主轴升起
    else if (iStep == 40) {
        AddProductData(QString("Clean finish at:%1 Spend time:%2S").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")).arg(m_COAT_CLEAN_TIME.GetTime()));
        m_gSystem.EvtLog(QObject::tr("CLEAN"), QObject::tr("WaferID:%1,CLEAN Finished").arg(m_gSystem.GetCleanWaferId().c_str()));
        ReleaseRes(SM_CLEAN, kResClean);
    }
    CProcess_CoatClean::all_action_after(iActionType, iStep);
}

void CProcess_Clean::Wait_Spindle_finish()
{
    CMotorDriver *pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);

    pMotorDriver->wait_move_finished(MOTORF_CLEAN_SPINDLE);
    //pMotorDriver->wait_move_finished(MOTORF4_CLEAN_CURTAIN);
}

/*!
 * \brief CProcess_Clean::nozzeloperator_clean
 * 涂敷操作
 * \param iType
 */
void  CProcess_Clean::nozzeloperator_clean(int32_t iType)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    switch (iType) {
        case WASHING:
            //打开二流体的气阀和水阀
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_AIR, true);
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_WATER, true);
			pDriver->setio(IO_OUTPUT, OUT_CLEAN_ELECT_AIR, true);
			//pDriver->setio(IO_OUTPUT, OUT_CLEAN_AIR, true);
            SetWaferHasWafer(true);
            break;
        case SPIN:
            //打开吹气阀
            //pDriver->setio(IO_OUTPUT,OUT_CLEAN_AIR,true);
            SetWaferHasWafer(false);
            break;
        case WASH_NOAIR:
            //只打开水阀
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_WATER, true);
            //pDriver->setio(IO_OUTPUT, OUT_CLEAN_WATER_SLOW, true);
            SetWaferHasWafer(true);
            break;
        case AIR:
            //只打开吹气阈
            //pDriver->setio(IO_OUTPUT, OUT_CLEAN_AIR, true);
            //pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_AIR, true);
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_ELECT_AIR, true);
            SetWaferHasWafer(false);
            //pDriver->setio(IO_OUTPUT,OUT_CLEAN_TWOFLUID_WATER,false);
            break;
        default:
            //清洗吹气阀
            //清洗二体水阀
            //清洗二流体气阀
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_AIR, FALSE);
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_AIR, FALSE);
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_TWOFLUID_WATER, FALSE);
            pDriver->setio(IO_OUTPUT, OUT_CLEAN_ELECT_AIR, FALSE);

            break;
    }
}

void CProcess_Clean::CleanArmUp(bool bUp)
{
    UNUSED(bUp);
}
//
///*!
// * \brief CProcess_Clean::SpindleUp
// * \param bUp
// * bUP=true 升起
// * bUP=false 降下
// */
void CProcess_Clean::SpindleUp(bool bUp, bool bAfterChecked/*=false*/)
{
//    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
//    Q_ASSERT(pDriver);
//    int iTimeOut = m_Variants.get_VData(Var_CoatClean_Spindle_Move_TimeOut)
//        ->toInt();
//    if (false == bAfterChecked) {
//        if (bUp) {
//            //主轴升起
//            pDriver->set_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                  IN_CLEAN_SPINDLE_UP_FORWARD, true, iTimeOut);
//        } else {
//            //主轴缩回
//            pDriver->set_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                  IN_CLEAN_SPINDLE_DOWN_BACK, FALSE, iTimeOut);
//        }
//    } else {
//        if (bUp) {
//            //主轴升起
//            pDriver->set_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                  -1, true, iTimeOut);
//        } else {
//            //主轴缩回
//            pDriver->set_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                  -1, FALSE, iTimeOut);
//        }
//    }
}
//
//
void CProcess_Clean::SpindleUpCheck(bool bUp)
{
//#ifdef __SIMULATOR__
//    return;
//#endif // __SIMULATOR__
//    CMotorDriver_Base* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver_Base);
//    Q_ASSERT(pDriver);
//    int iTimeOut = m_Variants.get_VData(Var_CoatClean_Spindle_Move_TimeOut)
//        ->toInt();
//    if (bUp) {
//        //主轴升起
//        pDriver->check_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                IN_CLEAN_SPINDLE_UP_FORWARD, true, iTimeOut);
//    } else {
//        //主轴缩回
//        pDriver->check_cylinder(OUT_CLEAN_SPINDLE_UPDOWN,
//                                IN_CLEAN_SPINDLE_DOWN_BACK, FALSE, iTimeOut);
//    }
}
//
//bool CProcess_Clean::isSpindleUp()
//{
//    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
//    Q_ASSERT(pDriver);
//    return pDriver->get_iodata(IO_INPUT, IN_CLEAN_SPINDLE_UP_FORWARD, true);
//}

/*!
 * \brief CProcess_Clean::MoveCleanWaitPos
 * 手臂移动到等待位置
 */
void CProcess_Clean::MoveCleanWaitPos()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dHeadCleanWaitPos = m_Variants.get_VData(Var_Clean_Arm_WaitPos_ID)
        ->toDouble();
    pDriver->absmove(MOTORF1_CLEAN_ARM, dHeadCleanWaitPos, TRUE);
}

void CProcess_Clean::MoveCleanPreparePos()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dCleanPreparePos = m_Variants.get_VData(Var_Clean_Arm_PerparePos_ID)
        ->toDouble();
    pDriver->absmove(MOTORF1_CLEAN_ARM, dCleanPreparePos, TRUE);
}
/*!
 * \brief CProcess_Clean::MoveCleanEagePos
 * 移动到清洗边缘
 */
void CProcess_Clean::MoveCleanEagePos()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dCleanEagePos = m_Variants.get_VData(Var_Clean_Arm_Edge_Pos)
        ->toDouble();
    pDriver->absmove(MOTORF1_CLEAN_ARM, dCleanEagePos, TRUE);
}

void CProcess_Clean::MoveCleanCenterPos()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dcleancenterpos = m_Variants.get_VData(Var_Clean_Arm_Center_Pos)
        ->toDouble();
    pDriver->absmove(MOTORF1_CLEAN_ARM, dcleancenterpos, TRUE);
}

/*!
 * \brief CProcess_Clean::MoveCleanCyclic
 * 手臂边缘到中心按设定速度的往复运动
 */
void CProcess_Clean::MoveCleanCyclic()
{
    if (m_gSystem.IsSimulator()) return;
    CMotorDriver_ACS* pAcsMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver_ACS);
    Q_ASSERT(pAcsMotorDriver);
    double PT[3], PTSPD[3];
    PT[0] = m_Variants.get_VData(Var_Clean_Arm_Edge_Pos)
        ->toDouble();
    PT[1] = m_Variants.get_VData(Var_Clean_Arm_Center_Pos)
        ->toDouble();
    PT[2] = PT[0];
    PTSPD[0] = m_Variants.get_VData(Var_Clean_Arm_Spd)
        ->toDouble();
    PTSPD[2] = PTSPD[1] = PTSPD[0];
    pAcsMotorDriver->MultiPointMove(MOTORF1_CLEAN_ARM, PT, 3, true, PTSPD);
}

/*!
 * \brief CProcess_Clean::MoveSpindleInitPos
 * 主轴回原点并到初始位置
 * \param bhome
 */
void CProcess_Clean::MoveSpindleInitPos(bool bhome/* =true*/, bool bWait)
{
    if (isSpindleHomed()) return;
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    double dSpindleAfterCleanPos = m_Variants.get_VData(Var_Clean_Spindle_InitPos_ID)
        ->toDouble();

    //Offset 35
    if (bhome) {
        int curPos = (int)pDriver->get_posdata(MOTORF_CLEAN_SPINDLE, true);
        CMotor* pMotor = static_cast<CMotor*>(pDriver->FindChannel(MOTORF_CLEAN_SPINDLE));
        bool bEnabled = pMotor->m_Variants.get_VData(Var_Motor_Axis_Enabled)->toBool();
        bool bHomed = pMotor->m_Variants.get_VData(Var_Motor_Hashome_ID)->toBool();
        if (!bEnabled || !bHomed)
        {
            //如果掉使能或者未回原,则直接回原点
            pDriver->home(MOTORF_CLEAN_SPINDLE, true);
        }
        else if (fabs(curPos) > 360) 
        {
            double dTargetPos = -20;
            double calcPos = curPos % 360;

            double distance1 = calcPos - (-360 + dTargetPos);
            double distance2 = calcPos - (0 + dTargetPos);
            double distance3 = calcPos - (360 + dTargetPos);
            double calcOffset = distance1;

            if (fabs(distance2) < fabs(calcOffset))
            {
                calcOffset = distance2;
            }
            if (fabs(distance3) < fabs(calcOffset))
            {
                calcOffset = distance3;
            }

            curPos -= calcOffset;

            pDriver->setspeed(MOTORF_CLEAN_SPINDLE, 200, 0, 0, 0, 0);
            pDriver->absmove(MOTORF_CLEAN_SPINDLE, curPos, true);
            pDriver->home(MOTORF_CLEAN_SPINDLE, true);
        }
        else
        {
            //如果已经回原了
            //do nothing
        }
    }
    pDriver->setdefaultspeed(MOTORF_CLEAN_SPINDLE);
    pDriver->absmove(MOTORF_CLEAN_SPINDLE, dSpindleAfterCleanPos, bWait);
}

/*!
 * \brief CProcess_Clean::SetdefaultSpeed
 * 恢复默认速度
 * \param bSetSpindle
 */
void CProcess_Clean::SetdefaultSpeed(bool bSetSpindle/*=true*/)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    if (bSetSpindle) {
        pDriver->setdefaultspeed(MOTORF_CLEAN_SPINDLE);
    }
    pDriver->setdefaultspeed(MOTORF1_CLEAN_ARM);
}

/*!
 * \brief CProcess_Clean::SpindleSpin
 * 主轴旋转
 * drpm 转每分
 * \param drpm
 */
void CProcess_Clean::SpindleSpin(double drpm)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->startmove(MOTORF_CLEAN_SPINDLE, fabs(drpm * 360 / 60));
}

/*!
 * \brief CProcess_Clean::SpindleStop
 * 停止主轴旋转
 */
void CProcess_Clean::SpindleStop()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    pDriver->stopmove(MOTORF_CLEAN_SPINDLE);
    MSleep(3000);
    pDriver->setdefaultspeed(MOTORF_CLEAN_SPINDLE);
}

void CProcess_Clean::CheckVaccum()
{
    if (m_gSystem.IsSimulator()) {
        return;
    }

    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (!pDriver->get_iodata(IO_OUTPUT, OUT_CLEAN_VACUUM, true)) {
        MQT_THROW_CODESTR(ALARM_CLEAN_CleanVaccumOFF, QObject::trUtf8("Vacuum %1 is Off,while cleaning")
                          .arg(pDriver->getioname(IO_OUTPUT, OUT_CLEAN_VACUUM)));
    }
    m_gSystem.VacuumLeakCheck(OUT_CLEAN_VACUUM, IN_CLEAN_VACUUM);
}

void CProcess_Clean::CheckWater()
{
    //TODO:执行清洗的操作
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);
    if (pDriver->get_iodata(IO_INPUT, IN_WATER_PRESSURE, true)) {
        MQT_THROW_CODESTR(ALARM_CLEAN_CleanWaterPressureLow, QObject::trUtf8("water press is Low,while cleaning"));
    }
}

/*!
 * \brief CProcess_Clean::CloseProtect
 * 打开 关闭保护罩
 * \param bClose
 * bClose true 关闭
 *
 */
void CProcess_Clean::CloseProtect(BOOL bClose, bool bWait)
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    if (bClose) {
        pDriver->set_cylinder(OUT_CLEAN_CURTAIN_OPENED, IN_CLEAN_CURTAIN_CLOSED, FALSE);
    } else {
        pDriver->set_cylinder(OUT_CLEAN_CURTAIN_OPENED, IN_CLEAN_CURTAIN_OPENED, TRUE);
    }
}

void CProcess_Clean::SetWaferHasWafer(bool bHas)
{
    CProcess_Trans* ptrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS,
                                         CProcess_Trans);

    QMutexLocker(&ptrans->m_slotMutex);
    if (ptrans->m_pSlotClean)
    {
        ptrans->m_pSlotClean->bHasWater = bHas;
    }
}
