#include "ballvalve.h"
#include "Modbus.h"
#include <QTimer>
#include <QElapsedTimer>

#include "ComStatistics.h"

static ComStatistics g_BallValve_Statistics("BallValve");

BallValve::BallValve(SerialUi* pSerial)
{
    m_pSerial = pSerial;
}

bool BallValve::check_crc(QByteArray data)
{
    int size = data.size();
    unsigned short crc1 =0, crc2= 0;

    unsigned char crc_h = data.at(size-2);
    unsigned char crc_l = data.at(size-1);

    crc1 = (crc_h <<8) |crc_l;
    crc2 = CRC16_MODBUS((unsigned char *)data.data(),data.size()-2);

     if(crc1 == crc2){
        return true;
     }else{
         return false;
     }


}

//设置阀门的开度值 A (0--1000) 表示：(A/10)%
bool BallValve::SetPosition(unsigned short value)
{
    QByteArray tx_buf;
    char zero = 0x00;
    QElapsedTimer  timer;
    timer.start();

    tx_buf.append(BALLVALVE_BUS_ADDRESS);
    tx_buf.append(0x06);
    tx_buf.append(zero);
    tx_buf.append(0x02);

    char c_high = (value>>8)&0xff;
    char c_low = (value)&0xff;

    tx_buf.append(c_high);
    tx_buf.append(c_low);

    unsigned short crc;

    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());

    //tx_buf.append(crc&0xff);
    tx_buf.append((crc>>8)&0xff);
    tx_buf.append(crc&0xff);

    g_BallValve_Statistics.ReQuestCount_increase();
    QByteArray rx_buf;
    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
    if(rx_buf.size() > 0){
        if(check_crc(rx_buf)){
            g_BallValve_Statistics.Update_Recvtime(timer.elapsed());
            return true;
        }else{
            qDebug("SetPosition <<< check crc failed");
            g_BallValve_Statistics.CrcErrorCount_increase();
            return false;
        }
    }else{
        qDebug("SetPosition <<< no data received use time: %lld ms", timer.elapsed());
        g_BallValve_Statistics.TimeoutCount_increase();
        return false;
    }

}

bool BallValve::GetWorkStatus(unsigned char& status)
{
    QByteArray tx_buf;
    QElapsedTimer  timer;
    timer.start();

    char zero = 0x00;

    tx_buf.append(BALLVALVE_BUS_ADDRESS);
    tx_buf.append(0x04);

    tx_buf.append(zero);
    tx_buf.append(0x01);

    tx_buf.append(zero);
    tx_buf.append(0x01);

    unsigned short crc;

    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());

    //tx_buf.append(crc&0xff);
    tx_buf.append((crc>>8)&0xff);
    tx_buf.append(crc&0xff);

    g_BallValve_Statistics.ReQuestCount_increase();

    QByteArray rx_buf;
    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
    if(rx_buf.size() > 0){
        if(check_crc(rx_buf)){

            status = rx_buf.at(4);
            g_BallValve_Statistics.Update_Recvtime(timer.elapsed());
            return true;
        }else{
            qDebug("GetWorkStatus <<< check crc failed");
            g_BallValve_Statistics.CrcErrorCount_increase();
            return false;
        }
    }else{
        qDebug("GetWorkStatus <<< no data received ");
        g_BallValve_Statistics.TimeoutCount_increase();
        return false;
    }
}

bool BallValve::GetPosition(unsigned short& value)
{
    QByteArray tx_buf;
    QElapsedTimer  timer;
    timer.start();

    char zero = 0x00;

    tx_buf.append(BALLVALVE_BUS_ADDRESS);
    tx_buf.append(0x04);

    tx_buf.append(zero);
    tx_buf.append(0x14);

    tx_buf.append(zero);
    tx_buf.append(0x01);

    unsigned short crc;

    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());

    //tx_buf.append(crc&0xff);
    tx_buf.append((crc>>8)&0xff);
    tx_buf.append(crc&0xff);

    g_BallValve_Statistics.ReQuestCount_increase();

    QByteArray rx_buf;
    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
    if(rx_buf.size() > 0){
        if(check_crc(rx_buf)){

            unsigned char dath = rx_buf.at(3);
            unsigned char datl = rx_buf.at(4);
            value = (dath << 8)|datl;
            g_BallValve_Statistics.Update_Recvtime(timer.elapsed());
            return true;
        }else{
            qDebug("GetPosition <<< check crc failed");
            g_BallValve_Statistics.CrcErrorCount_increase();
            return false;
        }
    }else{
        qDebug("GetPosition <<< no data received ");
        g_BallValve_Statistics.TimeoutCount_increase();
        return false;
    }
}


bool BallValve::GetSP(unsigned char& status, unsigned short& value)
{
    QByteArray tx_buf;
    QElapsedTimer  timer;
    timer.start();

    char zero = 0x00;

    tx_buf.append(BALLVALVE_BUS_ADDRESS);
    tx_buf.append(0x04);

    tx_buf.append(zero);
    tx_buf.append(0x52);

    tx_buf.append(zero);
    tx_buf.append(0x02);

    unsigned short crc;

    crc=CRC16_MODBUS((unsigned char *)tx_buf.data(),tx_buf.size());

    //tx_buf.append(crc&0xff);
    tx_buf.append((crc>>8)&0xff);
    tx_buf.append(crc&0xff);

    g_BallValve_Statistics.ReQuestCount_increase();

    QByteArray rx_buf;
    rx_buf = m_pSerial->serialWriteReponse(tx_buf);
    if(rx_buf.size() > 0){
        if(check_crc(rx_buf)){

            status = rx_buf.at(4);
            unsigned char dath = rx_buf.at(5);
            unsigned char datl = rx_buf.at(6);
            value = (dath << 8)|datl;

            g_BallValve_Statistics.Update_Recvtime(timer.elapsed());

            return true;
        }else{
            qDebug("GetSP <<< check crc failed");
            g_BallValve_Statistics.CrcErrorCount_increase();
            return false;
        }
    }else{
        qDebug("GetSP <<< no data received ");
        g_BallValve_Statistics.TimeoutCount_increase();
        return false;
    }
}

void BallValve::Dump_Statistics(QString file_path)
{
    g_BallValve_Statistics.Save2File(file_path);
}
