#include "TestService.h"
#include "pid.h"
#include "valve.h"
#include "ballvalve.h"
#include "PressureSensor.h"
#include "Calibrationpara.h"
#include<QDateTime>
#include<QTime>
#include<QEventLoop>
#include<QMessageBox>
#include<cmath>
#include <QSignalSpy>

#include <QDebug>

#include <QFile>
#include <QDir>




TestService::TestService(QThread *parent)
    :QThread(parent)
    ,m_SerialUi3(nullptr)
    ,m_SerialUi4(nullptr)
    ,m_pTimer_1(nullptr)
    ,m_pTimer_2(nullptr)
    ,m_compartmentid(0)
{

    m_bRunning=false;
    m_bRealEnd = true;

    for(int i=0; i<MAX_COMPARTMENT_NUM; i++ ){
        m_tank.m_comparts[i].m_id = i;
    }

}

TestService::~TestService()
{
    qDebug()<<"TestService destory";
    m_SerialUi3.closeConnect();
    m_SerialUi4.closeConnect();
}

void TestService::init()
{
    m_pTimer_1 = new QTimer(this);
     connect(m_pTimer_1, SIGNAL(timeout()), this, SLOT(OnTimer1()));

     //m_pTimer_2 = new QTimer(this);
     //connect(m_pTimer_2, SIGNAL(timeout()), this, SLOT(OnTimer2()));


      if(!m_SerialUi3.serialConnect("COM3", "9600", "8", "0", "1")){
          QString str = "打开串口COM3失败";
          emit onNotice(str);
      }

#if 1
      if(!m_SerialUi4.serialConnect("COM4", "9600", "8", "2", "1")){
          QString str = "打开串口COM4失败";
          emit onNotice(str);
      }
#endif

      connect(&m_report, SIGNAL(onProgress(QString)), this, SLOT(receive_reportprogress(QString)));

}

bool TestService::setTankinfo(const QVariantList& list)
{
    QString  standard_name;
    QString  licenseplate_str;
    QString  companyname_str;
    int compartment_num = 0;
    int total_volume = 0;
    int volume[MAX_COMPARTMENT_NUM] ={0};

    for(int i=0; i<list.count(); i++){
        QString item_string = list[i].toString();
        if(0 == i){
            standard_name = item_string;
        }else if(1 == i){
           licenseplate_str = item_string;
        }else if(2 == i){
            companyname_str = item_string;
        }else if(3 == i){
            total_volume = item_string.toInt();
        }else if(4 == i){
            compartment_num = item_string.toInt();
        }else{
            if(i< (MAX_COMPARTMENT_NUM+5))
                volume[i-5] = item_string.toInt();
        }
    }

     //check invalid
    bool ret_bool = true;

    if( compartment_num > 0 && compartment_num <= MAX_COMPARTMENT_NUM){
        int volume_sum =0;
        for(int i=0; i<compartment_num; i++){
            volume_sum += volume[i];
        }
        if(total_volume != volume_sum){
            ret_bool = false;
        }
    }else{
        ret_bool = false;
    }

    if(true == ret_bool){
        //m_standardname = standard_name;
        qDebug("setTankinfo: standard_name:[%s]", standard_name.toStdString().c_str());
        m_tank.licenseplate_str = licenseplate_str;
        qDebug("setTankinfo: licenseplate:[%s]", licenseplate_str.toStdString().c_str());
        m_tank.companyname_str = companyname_str;
        qDebug("setTankinfo: companyname:[%s]", companyname_str.toStdString().c_str());
        m_tank.total_volume = total_volume;
        qDebug("setTankinfo: total_volume:[%d]", total_volume);
        m_tank.compartment_num = compartment_num;
        qDebug("setTankinfo: compartment_num:[%d]", compartment_num);

        //Standard standard;
        if(g_StandardManager->getStandard(standard_name, m_standard)){

            for(int i=0; i<compartment_num; i++){
                m_tank.m_comparts[i].m_volume = volume[i];
                qDebug("setTankinfo: volume [%d]:[%d]", i, volume[i]);
                for(int j=0; j<m_standard.item_count; j++){
                    if(volume[i] >= m_standard.item[j].oilcompartment_volume){
                        m_tank.m_comparts[i].m_standarditem = m_standard.item[j];
                        qDebug("setTankinfo: compart [%d]: volume[%d]", i, m_standard.item[j].oilcompartment_volume);
                        qDebug("setTankinfo: compart [%d]: sys[%f]", i, m_standard.item[j].system_threshold);
                        qDebug("setTankinfo: compart [%d]: valve[%f]", i, m_standard.item[j].valve_threshold);
                        break;
                    }
                }
#if 0
                ParaItem pid_para;
                g_CalibrationPara->get_pidPara(volume[i], pid_para);
                qDebug("setTankinfo: pid max_volume:[%d]", pid_para.max_volume);
                qDebug("setTankinfo: pid keep_time:[%d]", pid_para.keep_time);

                qDebug("setTankinfo: pid outermax:[%f]", pid_para.outermax);
                qDebug("setTankinfo: pid outermin:[%f]", pid_para.outermin);
                qDebug("setTankinfo: pid outerkp:[%f]", pid_para.outerkp);
                qDebug("setTankinfo: pid outerki:[%f]", pid_para.outerki);
                qDebug("setTankinfo: pid outerkd:[%f]", pid_para.outerkd);

                qDebug("setTankinfo: pid innermax:[%f]", pid_para.innermax);
                qDebug("setTankinfo: pid innermin:[%f]", pid_para.innermin);
                qDebug("setTankinfo: pid innerkp:[%f]", pid_para.innerkp);
#endif

            }

        }else{
            QString str = "所选标准不存在！";
            emit onNotice(str);
            ret_bool = false;
        }

    }

    return ret_bool;

}


bool TestService::tstart(int compartmentid, int direction)
{
    if(m_bRunning){
        QString str = "当前有任务正在进行中...";
        emit onNotice(str);
        return false;
    }

    if(false == m_bRealEnd){
        QString str = "当前有任务还未完全结束...";
        emit onNotice(str);
        return false;
    }

    m_compartmentid = compartmentid-1;

    if(0 == direction)
        m_direction = Test_Direction_Positive;
    else
        m_direction = Test_Direction_Negative;

    m_stage = Test_Stage_SysTest;
    m_step = Test_Step_Start;

    m_pressuremutex.lock();
    m_pressurelist.clear(); //用来计算平均压力
    m_pressuremutex.unlock();

    QMessageBox::StandardButton result = QMessageBox::information(NULL, "提示：", "请对油气回收系统相关部件进行检查", QMessageBox::Ok|QMessageBox::Abort, QMessageBox::Ok);

    switch (result)
        {
        case QMessageBox::Ok:
            qDebug()<<"Ok";
            m_pTimer_1->start(1*500);  // 500 ms
            m_bRunning = true;
            start();
            break;
        case QMessageBox::Abort:
            qDebug()<<"Abort";
             return false;
            break;
        default:
        qDebug()<<"default";
              return false;
            break;
        }

    return true;

}

bool TestService::tselfstart(int compartmentid, int direction)
{
    if(m_bRunning){
        QString str = "当前有任务正在进行中...";
        emit onNotice(str);
        return false;
    }

    if(false == m_bRealEnd){
        QString str = "当前有任务还未完全结束...";
        emit onNotice(str);
        return false;
    }

    m_compartmentid = compartmentid-1;

    if(0 == direction)
        m_direction = Test_Direction_Positive;
    else
        m_direction = Test_Direction_Negative;

    m_stage = Test_Stage_SysTest;
    m_step = Test_Step_Start;

    m_pressuremutex.lock();
    m_pressurelist.clear(); //用来计算平均压力
    m_pressuremutex.unlock();

    QMessageBox::StandardButton result = QMessageBox::question(NULL, "提示：", "系统即将自检，请确认所有部件都己接好", QMessageBox::Ok|QMessageBox::Abort, QMessageBox::Ok);

    switch (result)
    {
    case QMessageBox::Ok:
        qDebug()<<"Ok";
        m_pTimer_1->start(1*500);  // 1s
        m_bRunning = true;
        start();
        break;
    case QMessageBox::Abort:
        qDebug()<<"Abort";
        return false;
        break;
    default:
        qDebug()<<"default";
          return false;
        break;
    }

    return true;

}

bool TestService::tstop(int compartmentid)
{
    if(m_compartmentid != compartmentid-1){
        return false;
    }

    if(m_pTimer_1->isActive())
        m_pTimer_1->stop();

    //if(m_pTimer_2->isActive())
     //   m_pTimer_2->stop();
    if(m_bRunning){
        //stop();
        m_bRunning = false;
    }

     return true;
}
bool TestService::reportpic_Ready(int compartmentid)
{
    Compartment& com = m_tank.get_compartment(compartmentid-1);
    com.m_testfinished = true;
    return true;
}

bool TestService::check_alltest_ok(int with_tips)
{
    bool ret_flag = true;
    for(int i=0; i< m_tank.compartment_num; i++){
        Compartment& com = m_tank.get_compartment(i);
        if(com.m_testfinished == false ){
            ret_flag = false;
            break;
        }
    }

    if((false == ret_flag) && (1 == with_tips)){
        QMessageBox::StandardButton result = QMessageBox::question(NULL, "提示：", "有油仓还未进行检测，是否强制生成报告？", QMessageBox::Yes|QMessageBox::No, QMessageBox::No);

        switch (result)
            {
            case QMessageBox::Yes:
                ret_flag = true;
                break;
            case QMessageBox::No:
                break;
            default:
                break;
            }

    }

    return ret_flag;

}

void TestService::receive_reportprogress(QString qstr)
{
    qDebug() << "TestService::receive_reportprogress ";
    qDebug() << qstr;
    emit onGenreportProgress(qstr);
}

bool TestService::genReport(QString word_path, QString pic_dir)
{
    bool ret = false;

    if(word_path.contains(".doc") || word_path.contains(".pdf") ){
        m_report.makeReport(m_tank, word_path, pic_dir);
    }else{
        QString str = "word_path invalid!";
        qDebug() << str;
    }

    return ret;
}

bool TestService::genReport_Self(QString word_path, QString pic_dir)
{
    bool ret = false;

    if(word_path.contains(".doc") || word_path.contains(".pdf") ){
        m_report.makeReport_Self(m_devinfo, word_path, pic_dir);
    }else{
        QString str = "word_path invalid!";
        qDebug() << str;
    }

    return ret;
}

bool TestService::genReport_Self2(const QString& jsonStr, QString word_path, QString pic_dir)
{
    bool ret = false;

    if(word_path.contains(".doc") || word_path.contains(".pdf") ){

        qDebug() << "genReport_Self2 jsonStr:" << jsonStr;
        m_devinfo2.update_testinfo(jsonStr);
        m_report.makeReport_Self(m_devinfo2, word_path, pic_dir);

    }else{
        QString str = "word_path invalid!";
        qDebug() << str;
    }

    return ret;
}

QJsonObject TestService::get_vrs_items()
{
    return m_tank.get_vrs_items();
}

QJsonObject TestService::get_bls_items()
{
    return m_tank.get_bls_items();
}

bool TestService::set_item_result(const QString& jsonStr )
{
    return m_tank.set_item_result(jsonStr);
}

bool TestService::set_leakage_value(const QString& jsonStr)
{
    return m_tank.set_leakage_value(jsonStr);
}

QJsonObject TestService::get_selftest_info()
{
    QJsonObject rootObj;

    rootObj.insert("target", m_devinfo.m_testinfo.m_target);
    rootObj.insert("interval", m_devinfo.m_testinfo.m_interval);
    rootObj.insert("threshold", m_devinfo.m_testinfo.m_threshold);
    rootObj.insert("begin", m_devinfo.m_testinfo.m_begin);
    rootObj.insert("end", m_devinfo.m_testinfo.m_end);
    rootObj.insert("delta", m_devinfo.m_testinfo.m_delta);
    rootObj.insert("passed", m_devinfo.m_testinfo.m_passed);

    return rootObj;
}


void TestService::push_pressurelist(double pressure)
{
    m_pressuremutex.lock();

    if(m_pressurelist.size() == AVERAGE_PRESSURE_COUNT){
        m_pressurelist.removeAt(0);
    }
    m_pressurelist.append(pressure);
    m_pressuremutex.unlock();
}
void TestService::clear_pressurelist()
{
    m_pressuremutex.lock();
    m_pressurelist.clear(); //用来计算平均压力
    m_pressuremutex.unlock();
}

double TestService::calculate_averagepressure()
{
    double average = 0.0;

    m_pressuremutex.lock();
    int n = m_pressurelist.size();

    if(n>0){

        double sum = 0.0;
        for(int i=0; i<n; i++){
            sum += m_pressurelist.at(i);
            //qDebug("push_pressurelist 333 size[%f]", m_pressurelist.at(i));
        }
        average = sum/n;
    }

    m_pressuremutex.unlock();

    return average;
}


bool TestService::valve_open(Valve_ID id)
{
    if(Valve_ID_All == id){
        Valve v(&m_SerialUi3, ALL_VALVE);
        return v.Open();
    }else{
        Valve v(&m_SerialUi3, id);
        return v.Open();
    }

}

bool TestService::valve_close(Valve_ID id)
{
    if(Valve_ID_All == id){
        Valve v(&m_SerialUi3, ALL_VALVE);
        return v.Close();
    }else{
        Valve v(&m_SerialUi3, id);
        return v.Close();
    }
}

QString TestService::read_PressureValue()
{
    float pressure = 0.0;
    double d_pressure = 0.0;
    static int timeout_count =0;

    PressureSensor ps(&m_SerialUi4);
    if(ps.Read(pressure)){
        push_pressurelist(pressure);
        timeout_count=0;
    }else{

        pressure = calculate_averagepressure();
        qDebug("Read_PressureValue failed");
        timeout_count++;
        if(timeout_count >= AVERAGE_PRESSURE_COUNT){
            //data is to old, clear
            clear_pressurelist();
            qDebug("clear_pressurelist ");
        }

    }

    int _ipressure = pressure*1000;
    _ipressure = (_ipressure/PRESSURE_DIVISION_VALUE)*PRESSURE_DIVISION_VALUE;
    d_pressure = _ipressure/1000.0;

    QString pressure_str = QString("%1").arg(d_pressure, 4,'f',2,QLatin1Char('0'));
    return pressure_str;

}

bool TestService::pressure_zero()
{
    PressureSensor ps(&m_SerialUi4);
    return ps.Set_Zero();
}

bool TestService::ballvalve_control(QString position_str)
{
    bool ok;
    ushort position = position_str.toUShort(&ok, 10);

    BallValve ball_v(&m_SerialUi4);
    return ball_v.SetPosition(position);
}


QJsonObject TestService::ballvalve_status()
{
    unsigned char status;
    unsigned short value = 0;

    QJsonObject rootObj;
    BallValve ball_v(&m_SerialUi4);

    if(ball_v.GetSP(status, value)){
        switch(status){
        case BALLVALVE_STATUS_OPENING:
            rootObj.insert("status", "opening");
            break;
        case BALLVALVE_STATUS_CLOSING:
            rootObj.insert("status", "closing");
            break;
        case BALLVALVE_STATUS_OPENEND:
            rootObj.insert("status", "opened");
            break;
        case BALLVALVE_STATUS_CLOSEEND:
            rootObj.insert("status", "closed");
            break;
        case BALLVALVE_STATUS_BREAK:
            rootObj.insert("status", "break");
            break;
        case BALLVALVE_STATUS_FAULT:
            rootObj.insert("status", "fault");
            break;
        default:
            rootObj.insert("status", "unkown");
            break;
        }
        rootObj.insert("position", value);
    }else{
        rootObj.insert("status", "unkown");
        rootObj.insert("position", 0);
    }

    return rootObj;
}

void TestService::dump_comstatistic()
{
    QString filepath = "D:/VaporRecoverySystemTest/comstatistic.txt";
    Valve in_v(&m_SerialUi3, VALVE_INTAKE);
    in_v.Dump_Statistics(filepath);

    PressureSensor ps(&m_SerialUi4);
    ps.Dump_Statistics(filepath);

    BallValve bv(&m_SerialUi4);
    bv.Dump_Statistics(filepath);

}

void TestService::OnTimer1()
{
    float pressure = 0.00;
    static int timeout_count =0;
    static int times_count = 0;

    PressureSensor ps(&m_SerialUi4);
    if(ps.Read(pressure)){
        if(m_direction == Test_Direction_Positive){
            //正压检测，不允许出现负值
            if(pressure < 0.0){
                pressure = 0.0;
            }
        }else {
            // 负压检测，不允许出现正值
            if(pressure > 0.0){
                pressure = 0.0;
            }

        }

        push_pressurelist(pressure);
        timeout_count=0;
    }else{

        qDebug("Read_PressureValue failed");
        pressure = calculate_averagepressure();
        timeout_count++;
        if(timeout_count >= AVERAGE_PRESSURE_COUNT){
            //data is to old, clear
            clear_pressurelist();
            qDebug("clear_pressurelist ");
        }
    }

    times_count++;

    if(0 == times_count%2){

        int _ipressure = 0;
        double d_pressure = 0.00;

        if(fabs(pressure) < 0.01){
            pressure = 0.0;
        }

        _ipressure = pressure*1000;
        _ipressure = (_ipressure/PRESSURE_DIVISION_VALUE)*PRESSURE_DIVISION_VALUE;
        d_pressure = _ipressure/1000.0;

        QString pressure_str = QString("%1").arg(d_pressure, 4,'f',2,QLatin1Char('0'));

        PressureItem item;
        //item.m_pressure = pressure_str;
        item.m_testDirection = m_direction;
        item.m_testStage = m_stage;
        item.m_testStep = m_step;

        QVariantMap map;
        map.clear();

        map.insert("pressure", pressure_str);
        map.insert("direction", item.m_testDirection);
        map.insert("stage", item.m_testStage);
        map.insert("step", item.m_testStep);


        //QString pressure_str = QString("%1").arg(pressure, 5,'f',3,QLatin1Char('0'));
        //m_tank.m_comparts[m_compartmentid].m_currentpressure= pressure_str.toFloat();
        emit sigPressure(m_compartmentid+1, map);

    }



}

void TestService::OnTimer2()
{
    //qDebug("OnTimer2 >>>enter ");
    //float pressure;
    //Read_pressure(pressure);

    //QThread::sleep(5);

    //emit Pressure_changed(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    //qDebug("OnTimer2 >>>leave ");
}

Ret_Value  TestService::PositivePressure_Add(const TestExpect& expect, bool bSavedata)
{
    Ret_Value ret_v = Ret_OK;
    int interval_time = 500; // ms
    int count = 0;
    int delay_count = 0;
    int exceed_times =0;

   QElapsedTimer  timer;
   timer.start();
   double prev_pressure = 0;
   double current_pressure = 0;

   double current_speed = 0;
   unsigned char bvstatus;
   unsigned short bvposition;
   unsigned short bvoffset = 150;
   int keep_times = 60;
   int stable_count = 0;  //稳压计数

   PressureSensor ps(&m_SerialUi4);
   BallValve bv(&m_SerialUi4);
   bool bv_ready = false;

   bv.SetPosition(bvoffset);

   PID* pPIDouter = NULL;
   PID* pPIDinner = NULL;
   double speed_target = 0.0;
   QList<float>  _pressurelist;


    ParaItem pid_para;
    g_CalibrationPara->get_pidPara(expect.volume, pid_para);

    pPIDouter = new PID(0.5, pid_para.outermax, pid_para.outermin, pid_para.outerkp, 0, 0);
    //pPIDouter = new PID(0.5, pid_para.outermax, pid_para.outermin, pid_para.outerkp, pid_para.outerkd, pid_para.outerki);
    pPIDinner = new PID(0.5, pid_para.innermax, pid_para.innermin, pid_para.innerkp, pid_para.innerkd, pid_para.innerki,pid_para.innermaxI, pid_para.innerIstep, pid_para.innerDstep);

    //将稳压时间转换成计数
    keep_times = pid_para.keep_time *(1000/interval_time);


    prev_pressure = calculate_averagepressure();

   Valve in_v(&m_SerialUi3, VALVE_INTAKE);
   bool bOpen_intake = false;
   bOpen_intake = in_v.Open();

   //
   QDateTime datetime = QDateTime::currentDateTime();
   QString timestr = datetime.toString("ddHHmmzzz");
   QString filepath = "D:/VaporRecoverySystemTest/";
   QFile datafile(filepath+timestr+"_PIDdata.csv");
   bool datafile_opened = false;
   if(true == bSavedata){
        datafile_opened = datafile.open(QFile::WriteOnly | QFile::Truncate);
   }


   //等待压力达到目标值附近
   while(m_bRunning){

        //等待球阀，到达指定位置 100
        if(false == bv_ready){
            if(false == bv.GetSP(bvstatus, bvposition)){
                qDebug(" PositivePressure_Add, bv.GetSP failed");
            }else{

                if(BALLVALVE_STATUS_FAULT == bvstatus){
                    ret_v = Ret_Failed;
                    break;
                }

                if((BALLVALVE_STATUS_OPENEND == bvstatus) || (BALLVALVE_STATUS_CLOSEEND == bvstatus) ){
                    int ps_offset = bvoffset;
                    int cu_position = bvposition;
                    if(abs(cu_position-ps_offset) <= 12){
                        bv_ready=true;
                    }
                }else{
                      bv.SetPosition(bvoffset);
                }
            }

            //
            if(true == bv_ready){
                pPIDinner->reset();
            }
        }else{

            current_pressure = calculate_averagepressure();
            current_speed = (current_pressure - prev_pressure)*(1000/interval_time);
            prev_pressure = current_pressure;

            //qDebug(" PositivePressure_Add, current_pressure : %f target: %f", current_pressure, expect.target);

            if(current_pressure >=  expect.target+0.01){

                count = 0;
                stable_count++;

                if(bOpen_intake){

                     qDebug(" PositivePressure_Add, in_v.Close ");

                    if(in_v.Close()){
                        bOpen_intake = false;
                        exceed_times++;
                    }
                        //bOpen_intake = false;
                }else{
                    // 过充了，压力下不来。 主要是系统自测会出现这种情况
                    if((1 == exceed_times) && (stable_count > keep_times)){
                        count = keep_times+10;
                    }

                }

                //阀门密闭性测试阶段，压力达到4.5以上就退出， 不管是上升阶段还是下降阶段
                if(m_stage == Test_Stage_ValveTest){
                   count = keep_times+10;
                }
#if 1

                if(exceed_times <= 1){
                    delay_count = 15*(1000/interval_time);
                }else if(2 == exceed_times){
                    delay_count =10*(1000/interval_time);
                }else{
                    delay_count =5*(1000/interval_time);
                }

                if(expect.volume < 200){ // 电磁阀与球阀之间的气管内有高压气体，对压力影响较大
                    if(bvposition != 0){
                        qDebug(" PositivePressure_Add, position : %d", 0);
                        if(bv.SetPosition(0))
                            bvposition = 0;
                    }
                }


#endif

            }else{

                 // stable_count 需要从第一次超出目标压力时，开始增加
                if(stable_count > 0) stable_count++;

                if(current_pressure >= expect.target && current_pressure < expect.target + 0.01){
                    count++;

                    //该区间有点窄，如果存在漏气较快的情况，进气阀关闭后，压力快速下降，很难进入该区间。就会陷入震荡

                    if(false == bOpen_intake){
                        //在进气阀关闭，压力回落过程中，两种情况触发加压过程退出
                        // 1. 压力值连续10秒都没有下降0.01Kpa, 说明压力基本稳定了
                        // 2. 计数超出稳压所需计数

                        if((count >=10*(1000/interval_time)) || (stable_count > keep_times) ){
                            count = keep_times+10;
                        }
                    }

                    // 进行阀门密闭性测试，加压过程中。 只要加压到目标压力就退出
                    if(m_stage == Test_Stage_ValveTest){
                        count = keep_times+10;
                    }


                }else{
                    count=0;

                    //解决 超出稳压时间 且压力下降过快的问题， 第一次低于目标值了也退出
                    if((delay_count == 5*(1000/interval_time)) && (stable_count > keep_times)){
                        count = keep_times+10;
                    }

                    if(delay_count > 0){
                        delay_count--;
                    }

                    if(false == bOpen_intake && 0 == delay_count){
                        bOpen_intake = in_v.Open();
                        qDebug(" PositivePressure_Add, in_v.Open 222 ");
                        pPIDinner->reset();
                        if(bv.SetPosition(bvoffset))
                            bvposition = bvoffset;
                    }

                }

                if(NULL != pPIDouter && NULL != pPIDinner && 0 == delay_count){

                    speed_target = pPIDouter->calculate(expect.target, current_pressure);

                    //qDebug(" PositivePressure_Add, pPIDinner speed_target:%f, current_speed:%f", speed_target, current_speed);
                    double inc = pPIDinner->calculate(speed_target, current_speed);

                    unsigned short  position = bvoffset +inc;

                    //qDebug(" PositivePressure_Add, position : %d", position);
                    if(bvposition != position){
                        //qDebug(" PositivePressure_Add, position : %d", position);
                        if(bv.SetPosition(position))
                            bvposition = position;
                    }


                }else{

                    if(0 == delay_count){
                        qDebug(" PositivePressure_Add, NULL = pPIDouter NULL == pPIDinner ");
                    }

                    //qDebug(" PositivePressure_Add, NULL = pPIDouter NULL == pPIDinner ");
                }



            }
        }

        //判断是否有泄露（球阀开度值打到最大， 连续20秒压力不上升，切达不到目标压力）
        if(bvposition == bvoffset+pid_para.innermax){
            _pressurelist.push_back(current_pressure);
            if(_pressurelist.size()  == 20*(1000/interval_time)){
                float first = _pressurelist.front();
                if((current_pressure - first) <= 0.2){  //20秒了， 压力上升小于0.2，判为漏气，退出
                    ret_v = Ret_Excepion;
                    break;
                }

                _pressurelist.removeFirst();

            }
        }else{
            if(true != _pressurelist.isEmpty()){
                _pressurelist.clear();
            }
        }



        if(count >= keep_times){ //about 60s
            break;
        }

        if(true == bSavedata && true == datafile_opened){

            QTextStream out(&datafile);    // 输入流

            QString str1 = QString("%1").arg(expect.target, 8,'f',6,QLatin1Char('0'));
            QString str2 = QString("%1").arg(current_pressure, 8,'f',6,QLatin1Char('0'));

            //out << QString::number(expect.target) << "," << QString::number(current_pressure) << ",";
            out << str1 << "," << str2 << ",";

            str1 = QString("%1").arg(speed_target, 8,'f',6,QLatin1Char('0'));
            str2 = QString("%1").arg(current_speed, 8,'f',6,QLatin1Char('0'));

            //out << QString::number(speed_target) << "," << QString::number(current_speed) << ",";
            out << str1 << "," << str2 << ",";
            out << QString::number(bvposition) << "\n";

        }

        QThread::msleep(interval_time);

        int remainingtime = expect.timeout*1000 - timer.elapsed();
        if(remainingtime <= 0){

            qDebug(" add_pressure timeout, Rough valve will colse");
            ret_v = Ret_Timeout;
            break;
        }

   }

   if(!m_bRunning){
       // be stoped
       ret_v = Ret_Exit;
   }

   if(NULL != pPIDouter){
        delete pPIDouter;
   }

   if(NULL != pPIDinner){
        delete pPIDinner;
   }

   in_v.Close();
   bv.SetPosition(0);

   if(true == bSavedata && true == datafile_opened){
       datafile.close();
   }

   return ret_v;

}


//将打开泄压阀，等待压力归零 （小于 0.01Kpa ）。
Ret_Value  TestService::Pressure_Relief(const TestExpect& expect)
{
    Ret_Value ret_v = Ret_OK;
    bool bOpen_ventv = false;
    Valve vent_v(&m_SerialUi3, VALVE_VENT);

    float current_pressure;
    float last_pressure = calculate_averagepressure();

    QElapsedTimer  timer;
    timer.start();
    int count = 0;
    int count2 = 0;

    //打开泄压阀
    bOpen_ventv = vent_v.Open();
    //last_pressure = calculate_averagepressure();

    //等待压力清零
    while(m_bRunning){

        if(false == bOpen_ventv){
            bOpen_ventv = vent_v.Open();
        }

        current_pressure = calculate_averagepressure();


        if(fabs(current_pressure - last_pressure) <= 0.01){
            qDebug(" Pressure_Relief 111  finished");
            count++;
        }else{
            count=0;
            last_pressure = current_pressure;
        }

        if(fabs(current_pressure) < 0.01){
            count2++;
        }else{
            count2=0;
        }

        if((count > 20) ||(count > 20)){
            //关闭泄压阀
            vent_v.Close();
             break;
        }

        QThread::msleep(1000);

        int remainingtime = expect.timeout*1000 - timer.elapsed();
        if(remainingtime < 0){
            ret_v = Ret_Timeout;
            qDebug("timeout, Pressure_Relief Timeout");
            break;
        }

    }

     if(!m_bRunning){
        ret_v = Ret_Exit;
     }

     vent_v.Close();

    return ret_v;
}

Ret_Value  TestService::Pressure_Relief()
{
    Ret_Value ret_v = Ret_OK;
    bool bOpen_ventv = false;
    Valve vent_v(&m_SerialUi3, VALVE_VENT);

    float current_pressure;

    QElapsedTimer  timer;
    timer.start();
    int count = 0;

    //打开泄压阀
    bOpen_ventv = vent_v.Open();

    //等待压力清零
    while(1){

        if(false == bOpen_ventv){
            bOpen_ventv = vent_v.Open();
        }

        if(false == m_pTimer_1->isActive())
            OnTimer1();

        current_pressure = calculate_averagepressure();

        if(current_pressure < 0.2){
            qDebug(" Pressure_Relief finished 222");
            count++;
        }else{
            count=0;
        }

        if(count > 0){
            //关闭泄压阀
            vent_v.Close();
            break;

        }

        QThread::msleep(1000);

        int remainingtime = 60*1000 - timer.elapsed();
        if(remainingtime < 0){
            ret_v = Ret_Timeout;
            qDebug("timeout, Pressure_Relief Timeout");
            break;
        }

    }

     vent_v.Close();
     qDebug(" Pressure_Relief leave");
    return ret_v;
}


Ret_Value  TestService::Pressure_Keep(int keeptime, double& start_value, double& end_value)
{
    int count = 0;

    Ret_Value ret_v = Ret_OK;

    start_value = calculate_averagepressure();

    int _ipressure = start_value*1000;
    _ipressure = (_ipressure/PRESSURE_DIVISION_VALUE)*PRESSURE_DIVISION_VALUE;
    start_value = _ipressure/1000.0;


    while((count < keeptime) && m_bRunning){
       QThread::msleep(1000);
       count++;
    }

    end_value = calculate_averagepressure();

    _ipressure = end_value*1000;
    _ipressure = (_ipressure/PRESSURE_DIVISION_VALUE)*PRESSURE_DIVISION_VALUE;
    end_value = _ipressure/1000.0;


    if(!m_bRunning){
        // be stoped
        ret_v = Ret_Exit;
    }

    return ret_v;
}

bool TestService::self_checking()
{
    //读继电器状态
    Valve  all_v(&m_SerialUi3, ALL_VALVE);
    if(false == all_v.Close()){
        return false;
    }

    //读取球阀状态
    BallValve ball_v(&m_SerialUi4);
    unsigned char status;
    unsigned short value;
    if(false == ball_v.GetSP(status, value)){
        return false;
    }
    if(status == BALLVALVE_STATUS_FAULT){
        return false;
    }

    ball_v.SetPosition(0);

    PressureSensor ps(&m_SerialUi4);
    float pressure = 0.0;
    if(false == ps.Read(pressure)){
       return false;
    }

    return true;
}

bool TestService::test_init()
{
    //bool ret_v=true;
    Valve all_v(&m_SerialUi3, ALL_VALVE);
    all_v.Close();

    BallValve ball_v(&m_SerialUi4);
    unsigned char status;
    unsigned short value;

    if(ball_v.GetSP(status, value)){
       if(value > 20){

           ball_v.SetPosition(0);
           int wait_time = (1+value/100);
           QThread::msleep(wait_time*1000);
       }
    }else{
        return false;
    }

    return true;

}

int TestService::make_messagebox(Test_Direction direction, Test_Step step, Ret_Value ret_v)
{
    int ret_btn = QMessageBox::NoButton;
    QString notice_str;

    if(Test_Direction_Positive == direction){

        switch(step){
        case Test_Step_AddPressure:
            if(Ret_Timeout == ret_v){
                notice_str = "加压超时， 是否重试？";
                ret_btn = m_msgbox.information(NULL, "提示：", notice_str, QMessageBox::Retry|QMessageBox::Abort,  QMessageBox::Retry);
            }else if(Ret_Failed == ret_v){
                notice_str = "继电器通信失败, 和序终止";
                ret_btn = m_msgbox.information(NULL, "提示：", notice_str, QMessageBox::Ok,  QMessageBox::Ok);
            }else if(Ret_Excepion == ret_v){
                notice_str = "持续性压力不上升，请检测是否有漏气或阀门未关或气源没打开";
                ret_btn = m_msgbox.information(NULL, "提示：", notice_str, QMessageBox::Ok,  QMessageBox::Ok);
            }

            break;
        default:
            break;

        }

    }else {


    }

    return ret_btn;
}



void TestService::run()
{
    qDebug("doTest >>>enter ");
    QString notice_str;
    //QElapsedTimer  q_time;
    int ret_btn = QMessageBox::NoButton;
    TestExpect texpect;
    bool bQuit = false;

    //q_time.start();
    Ret_Value ret_v = Ret_OK;

    m_bRealEnd = false;

    if(m_compartmentid >= 0){

        if(m_direction == Test_Direction_Positive){

            while(m_bRunning && (bQuit == false)){

                switch(m_step){

                case Test_Step_Start:
                    {
                        m_tank.get_compartment(m_compartmentid).clear_result();

                        if(false == self_checking()){
                          ret_btn = m_msgbox.information(NULL, "提示：", "通信故障，请终止检测", QMessageBox::Abort, QMessageBox::Abort);
                        }else{
                           test_init();
                          ret_btn = m_msgbox.information(NULL, "提示：", "请确认已经打开气源总阀", QMessageBox::Ok, QMessageBox::Ok);
                        }

                         switch (ret_btn)
                         {
                         case QMessageBox::Ok:
                             m_step = Test_Step_AddPressure;
                             break;
                         case QMessageBox::Abort:
                             bQuit = true;
                             break;
                         default:
                             break;
                         }
                    }

                    break;
                case Test_Step_AddPressure:
                    {
                        if(m_stage == Test_Stage_SysTest){
                            emit sigState(m_compartmentid+1, "回收系统检测, 加压", "");
                        }else{
                            emit sigState(m_compartmentid+1, "回收阀检测, 加压", "");
                        }

                        texpect.target = m_standard.positive_target;
                        texpect.volume = m_tank.m_comparts[m_compartmentid].m_volume;
                        texpect.timeout = m_tank.m_comparts[m_compartmentid].get_addpressure_timeout();
                        ret_v = PositivePressure_Add(texpect);
                        if(Ret_OK == ret_v){
                            if(m_stage == Test_Stage_SysTest){
                                m_step = Test_Step_KeepPressure;
                            }else if(m_stage == Test_Stage_ValveTest){

                                m_msgbox.information(NULL, "提示：", "即将泄压, 请确认已经关闭油气回收阀。", QMessageBox::Ok, QMessageBox::Ok);

                                m_step = Test_Step_reliefPressure;
                            }

                        }else if(Ret_Exit == ret_v){
                            bQuit = true;
                        }else{
                            ret_btn = make_messagebox(m_direction, m_step, ret_v);
                            switch (ret_btn)
                            {
                            case QMessageBox::Retry:
                                qDebug()<<"Retry";

                                break;
                            case QMessageBox::Abort:
                                qDebug()<<"Abort";
                                bQuit = true;
                                break;
                            case QMessageBox::Ok:
                                qDebug()<<"OK";
                                bQuit = true;
                                break;
                            default:
                                break;
                            }

                        }

                    }
                    break;

                case Test_Step_KeepPressure:
                    {
                        if(m_stage == Test_Stage_SysTest){
                            emit sigState(m_compartmentid+1, "油气回收系统检测, 保压", "");
                        }else{
                            emit sigState(m_compartmentid+1, "油气回收阀检测, 保压", "");
                        }

                        // 检测 5分钟都没超限，就是通过了
                        //float delta = 0;
                        //float threshold = 0.0;
                        //bool bPassed = true;

                        // 检测 5分钟都没超限，就是通过了
                        double delta = 0.0;
                        double start_value = 0.0;
                        double end_value = 0.0;
                        bool bPassed = true;

                        //ret_v = Pressure_Keep2(5*60, start_value, end_value);


                        if(m_stage == Test_Stage_SysTest){

                            ret_v = Pressure_Keep(m_standard.interval_time, start_value, end_value);
                            m_step = Test_Step_KeepEnd;

                            double offset = 0;
                            //修正 强制初始压力为 positive_target
                            if(start_value != m_standard.positive_target){
                                offset = m_standard.positive_target - start_value;
                                start_value = m_standard.positive_target;
                                end_value -= offset;
                            }

                            m_tank.m_comparts[m_compartmentid].m_result.sysstart_pressure = start_value;
                            m_tank.m_comparts[m_compartmentid].m_result.sysend_pressure = end_value;

                            delta = start_value - end_value;

                            m_tank.m_comparts[m_compartmentid].m_result.delta_sys_pressure = delta;

                            if(Ret_Exit == ret_v){

                                bQuit = true;
                            } else {

                                if(delta < m_tank.m_comparts[m_compartmentid].m_standarditem.system_threshold){
                                    bPassed = true;
                                    m_tank.m_comparts[m_compartmentid].m_result.pass_sys_pressure = true;
                                }else{
                                    bPassed = false;
                                    m_tank.m_comparts[m_compartmentid].m_result.pass_sys_pressure = false;
                                }

                                m_tank.m_comparts[m_compartmentid].m_result.sys_test_finished = true;

                                QString delta_str = QString("%1").arg(delta, 4,'f',2,QLatin1Char('0'));
                                emit sigSystemResult(m_compartmentid+1, delta_str, bPassed);
                                emit sigState(m_compartmentid+1, "油气回收系统检测,已完成", "");

                                ret_btn = QMessageBox::NoButton;
                                notice_str = "系统密闭性已经检测完成，是否进行阀门密闭性检测？";
                                ret_btn = m_msgbox.information(NULL, "提示：",  notice_str, QMessageBox::Yes|QMessageBox::No,  QMessageBox::Yes);
                                switch (ret_btn)
                                {
                                case QMessageBox::Yes:
                                    m_stage = Test_Stage_ValveTest;
                                    if(calculate_averagepressure() < m_standard.positive_target){
                                        m_step = Test_Step_AddPressure;
                                    }else{
                                        m_msgbox.information(NULL, "提示：", "即将泄压, 请确认已经关闭油气回收阀", QMessageBox::Ok, QMessageBox::Ok);
                                        m_step = Test_Step_reliefPressure; //如果压力还在4.5以上， 可以不调压
                                    }

                                    break;
                                case QMessageBox::No:
                                    m_step = Test_Step_End;
                                    break;
                                default:
                                    break;
                                }


                            }


                        }else{

                            ret_v = Pressure_Keep(m_standard.interval_time, start_value, end_value);
                            m_step = Test_Step_KeepEnd;

                            double offset = 0;
                            //修正 强制初始压力为 0
                            if(start_value != 0.0){
                                offset = start_value;
                                start_value = 0.0;
                                end_value -= offset;
                            }

                            m_tank.m_comparts[m_compartmentid].m_result.valvestart_pressure = start_value;
                            m_tank.m_comparts[m_compartmentid].m_result.valveend_pressure = end_value;

                            delta = end_value - start_value;
                            m_tank.m_comparts[m_compartmentid].m_result.delta_valve_pressure = delta;

                            if(Ret_Exit == ret_v){
                                bQuit = true;
                            }else {
                                if(delta <= m_tank.m_comparts[m_compartmentid].m_standarditem.valve_threshold){
                                    m_tank.m_comparts[m_compartmentid].m_result.pass_valve_pressure = true;
                                    bPassed = true;
                                }else{
                                    m_tank.m_comparts[m_compartmentid].m_result.pass_valve_pressure = false;
                                    bPassed = false;
                                }
                                m_tank.m_comparts[m_compartmentid].m_result.valve_test_finished = true;

                                QString delta_str = QString("%1").arg(delta, 4,'f',2,QLatin1Char('0'));
                                emit sigValveResult(m_compartmentid+1, delta_str, bPassed);
                                emit sigState(m_compartmentid+1, "油气回收阀检测,已完成", "");

                                m_step = Test_Step_End;
                            }

                        }

                    }
                    break;
                case Test_Step_reliefPressure:
                    {
                        if(m_stage == Test_Stage_SysTest){
                            emit sigState(m_compartmentid+1, "油气回收系统检测结束, 泄压", "");
                        }else if(m_stage == Test_Stage_ValveTest){
                            emit sigState(m_compartmentid+1, "油气回收阀检测结束, 泄压", "");
                        }

                        texpect.volume = 0;
                        texpect.target = 0.0;
                        texpect.timeout = 90;//m_tank.m_comparts[m_compartmentid].get_adjust_timeout();
                        ret_v = Pressure_Relief(texpect);
                        if(Ret_Exit == ret_v){
                            bQuit = true;
                        }else if(Ret_OK == ret_v){
                            m_step = Test_Step_KeepPressure;
                            if(m_stage == Test_Stage_ValveTest){
                                  m_step = Test_Step_KeepPressure;
                            }else{
                                m_step = Test_Step_End;
                            }

                        }else{

                            ret_btn = QMessageBox::NoButton;

                            notice_str = "泄压超时, 是否重试？";
                            ret_btn = m_msgbox.information(NULL, "提示：", notice_str, QMessageBox::Retry|QMessageBox::Abort,  QMessageBox::Retry);

                            switch (ret_btn)
                            {
                            case QMessageBox::Retry:
                                break;
                            case QMessageBox::Abort:
                                bQuit = true;
                                break;
                            default:
                                break;
                            }

                        }


                    }
                    break;
                default:
                    break;
                }


                if(Test_Step_End == m_step){
                    break;
                }

            }

            if(Test_Step_End == m_step){
                ret_btn = m_msgbox.information(NULL, "提示：", "检测结束，是否要泄压？ 此过程可能耗费很长时间", QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
            }else{

                ret_btn = QMessageBox::NoButton;
                if(true == bQuit){
                    ret_btn = m_msgbox.information(NULL, "提示：", "程序即将退出，是否要泄压？ 此过程可能耗费很长时间", QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
                }
            }

            switch (ret_btn)
            {
            case QMessageBox::Yes:

                if( m_stage == Test_Stage_ValveTest && m_step >= Test_Step_reliefPressure){
                    m_msgbox.information(NULL, "提示：", "即将对罐仓内压力进行泄放，请确认已打开油气回收阀", QMessageBox::Yes, QMessageBox::Yes);
                }
                Pressure_Relief();
                break;
            default:
                break;
            }


            if((true == m_tank.m_comparts[m_compartmentid].m_result.sys_test_finished))
                    //&& (true == m_tank.m_comparts[m_compartmentid].m_result.valve_test_finished))
            {
                m_tank.m_comparts[m_compartmentid].m_testfinished = true;
            }

            emit sigStop(m_compartmentid+1);



        }else{
            //负压测试， 暂不支持
            m_stage = Test_Stage_SysTest;
            qDebug(" negative test is not support now  ");
        }

    }else{

        //self test
        if(m_direction == Test_Direction_Positive){

             while(m_bRunning && (bQuit == false)){

                 switch(m_step){
                     case Test_Step_Start:
                         {
                            emit sigState(m_compartmentid+1, "开始", "");

                              if(false == self_checking()){
                                ret_btn = m_msgbox.information(NULL, "提示：", "通信故障，请终止程序", QMessageBox::Abort, QMessageBox::Abort);
                              }else{
                                 test_init();
                                ret_btn = m_msgbox.information(NULL, "提示：", "请确认已经打开旋拧阀", QMessageBox::Ok, QMessageBox::Ok);
                              }

                              switch (ret_btn)
                              {
                               case QMessageBox::Ok:
                                  qDebug()<<"Yes";
                                  m_step = Test_Step_AddPressure;
                                  break;
                               case QMessageBox::Abort:
                                    bQuit = true;
                                  break;
                              }
                         }

                         break;
                      case Test_Step_AddPressure:
                         {
                             emit sigState(m_compartmentid+1, "加压", "");
                             QThread::msleep(2000);

                             texpect.volume = 5;
                             texpect.target = m_devinfo.m_testinfo.m_target;
                             texpect.timeout = 5*60; //5分钟
                             ret_v = PositivePressure_Add(texpect);

                             if(Ret_Exit == ret_v){
                                bQuit = true;
                             }else if(Ret_OK == ret_v){
                                m_step = Test_Step_KeepPressure;
                             }else{

                                 ret_btn = QMessageBox::NoButton;
                                 ret_btn = make_messagebox(m_direction, m_step, ret_v);
                                 switch (ret_btn)
                                 {
                                 case QMessageBox::Retry:
                                     qDebug()<<"Retry";

                                     break;
                                 case QMessageBox::Abort:
                                     qDebug()<<"Abort";
                                     bQuit = true;
                                     break;
                                 case QMessageBox::Ok:
                                     qDebug()<<"OK";
                                     bQuit = true;
                                     break;
                                 default:
                                     break;
                                 }

                             }

                         }
                        break;
                     case Test_Step_KeepPressure:
                         {
                             emit sigState(m_compartmentid+1, "保压", "");

                             // 检测 5分钟都没超限，就是通过了
                             double delta = 0.0;
                             double start_value = 0.0;
                             double end_value = 0.0;
                             bool bPassed = true;

                             ret_v = Pressure_Keep(m_devinfo.m_testinfo.m_interval, start_value, end_value);
                             m_step = Test_Step_KeepEnd;

                             if(Ret_Exit == ret_v){
                                bQuit = true;
                             }else {

                                 m_devinfo.m_testinfo.m_begin = start_value;
                                 m_devinfo.m_testinfo.m_end = end_value;

                                 delta = start_value - end_value;

                                 if(delta <= m_devinfo.m_testinfo.m_threshold){
                                    bPassed = true;
                                 }else{
                                    bPassed = false;
                                 }

                                // m_devinfo.m_testinfo.m_delta = delta;
                                 //int i_delta = delta*1000;
                                 //i_delta = (i_delta/PRESSURE_DIVISION_VALUE)*PRESSURE_DIVISION_VALUE;
                                 m_devinfo.m_testinfo.m_delta  = delta;
                                 m_devinfo.m_testinfo.m_passed = (bPassed == true?1:0);

                                 //QString delta_str = QString("%1").arg(delta, 4,'f',2,QLatin1Char('0'));
                                 QString info_str = "初始压力：";
                                 info_str +=  QString("%1").arg(start_value, 4,'f',2,QLatin1Char('0'));
                                 info_str += ", 结束压力：";
                                 info_str += QString("%1").arg(end_value, 4,'f',2,QLatin1Char('0'));
                                 info_str += ", Deta:";
                                 info_str += QString("%1").arg(delta, 4,'f',2,QLatin1Char('0'));

                                 emit sigSelfTestResult(m_compartmentid+1, info_str, bPassed);
                                 emit sigState(m_compartmentid+1, "已完成", "");

                                 ret_btn = m_msgbox.information(NULL, "提示：", "栓测任务结束，是否要泄压？", QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);

                                 switch (ret_btn)
                                 {
                                 case QMessageBox::Yes:
                                     //qDebug()<<"Yes";
                                     m_step = Test_Step_reliefPressure;
                                     break;
                                 case QMessageBox::No:
                                     m_step = Test_Step_End;
                                     break;
                                 default:
                                     break;
                                 }

                             }


                         }
                         break;
                     case Test_Step_reliefPressure:
                          {
                             ret_v = Pressure_Relief();
                             if(Ret_Exit == ret_v){
                                bQuit = true;
                             }

                              m_step = Test_Step_End;

                          }
                         break;
                      default:
                         break;
                 }

                 if(Test_Step_End == m_step){
                    break;
                 }

             }

             if(Test_Step_End == m_step){
                 ret_btn = QMessageBox::NoButton;
             }else{

                 ret_btn = QMessageBox::NoButton;
                 if(true == bQuit){
                     ret_btn = m_msgbox.information(NULL, "提示：", "程序即将退出，是否要泄压？", QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
                 }

                 switch (ret_btn)
                 {
                 case QMessageBox::Yes:
                     Pressure_Relief();
                     break;
                 default:
                     break;
                 }

             }



        }else{ //negtive

        }

    }


    if(m_bRunning){
        m_bRunning = false;
        emit sigStop(m_compartmentid+1);
    }

    Valve all_v(&m_SerialUi3, ALL_VALVE);
    all_v.Close();

    //dump_comstatistic();
    m_bRealEnd = true;


    qDebug("doTest >>>leave ");

}




