#include "cprocess_laserpowercali.h"
#include "common_include.h"
#include "cpowermeter.h"
#include "cpowermeterdriver.h"
#include "claserpathdriver.h"
//#include "claserpathdriver_epulse.h"
#include "cpowermeterdriver_lp.h"
#include "claserdriver_sp.h"
#include <QDateTime>
//#include "claserpathdriver_thorlab.h"
CProcess_LaserPowerCali::CProcess_LaserPowerCali(const QString& name,
                                                 int32_t id,
                                                 int32_t iLaserPathID)
    :CMProcess(name, id)
{
    m_iLaserPathID = iLaserPathID;

    m_Variants.add_Variant(Var_Process_LaserPowerCali_XPos,
                           QObject::trUtf8("XPos"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_YPos,
                           QObject::trUtf8("YPos"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_ZPos,
                           QObject::trUtf8("ZPos"), double(0), false,
                           Variant::TOXML);
    //EPULSE为次数
    m_Variants.add_Variant(Var_Process_LaserPowerCali_Step,
                           QObject::trUtf8("AngleStep"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_MeasTime,
                           QObject::trUtf8("MeasTime"), int(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_StableTime,
                           QObject::trUtf8("StableTime"), int(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_StableThres,
                           QObject::trUtf8("Stable_Thres"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_LaserPowerCali_PowerCheck_Thres,
                           QObject::trUtf8("Check_Thres"), double(0), false,
                           Variant::TOXML);
    //功率复检百分比偏差
    m_Variants.add_Variant(Var_Process_LaserPowerCali_PowerCheck_ThresPercent,
                           QObject::trUtf8("PowerCheckThresPercent"), double(0), false,
                           Variant::TOXML);


    m_Variants.add_Variant(Var_Process_PowerCali_Type,
                           QObject::trUtf8("PowerCaliType"), uint(0), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_PowerChekDate,
                           QObject::trUtf8("PowerCheckDateTime"), QString("2024-01-01 10:00:00"), false,
                           Variant::TOXML);

                       //功率检测类型 0不使用 1 首片 2每片 3按频率 4按时间间隔
    m_Variants.add_Variant(Var_Process_PowerCheckType,
                           QObject::trUtf8("PowerCheckMethod"), uint(0), false,
                           Variant::TOXML, QStringList() << "No Use" << "1'st" << "Every" << "Every Interval" << "Time Interval");

                       //功率检测时间间隔
    m_Variants.add_Variant(Var_Process_PowerCheckTimeInterval,
                           QObject::trUtf8("PowerCheckTimeInterval"), int(10), false,
                           Variant::TOXML);

                       //功率复检频率
    m_Variants.add_Variant(Var_Process_PowerCheckFreq,
                           QObject::trUtf8("PowerCheckFreq"), int(3), false,
                           Variant::TOXML);

                       /*m_Variants.add_Variant(Var_Process_LaserLightBeam_XPos,
                       QObject::trUtf8("Light_Beam_XPos"),double(0),false,
                       Variant::TOXML);
                       m_Variants.add_Variant(Var_Process_LaserLightBeam_YPos,
                       QObject::trUtf8("Light_Beam_YPos"),double(0),false,
                       Variant::TOXML);
                       m_Variants.add_Variant(Var_Process_LaserLightBeam_ZPos,
                       QObject::trUtf8("Light_Beam_ZPos"),double(0),false,
                       Variant::TOXML);*/

    m_iCurFreq = 50;
    m_dCurWidth = 0;
    m_iLastCheckPowerWafer = 0;
}

//移动到功率测量位置
int CProcess_LaserPowerCali::MoveCaliPos()
{
    CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pDriver);


    double dXPos = m_Variants.get_VData(Var_Process_LaserPowerCali_XPos)
        ->toDouble();
    double dYPos = m_Variants.get_VData(Var_Process_LaserPowerCali_YPos)
        ->toDouble();
    double dZPos = m_Variants.get_VData(Var_Process_LaserPowerCali_ZPos)
        ->toDouble();

    if(LASER_ON == pDriver->get_iodata(IO_OUTPUT, OUT_LASERGATE, true)) {
        MQT_THROW_CODESTR(ALARM_MOTION_MOVE_CALI_FAIELD_LASERON, QObject::tr("Move cali. pos can't move,because Laser On"));
    }
    pDriver->absmove(MOTORZ, dZPos);
    _SysExt_Instance.absmove_xy(dXPos, dYPos);
    //CLaserDriver* pLaserDriver=GET_CARD(LASER_DRIVER,CLaserDriver);
    //Q_ASSERT(pLaserDriver);
    //关光
    //pLaserDriver->OpenLaserGate(LASERPATH_D_NARROW,FALSE);


    //CLaserPathDriver* pPathDriver=GET_CARD(LASERPATH_DRIVER,
    //                                       CLaserPathDriver);
    //Q_ASSERT(pPathDriver);
    //pPathDriver->MovePathInitAngle(m_iLaserPathID);

    return MSG_FINISHED;
}


int CProcess_LaserPowerCali::WaitMeasStable()
{
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    //    pLaserDriver->SetGateSource(LASER,true);
    MSleep(m_Variants.get_VData(Var_Process_LaserPowerCali_MeasTime)
           ->toInt());
    CPreciseTime timeCost;
    timeCost.StartTime();
    int  iTimeCount = 0;
    int  iWaitTime = m_Variants.get_VData(Var_Process_LaserPowerCali_StableTime)
        ->toInt();
    double dMeasStableThres = m_Variants.get_VData(Var_Process_LaserPowerCali_StableThres)
        ->toDouble();
	CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER, CPowerMeterDriver_lp);
	Q_ASSERT(pPowerMeterDriver);
    do {
        CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD,
                                                    CPowerMeter);
        Q_ASSERT(pPowerMeterHead);
        try {
            pPowerMeterDriver->freshresult(POWERMETERHEAD);

        } catch(const QString& ex) {
            continue;
        }

        double dPower1 = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
            ->toDouble();

        MSleep(100);
        try {
            pPowerMeterDriver->freshresult(POWERMETERHEAD);
        } catch(const QString& ex) {
            continue;
        }

        double dPower2 = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
            ->toDouble();
        if(fabs(dPower2 - dPower1) < fabs(dMeasStableThres)) {
            break;
        }
        iTimeCount = DWORD(timeCost.GetTime() * 1000);
    } while(iTimeCount < iWaitTime);
    timeCost.StopTime();
    //    pLaserDriver->SetGateSource(LASER,false);
    if(iTimeCount >= iWaitTime) {
        pLaserDriver->OpenLaserGate(LASER, FALSE);
        pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
        MQT_THROW_CODESTR(ALARM_POWERCALI_WaitLaserStableTimeOut, QObject::trUtf8("Meas power err. Wait Meas Stable TIME OUT"));
    }
    return 0;
}


void CProcess_LaserPowerCali::WaitPowermeterReady(double dTargetPower)
{
	CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
	Q_ASSERT(pLaserDriver);
	CPreciseTime timeCost;
	timeCost.StartTime();
	int  iTimeMs = 0;
	int  iWaitTime = m_Variants.get_VData(Var_Process_LaserPowerCali_StableTime)
		->toInt();
	iWaitTime *= 2;
	CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER, CPowerMeterDriver_lp);
	Q_ASSERT(pPowerMeterDriver);
	do {
		CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD,
			CPowerMeter);
		Q_ASSERT(pPowerMeterHead);
		try {
			pPowerMeterDriver->freshresult(POWERMETERHEAD);

		}
		catch (const QString& ex) {
			continue;
		}

		double dPower1 = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
			->toDouble();

		MSleep(200);
		try {
			pPowerMeterDriver->freshresult(POWERMETERHEAD);
		}
		catch (const QString& ex) {
			continue;
		}

		//当前功率小于目标功率的90%或者 小于0.5W则认为稳定
        if(dPower1 < dTargetPower * 0.9 || dPower1 < 0.5) {
            {
                return;;
            }
		}
        iTimeMs = DWORD(timeCost.GetTime() * 1000);
	} while (iTimeMs < iWaitTime);
	
    //下降到测量值超时
	timeCost.StopTime();
	if (iTimeMs > iWaitTime) {
		pLaserDriver->OpenLaserGate(LASER, FALSE);
		pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
		MQT_THROW_CODESTR(ALARM_POWERMETER_NOTREADY, QObject::trUtf8("Meas power err. Wait power meter Drop to ready timeout"));
	}
}

void CProcess_LaserPowerCali::before_cali_power(int iFreq, int iEpulse, double dBeamWidth)
{
    Q_UNUSED(dBeamWidth);
    //int iWidth=int(dWidth*1000);

    //    CMotorDriver* pMotorDriver=GET_CARD(MOTORDRIVER,CMotorDriver);
    //    Q_ASSERT(pMotorDriver);
	CLaserDriver_Base* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver_Base);
    Q_ASSERT(pLaserDriver);


    CLaserPathDriver* pLPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
    Q_ASSERT(pLPathDriver);

    MoveCaliPos();
    //开光
    pLaserDriver->OpenLaserGate(LASER, false);

    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    POWERPOSVECTOR Param;
    bool b = pLpath->FindPowerPosVector(iFreq, iEpulse, dBeamWidth, Param);
    if(!b) {
        int iWidth = dBeamWidth * 1000;
        if(m_iLaserPathID != LASERPATH_D_WIDE) {
            iWidth = 0;
        }
        QPair<CPowerIndex, POWERPOSVECTOR> ParamPair(CPowerIndex(iFreq, iEpulse, iWidth), Param);
        pLpath->m_mPowerCali.push_back(ParamPair);
    } else {
        Param.clear();
    }

    //移动到光路位置
    pLPathDriver->MoveBeamWidthPos(m_iLaserPathID, dBeamWidth);

    pLaserDriver->SetFreq(LASER, iFreq);
    pLaserDriver->SetEpulseFreq(LASER, iEpulse*1000);
    pLpath->m_vPowerPos.clear();

    //打开光闸
	pLPathDriver->OpenShutter(m_iLaserPathID, true);

    m_dLastPower = 0;
}
void CProcess_LaserPowerCali::cali_power(int iFreq, int iEpulse, double dBeamWidth, int iStep)
{
    //限制最大功率15W
    /*if (m_dLastPower > 15)
    {
        return;
    }*/

    if (_SysExt_Instance.m_bEMG)return;
    //开光
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    pLaserDriver->OpenLaserGate(LASER, true);
	OpenLensOutBlow(false);

    CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD, CPowerMeter);
    Q_ASSERT(pPowerMeterHead);
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
       
	CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER, CPowerMeterDriver_lp);
	Q_ASSERT(pPowerMeterDriver);
    double dStep = m_Variants.get_VData(Var_Process_LaserPowerCali_Step)
        ->toDouble();
    if(DEQUAL0(dStep)) {
        pLaserDriver->OpenLaserGate(LASER, false);
        pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
        MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("Cali laser power err. Step equal 0"));
    }

    //TODO:功率测量
    double dPowerMaxAngle = pLpath->m_Variants.get_VData(Var_LaserPath_PowerMaxAngle_ID)
        ->toDouble();
    double dAngleOffset = (iStep - 1) * dStep;
    double dAngle = dPowerMaxAngle + 45 + dAngleOffset;

    pMotorDriver->absmove(MOTORG2_POWER, dAngle);

    if(!_SysExt_Instance.IsSimulator()) {
        WaitMeasStable();
    }

    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();

    if(dPower > 0.1 &&  dPower > m_dLastPower+0.1) {
        PowerParamIndex PosParam;
        PosParam.dIndex = dAngle;
        PosParam.dPower = dPower;
        PosParam.dPower_RT = dPower / iFreq;
        pLpath->m_vPowerPos.push_back(PosParam);

        m_dLastPower = dPower;
    }

    m_iCurFreq = iFreq;
    m_dCurWidth = dBeamWidth;
    m_iCurEpulse = iEpulse;
    pLaserDriver->OpenLaserGate(LASER, false);
}

void CProcess_LaserPowerCali::after_cali_power(int iFreq, int iEpulse, double dBeamWidth)
{
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    pLaserDriver->OpenLaserGate(LASER, false);
	CLaserPathDriver* pPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
	Q_ASSERT(pPathDriver);
    //关闭光闸
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	pPathDriver->OpenShutter(m_iLaserPathID, false);

    if (_SysExt_Instance.m_bEMG)
    {
        return;
    }

    _SysExt_Instance.m_SysMsg.SetMsg(QObject::trUtf8("Q:%1KHz E:%2KHz W:%3mm power cali. finish")
                              .arg(iFreq).arg(iEpulse).arg(dBeamWidth));

    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    bool b = pLpath->AddPowerPosVector(iFreq, iEpulse, dBeamWidth, pLpath->m_vPowerPos);
    UNUSED(b);
    LOG_INFO(QObject::trUtf8("Q:%1KHz E:%2KHz W:%3mm power cali. finish")
             .arg(iFreq).arg(iEpulse).arg(dBeamWidth).toLocal8Bit().data());

	CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER, CPowerMeterDriver_lp);
	Q_ASSERT(pPowerMeterDriver);
    pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
}

void CProcess_LaserPowerCali::check_power_diff(int iFreq, int iEpulse, double dBeamWidth,
                                               double dRealPower, bool report)
{
    QString msg;
    bool bCanStart;
    CLaserDriver_SP* pLaser = GET_CARD(LASER_DRIVER, CLaserDriver_SP);
    if (!_SysExt_Instance.m_bEnbaleLaserOpen)
    {
        msg = QObject::tr("Not enable laser");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    if(!pLaser->m_bInited) {
        msg = QObject::tr("Laser is not connected");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    if(pLaser->m_bError) {
        msg = QObject::tr("Laser is error, please contact manager");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    if(pLaser->m_bPreheat) {
        msg = QObject::tr("Laser is preheating,please waiting");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    if(!pLaser->m_bEmissionOn) {
        msg = QObject::tr("Laser is not opened");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    if(!pLaser->m_bInternalGate) {
        msg = QObject::tr("Laser Inner Gate not opened");
        MQT_THROW_CODESTR(ALARM_POWERMETER_LASERNOTREADY, msg);
    }

    _SysExt_Instance.SendEvent(EVENT_PowerCheckStarted);

    CLaserPathDriver* pPathDriver = GET_CARD(LASERPATH_DRIVER,
                                             CLaserPathDriver);
    Q_ASSERT(pPathDriver);
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);

    pLaserDriver->OpenLaserGate(LASER, FALSE);

    //重置0
    CPowerMeterDriver_lp* pPowerMeterDriver = GET_CARD(POWERMETERDRIVER,
                                                       CPowerMeterDriver_lp);
    Q_ASSERT(pPowerMeterDriver);
    pPowerMeterDriver->m_sCurCheckInfo = QObject::tr("Move to cali pos");
    MoveCaliPos();

    //pLaserDriver->SetGateSource(LASER,TRUE);
    pPathDriver->MovePathAngle(m_iLaserPathID, iEpulse, dBeamWidth,
                               iFreq, dRealPower);

	CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD,
		CPowerMeter);
	Q_ASSERT(pPowerMeterHead);

    _SysExt_Instance.SendEvent(EVENT_PowerCheckStarted);

    QString strBegin = QObject::trUtf8("PWCHK:Q:%1KHz E:%2KHz W:%3mm Power:%4W ").arg(iFreq).arg(iEpulse).arg(dBeamWidth).arg(dRealPower);
    _SysExt_Instance.SendLogMessage(strBegin, NOTIFY_MSG_TYPE);
    pPowerMeterDriver->m_sCurCheckInfo = strBegin;

    CPreciseTime tm;
    tm.StartTime();
    pLaserDriver->OpenLaserGate(LASER, TRUE);

    //TODO:是否需要吹一下
    MSleep(100);

	//关闭吹风
	OpenLensOutBlow(false);

    WaitPowermeterReady(dRealPower);

    WaitMeasStable();

    MSleep(m_Variants.get_VData(Var_Process_LaserPowerCali_MeasTime)
           ->toInt());

    try {
        pPowerMeterDriver->freshresult(POWERMETERHEAD);
    } catch(const QString& ex) {
        pLaserDriver->OpenLaserGate(LASER, FALSE);
        pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
        MQT_THROW_CODESTR(ALARM_POWERMETER_COMMUNICATION, ex);
    }

    tm.StopTime();
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();

    //检查完了关闭激光
    pLaserDriver->OpenLaserGate(LASER, FALSE);
    double percent = fabs(dPower - dRealPower) / dRealPower * 100;
    QString str = QObject::trUtf8("TM:%1,"
                                  "Freq:%2,Epulse:%6,BeamWidth:%7,PWInput:%3W,PWOutput:%4W,"
                                  "Percent:%5%")
        .arg(tm.FormatTime())
        .arg(iFreq)
        .arg(dRealPower)
        .arg(dPower).arg(percent)
        .arg(iEpulse).arg(dBeamWidth);

    pPowerMeterDriver->m_sCurCheckInfo = QObject::tr("Check finish");

    //添加光路的描述
    str += "," + _SysExt_Instance.m_mapNameList.at(m_iLaserPathID);
    _SysExt_Instance.EvtLog(QObject::trUtf8("PWCHKD"), str);
    _SysExt_Instance.SendLogMessage(str, NOTIFY_MSG_TYPE);

    _SysExt_Instance.SetVariable(SVID_LaserCheckPower, QString::number(dPower, 'f', 2).toStdString());
    _SysExt_Instance.SetVariable(SVID_LaserDetectedPower, QString::number(dRealPower, 'f', 2).toStdString());
    _SysExt_Instance.SendEvent(EVENT_PowerCheckComplete);
    AddProductData(str);

    CProcess_LaserPowerCali* pProcess = GET_PROCESS(PROCESS_POWERCALI_D_NARROW, SM_MAIN, CProcess_LaserPowerCali);
    double dthres = pProcess->m_Variants.get_VData(Var_Process_LaserPowerCali_PowerCheck_Thres)->toDouble();
    double dthresPercent = pProcess->m_Variants.get_VData(Var_Process_LaserPowerCali_PowerCheck_ThresPercent)->toDouble();

    if(fabs(dPower - dRealPower) > dthres && percent > dthresPercent) {
        str += QObject::trUtf8("\nPower check over threshold:%1W Percent:%2%")
            .arg(dthres).arg(dthresPercent);
        MQT_THROW_CODESTR(ALARM_PowerCheckOutrange, str);
    } else {
        pProcess->m_Variants.get_VData(Var_Process_PowerChekDate)->setValue(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
        pProcess->m_iLastCheckPowerWafer = 1;
    }

    if(report) {
        pPowerMeterDriver->m_sCheckPowerResult += str + "\n";
        //_SysExt_Instance.m_SysMsg.SetMsg(str);
    }

    pPowerMeterDriver->m_lastUsePowermeterTime = QDateTime::currentDateTime();
}


void CProcess_LaserPowerCali::OpenLensOutBlow(bool bOpen)
{
    CLaserPathDriver* pLaserPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
    pLaserPathDriver->OpenLensBlow(m_iLaserPathID, bOpen);
}

#if 0
void CProcess_LaserPowerCali::before_cali_PChange(int iFreq, double dWidth)
{
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    CLaserPathDriver* pLPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
    MoveCaliPos();
    //开光
    pLaserDriver->OpenLaserGate(LASER, true);
    //pLaserDriver->SetGateSource(LASER,true);
    pLpath->m_vPowerPos.clear();
    pLPathDriver->MoveBeamPos(m_iLaserPathID, dWidth);
    pLaserDriver->SetFreq(LASER, iFreq);
}

void CProcess_LaserPowerCali::cali_PChange(int iFreq, double dWidth, int iStep)
{
    UNUSED(iFreq); UNUSED(dWidth);
    CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD, CPowerMeter);
    Q_ASSERT(pPowerMeterHead);
    //    CLaserDriver* pLaserDriver=GET_CARD(LASERDRIVER,CLaserDriver);
    //    Q_ASSERT(pLaserDriver);
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    double dStep = m_Variants.get_VData(Var_Process_LaserPowerCali_Step)->toDouble();

    double dBaseAngle = 0;
    dBaseAngle = pLpath->m_Variants.get_VData(Var_LaserPath_PChangeAngle_ID)
        ->toDouble();
    if(DEQUAL0(dStep)) {
        MQT_THROW_STR(QObject::trUtf8("Cali laser power err. Step equal 0"));
    }
    double dAngleOffset = -45 + dStep * (iStep - 1);
    double dAngle = dBaseAngle + dAngleOffset;
    pMotorDriver->absmove(MOTORG1_PCHANGE, dAngle);
    WaitMeasStable();
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();

    PowerPosParam PosParam;
    PosParam.dIndex = dAngleOffset;
    PosParam.dPower = dPower;

    pLpath->m_vPowerPos.push_back(PosParam);

    m_iCurFreq = iFreq;
    m_dCurWidth = dWidth;
}

void CProcess_LaserPowerCali::after_cali_PChange(int iFreq, double dWidth)
{
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    //pLaserDriver->SetGateSource(LASER,false);
    pLaserDriver->OpenLaserGate(LASER, false);
    int isize = pLpath->m_vPowerPos.size();
    if(!isize) {
        MQT_THROW_STR(QObject::trUtf8("have not any cali data"));
    }
    double dBaseAngle = 0;
    dBaseAngle = pLpath->m_Variants.get_VData(Var_LaserPath_PChangeAngle_ID)
        ->toDouble();
    double dmax = pLpath->m_vPowerPos[0].dPower;
    int imax = 0;
    for(int i = 0; i < isize; i++) {
        if(pLpath->m_vPowerPos[i].dPower > dmax) {
            imax = i;
            dmax = pLpath->m_vPowerPos[i].dPower;
        }
    }
    double dangle = dBaseAngle + pLpath->m_vPowerPos[imax].dIndex;
    pLpath->m_Variants.get_VData(Var_LaserPath_PChangeAngle_ID)->setValue(dangle);

    m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("%1KHz %2mm Width PChange cali. "
                                              "finish")
                              .arg(iFreq).arg(dWidth));
}
#endif

void CProcess_LaserPowerCali::before_cali_MaxPower(int iFreq, double dWidth)
{
    Q_UNUSED(dWidth);
    m_curMaxPower = 0;
    m_lastCaliPower = 0;
    m_bCaliMaxPowerUp = true;
    m_findMaxPower = false;

    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);

    MoveCaliPos();
    //开光
    pLaserDriver->OpenLaserGate(LASER, true);
    //pLaserDriver->SetGateSource(LASER,true);
	//关闭吹风
	OpenLensOutBlow(false);

    pLpath->m_vPowerPos.clear();
    CLaserPathDriver* pLPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
    pLPathDriver->MoveBeamWidthPos(m_iLaserPathID, dWidth);

    if(RTN_FAILED1 == pLaserDriver->SetFreq(LASER, iFreq)) {
        MQT_THROW_CODESTR(ALARM_LASER_COMMUNICATION, QObject::tr("Before cali. max power set laser freq parameter failed."));
    }
}

void CProcess_LaserPowerCali::cali_MaxPower(int iFreq, double dWidth, int iStep)
{
    double dStep = m_Variants.get_VData(Var_Process_LaserPowerCali_Step)->toDouble();

    //if(m_findMaxPower) return;
    //if(iStep>1 && iStep%int(1000/(dStep-0.001)/1000)!=0 && !m_bCaliMaxPowerUp) return; //如果在下降过程中，则以1度的速度，快速下降
    UNUSED(iFreq); UNUSED(dWidth);
    CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD, CPowerMeter);
    Q_ASSERT(pPowerMeterHead);
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);
    //步进

    double dBaseAngle = 0;
    dBaseAngle = pLpath->m_Variants.get_VData(Var_LaserPath_PowerMaxAngle_ID)
        ->toDouble();
    if(DEQUAL0(dStep)) {
        MQT_THROW_STR(QObject::trUtf8("Cali laser power err. Step equal 0"));
    }

#ifndef __USE_MOTOR_PATH__
    //TODO:衰减器运动，直到检测到最大值
    double dAngle = 0;
    double dAngleOffset = -45 + dStep * (iStep - 1);
    dAngle = dBaseAngle + dAngleOffset;
    WaitMeasStable();

    CPowerMeterDriver* pPowerMeterDriver = GET_CHDIRECT(POWERMETERDRIVER, CPowerMeterDriver);
    Q_ASSERT(pPowerMeterHead);
    pPowerMeterDriver->freshresult(POWERMETERHEAD);
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();


    PowerParamIndex PosParam;
    PosParam.dIndex = dAngleOffset;
    PosParam.dPower = dPower;

    pLpath->m_vPowerPos.push_back(PosParam);
#else
    double dAngle = 0;
    double dAngleOffset = -45 + dStep * (iStep - 1);
    dAngle = dBaseAngle + dAngleOffset;
    pMotorDriver->absmove(MOTORG2_POWER, dAngle);

    WaitMeasStable();
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();


    PowerParamIndex PosParam;
    PosParam.dIndex = dAngleOffset;
    PosParam.dPower = dPower;

    pLpath->m_vPowerPos.push_back(PosParam);
#endif

    m_iCurFreq = iFreq;
    m_dCurWidth = dWidth;

    //上升过程中突然下降，即找到了
    /*double dthres= m_Variants.get_VData(Var_Process_LaserPowerCali_PowerCheck_Thres)->toDouble();
    if(m_lastCaliPower<0){
        m_lastCaliPower = dPower;
        m_curMaxPower = dPower;
        return;
    }

    if(m_lastCaliPower - dPower > dthres){
        m_bCaliMaxPowerUp = false;
        m_lastCaliPower = dPower;

        if(dPower+0.01<m_curMaxPower
            && m_bCaliMaxPowerUp)
        {
            m_findMaxPower = true;
        }

    }else if(m_lastCaliPower - dPower < -dthres){
        m_lastCaliPower = dPower;
        m_bCaliMaxPowerUp = true;
    }

    if(m_curMaxPower < m_lastCaliPower*100){
        m_curMaxPower = m_lastCaliPower*100;
    }*/
}

void CProcess_LaserPowerCali::after_cali_MaxPower(int iFreq, double dWidth)
{
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);

    double dBaseAngle = 0;
    dBaseAngle = pLpath->m_Variants.get_VData(Var_LaserPath_PowerMaxAngle_ID)
        ->toDouble();

    pLaserDriver->OpenLaserGate(LASER, false);

    int isize = pLpath->m_vPowerPos.size();
    if(!isize) {
        MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("have not any cali data"));
    }
    double dmax = pLpath->m_vPowerPos[0].dPower;
    int imax = 0;
    for(int i = 0; i < isize; i++) {
        if(pLpath->m_vPowerPos[i].dPower > dmax) {
            imax = i;
            dmax = pLpath->m_vPowerPos[i].dPower;
        }
    }
    double dangle = dBaseAngle + pLpath->m_vPowerPos[imax].dIndex;
    pLpath->m_Variants.get_VData(Var_LaserPath_PowerMaxAngle_ID)->setValue(dangle);

    _SysExt_Instance.m_SysMsg.SetMsg(QObject::trUtf8("%1KHz %2mm Width MaxPower angle cali. "
                                              "finish")
                              .arg(iFreq).arg(dWidth));
}

//测量最大功率
void CProcess_LaserPowerCali::check_full_power(int iFreq, double dWidth)
{
    CPreciseTime tm;
    tm.StartTime();

    CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD, CPowerMeter);
    Q_ASSERT(pPowerMeterHead);
    CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
    Q_ASSERT(pLaserDriver);
    CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
    Q_ASSERT(pMotorDriver);
    CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
    Q_ASSERT(pLpath);

    pLaserDriver->OpenLaserGate(LASER, FALSE);
    //功率计归0

    MoveCaliPos();
    //开光
    pLaserDriver->OpenLaserGate(LASER, TRUE);
	//关闭吹风
	OpenLensOutBlow(false);

    WaitMeasStable();
    pLaserDriver->OpenLaserGate(LASER, FALSE);
    //pLaserDriver->SetGateSource(LASER,FALSE);
    MSleep(m_Variants.get_VData(Var_Process_LaserPowerCali_MeasTime)
           ->toInt());
    double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
        ->toDouble();

    CLaser* pLaser = GET_CHDIRECT(LASER, CLaser);
    tm.StopTime();
    QString str;
    str = QObject::trUtf8("TM:%1,Freq:%2,Max Power:%4")
        .arg(tm.FormatTime()).arg(iFreq).arg(dPower);
    _SysExt_Instance.EvtLog(QObject::trUtf8("CHKFULL"), str);
    _SysExt_Instance.m_SysMsg.SetMsg(str);
}

void CProcess_LaserPowerCali::do_msg(int iID, QVariantList& vlInput, V_MsgOutput* pvlOutput)
{
    int32_t isize = vlInput.size();
    switch(iID) {
        case MOVECALIPOS:
            if(isize >= 0) {
                MoveCaliPos();
            }
            break;
        case CALIPOWER_BEFORE:
            if(isize >= 2) {
                before_cali_power(vlInput[0].toInt(),
                                  vlInput[1].toInt(),
                                  vlInput[2].toDouble());
            }
            break;
        case CALIPOWER:
            if(isize >= 3) {
                cali_power(vlInput[0].toInt(),
                           vlInput[1].toInt(),
                           vlInput[2].toDouble(), vlInput[3].toInt());
                m_iCurMsgID = CALIPOWER;
            }
            break;
        case CALIPOWER_AFTER:
            if(isize >= 2) {
                after_cali_power(vlInput[0].toInt(),
                                 vlInput[1].toInt(),
                                 vlInput[2].toDouble());
            }
            break;
        case CHECKPOWER:
            if(isize >= 4) {
                check_power_diff(vlInput[0].toInt(), vlInput[1].toInt(), vlInput[2].toDouble(),
                                 vlInput[3].toDouble(), vlInput[4].toBool());
            }
            break;
        case CHECKFULLPOWER:
            if(isize >= 2) {
                check_full_power(vlInput[0].toInt(), vlInput[1].toDouble());
            }
            break;
        case CALIPCHANGEANGLE_BEFORE:
            if(isize >= 2) {
#if 0
                before_cali_PChange(vlInput[0].toInt(),
                                    vlInput[1].toDouble());
#else
                MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("Not support operate"));
#endif
            }
            break;
        case CALIPCHANGEANGLE:
            if(isize >= 3) {
#if 0
                cali_PChange(vlInput[0].toInt(),
                             vlInput[1].toDouble(), vlInput[2].toInt());
                m_iCurMsgID = CALIPCHANGEANGLE;

#else
                MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("Not support operate"));
#endif
            }
            break;
        case CALIPCHANGEANGLE_AFTER:

            if(isize >= 2) {
#if 0
                after_cali_PChange(vlInput[0].toInt(),
                                   vlInput[1].toDouble());
#else
                MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("Not support operate"));
#endif
            }
            break;
        case CALIMAXPOWERANGLE_BEFORE:
            if(isize >= 2) {

                before_cali_MaxPower(vlInput[0].toInt(),
                                     vlInput[1].toDouble());
            }
            break;
        case CALIMAXPOWERANGLE:
            if(isize >= 3) {
                cali_MaxPower(vlInput[0].toInt(),
                              vlInput[1].toDouble(), vlInput[2].toInt());
                m_iCurMsgID = CALIMAXPOWERANGLE;
            }
            break;
        case CALIMAXPOWERANGLE_AFTER:
            if(isize >= 2) {
                after_cali_MaxPower(vlInput[0].toInt(),
                                    vlInput[1].toDouble());
            }
            break;
		case OPEN_LENS_BLOW:
			OpenLensOutBlow(vlInput[0].toBool());
			break;
#ifdef __USE_LASER_BAEM__POWER__
		case CALIPOWER_BEAM_BEFORE:
			if (isize >= 2)
			{
				before_cali_power_rate(vlInput[0].toInt(),
					vlInput[1].toInt(),
					vlInput[2].toDouble(), vlInput[3].toDouble());
			}
			break;
		case CALIPOWER_BEAM:
			if (isize >= 3)
			{
				calibeam_power_rate(vlInput[0].toInt(),
					vlInput[1].toInt(),
					vlInput[2].toDouble(), vlInput[3].toInt(), vlInput[3].toDouble());
				m_iCurMsgID = CALIPOWER;
			}
			break;
		case CALIPOWER_BEAM_AFTER:
			if (isize >= 2)
			{
				after_cali_power_rate(vlInput[0].toInt(),
					vlInput[1].toInt(),
					vlInput[2].toDouble(), vlInput[3].toDouble());
			}
			break;
#endif
    }
    CMProcess::do_msg(iID, vlInput, pvlOutput);
}
#ifdef __USE_LASER_BAEM__POWER__
void CProcess_LaserPowerCali::before_cali_power_rate(int iFreq, int iEpulse, double dWidth, double dAngle)
{
	Q_UNUSED(dWidth);
	CLaserDriver_Base* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver_Base);
	Q_ASSERT(pLaserDriver);


	CLaserPathDriver* pLPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
	Q_ASSERT(pLPathDriver);

	MoveCaliPos();
	//开光
	pLaserDriver->OpenLaserGate(LASER, false);
	pLPathDriver->OpenShutter(m_iLaserPathID, true);

	CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
	Q_ASSERT(pLpath);
    pLpath->m_mBeamPowerRateCali.clear();
 
	CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pMotorDriver);
	pMotorDriver->absmove(MOTORG2_POWER, dAngle);

	pLaserDriver->SetFreq(LASER, iFreq);
	pLaserDriver->SetEpulseFreq(LASER, iEpulse * 1000);
}
void CProcess_LaserPowerCali::calibeam_power_rate(int iFreq, int iEpulse, double dBeamWidth, int iStep, double dAngle)
{
	//开光
	CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
	pLaserDriver->OpenLaserGate(LASER, true);

	//关闭吹风
	OpenLensOutBlow(false);

	CPowerMeter* pPowerMeterHead = GET_CHDIRECT(POWERMETERHEAD, CPowerMeter);
	Q_ASSERT(pPowerMeterHead);
	CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pMotorDriver);
	CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
	Q_ASSERT(pLpath);

	//TODO:功率测量
    CLaserPathDriver* pLPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
    Q_ASSERT(pLPathDriver);
    pLPathDriver->MoveBeamPosCali(m_iLaserPathID, dBeamWidth);

	if (!_SysExt_Instance.IsSimulator())
	{
		WaitMeasStable();
	}

	double dPower = pPowerMeterHead->m_Variants.get_VData(Var_PowerMeter_MeasResult_ID)
		->toDouble();

    if (iStep == 0)
    {
        if (dPower < 0.1)
        {
            MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Power is too low"));
        }

        pLpath->m_iBeamPowerRateFreq = iFreq;
        pLpath->m_iBeamPowerRateEpulse = iEpulse;
        pLpath->m_iBeamPowerRateMaxPower = dPower;
    }
    else
    {
        DBeamPowerRate powerRate;
        powerRate.dPos = dBeamWidth;
        powerRate.dBeamWidth = dBeamWidth;
        powerRate.dCurPower = dPower;
        powerRate.dPowerRate = dPower / pLpath->m_iBeamPowerRateMaxPower;
        pLpath->m_mBeamPowerRateCali[dBeamWidth*1000] = powerRate;
    }
	
	pLaserDriver->OpenLaserGate(LASER, false);
}

void CProcess_LaserPowerCali::after_cali_power_rate(int iFreq, int iEpulse, double dWidth, double dAngle)
{
	CLaserDriver* pLaserDriver = GET_CARD(LASER_DRIVER, CLaserDriver);
	Q_ASSERT(pLaserDriver);
	pLaserDriver->OpenLaserGate(LASER, false);
	CLaserPathDriver* pPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
	Q_ASSERT(pPathDriver);
	//关闭光闸
	CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	pPathDriver->OpenShutter(m_iLaserPathID, false);

	CLaserPath* pLpath = GET_CHDIRECT(m_iLaserPathID, CLaserPath);
	Q_ASSERT(pLpath);
    std::swap(pLpath->m_mBeamPowerRate, pLpath->m_mBeamPowerRateCali);

    _SysExt_Instance.m_SysMsg.SetMsg(QObject::trUtf8("%1KHz power rate cali. "
                                     "finish")
                                     .arg(iEpulse));
}
#endif
