#include "modbusrtu.h"
#include <QTimer>
#include <QEvent>
#include <QDebug>
#include "modbus-private.h"
#include <QMessageBox>
#include <QEventLoop>
ModbusRTU::ModbusRTU(QObject *parent) : QThread(parent)
{
    init();
    // start();

}

ModbusRTU::~ModbusRTU()
{
    modbus_close(m_ModbusRTUDevice);
    modbus_free(m_ModbusRTUDevice);
}

void ModbusRTU::init()
{

}

void ModbusRTU::run()
{
    qDebug() << "进入线程：" << QThread::currentThread();
    while(true)
    {
        if (closeThread)
        {
            QElapsedTimer time;
            time.start();
            QThread::msleep(300);
            uint16_t base1_45[45];
            uint16_t base57_78[22];
            uint16_t base83_106[24];
            uint16_t base47[1];
            uint16_t base49[1];
            uint16_t base51[1];
            uint16_t base53[1];
            uint16_t base55[1];
            QList<int> base_list_47_49_51_53_55;
            uint16_t sgl_vol[16];    // Buffer to store the registers
            uint16_t sgl_tempt[16];
            uint16_t fault[8];

        label:    int ret_base1_45 = modbus_read_input_registers(m_ModbusRTUDevice, 1, 45, base1_45);
            if(MODBUS_ERR == ret_base1_45)
            {
                goto label;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData_base_info1_45(sendArray, TypeSendData, base1_45);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showModbusData_base_info1_45(recvArray, TypeRecvData, base1_45);
                free(m_ModbusRTUDevice->recvMsg);
            }

            int ret_base47 = modbus_read_input_registers(m_ModbusRTUDevice, 47, 1, base47);
            int ret_base49 = modbus_read_input_registers(m_ModbusRTUDevice, 49, 1, base49);
            int ret_base51 = modbus_read_input_registers(m_ModbusRTUDevice, 51, 1, base51);
            int ret_base53 = modbus_read_input_registers(m_ModbusRTUDevice, 53, 1, base53);
            int ret_base55 = modbus_read_input_registers(m_ModbusRTUDevice, 55, 1, base55);
            if (ret_base47 == -1 | ret_base49 == -1 | ret_base51 == -1 | ret_base53 == -1 | ret_base55 == -1)
            {
                return;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData_base_info47_49_51_53_55(sendArray, TypeSendData);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray;
                recvArray.append(reinterpret_cast<char*>(&base47), sizeof(base47));
                recvArray.append(reinterpret_cast<char*>(&base49), sizeof(base49));
                recvArray.append(reinterpret_cast<char*>(&base51), sizeof(base51));
                recvArray.append(reinterpret_cast<char*>(&base53), sizeof(base53));
                recvArray.append(reinterpret_cast<char*>(&base55), sizeof(base55));

                for (int i = 0; i < recvArray.size(); i += 2) {
                    uint16_t value;
                    memcpy(&value, recvArray.data() + i, 2);
                    base_list_47_49_51_53_55.append(value);
                }

                emit sig_showModbusData_base_info_list_47_49_51_53_55(base_list_47_49_51_53_55, TypeRecvData);
                free(m_ModbusRTUDevice->recvMsg);
            }

            int ret_base57_78 = modbus_read_input_registers(m_ModbusRTUDevice, 57, 22, base57_78);
            if(MODBUS_ERR == ret_base57_78)
            {
                goto label;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData_base_info57_78(sendArray, TypeSendData, base57_78);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showModbusData_base_info57_78(recvArray, TypeRecvData, base57_78);
                free(m_ModbusRTUDevice->recvMsg);
            }

            int ret_fault = modbus_read_input_registers(m_ModbusRTUDevice, 66, 8, fault);
            if(MODBUS_ERR == ret_fault)
            {
                goto label;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showFault(sendArray, TypeSendData, fault);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showFault(recvArray, TypeRecvData,fault);
                free(m_ModbusRTUDevice->recvMsg);
            }

            int ret_base83_106 = modbus_read_input_registers(m_ModbusRTUDevice, 83, 24, base83_106);
            if(MODBUS_ERR == ret_base83_106)
            {
                goto label;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData_base_info83_106(sendArray, TypeSendData, base83_106);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showModbusData_base_info83_106(recvArray, TypeRecvData, base83_106);
                free(m_ModbusRTUDevice->recvMsg);
            }
            int volAddress = (1001 + BMUIndex * 16);
            int tempAddress = (1601 + BMUIndex * 16);

            int ret_vol = modbus_read_input_registers(m_ModbusRTUDevice, volAddress, 16, sgl_vol);
            if(MODBUS_ERR == ret_vol)
            {
                goto label;

            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData(sendArray, TypeSendData, sgl_vol);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showModbusData(recvArray, TypeRecvData, sgl_vol);
                free(m_ModbusRTUDevice->recvMsg);
            }
            int ret_tempt = modbus_read_input_registers(m_ModbusRTUDevice, tempAddress, 16, sgl_tempt);
            if(MODBUS_ERR == ret_tempt)
            {
                goto label;
            }
            else
            {
                QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
                emit sig_showModbusData_sgl_tempt(sendArray, TypeSendData, sgl_tempt);
                free(m_ModbusRTUDevice->sendMsg);
                QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
                emit sig_showModbusData_sgl_tempt(recvArray, TypeRecvData, sgl_tempt);
                free(m_ModbusRTUDevice->recvMsg);
            }

            int milsec = time.elapsed();
            qDebug() <<"the time:  " << milsec;
        }
    }
}


void ModbusRTU::write_regs_slot(int addr,const uint16_t data)
{
    // qDebug() << "write:进入线程：" << QThread::currentThread();
    int rc = write_single_register(addr, data);
    this->blockSignals(true);
    if(MODBUS_ERR == rc) {
        qDebug() << "write######modbus no message" << modbus_strerror(errno);
        return;
    }
}

void ModbusRTU::read_regs_slot(int addr, int nb, uint16_t *data, int row)
{
    // qDebug() << "read:进入线程：" << QThread::currentThread();
    // uint16_t temp[10];
    // uint16_t temp1[10] = {1, 2, 3, 4, 5};
    // memset(temp1, 0, sizeof(temp));
    qDebug() << "current add and nb" << addr << "   " << nb;
    int rc = read_holding_register(addr, nb, data);
    if(MODBUS_ERR == rc) {
        qDebug() << "read modbus no message" << modbus_strerror(errno);
        return;
    }
    else
    {
        // qDebug() << "read rc" << rc;
        // QByteArray sendArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->sendMsg), m_ModbusRTUDevice->sendMsgLen);
        // emit sig_showReadHoldingRegs(row, nb, temp);
        // free(m_ModbusRTUDevice->sendMsg);
        QByteArray recvArray = QByteArray::fromRawData(reinterpret_cast<char *>(m_ModbusRTUDevice->recvMsg), m_ModbusRTUDevice->recvMsgLen);
        emit sig_showReadHoldingRegs(row, nb, data);
        free(m_ModbusRTUDevice->recvMsg);
        // emit sig_testData(temp);
    }
}

void ModbusRTU::slot_pauseThread()
{
    qDebug() << "暂停线程";
    closeThread = false;
    // emit paused();
}

void ModbusRTU::slot_resumeThread()
{
    qDebug() << "恢复线程";

    // eventLoop.exit();
    // eventLoop.quit();

    // qDebug() << "Event loop state before quit: " << eventLoop.isRunning();
    closeThread = true;
    // emit resumed();
    // qDebug() << "closeThread:" << closeThread;
}

void ModbusRTU::change_BMUIndex_slot(int index)
{
    BMUIndex = index;
}


bool ModbusRTU::modbusRTUConnect(const char *comPort, int baudRate, char parity, int dataBit, int stopBit)
{
    qDebug() << "comPort:" << comPort << "baudRate:" << baudRate << "parity:" << parity << "dataBit" << dataBit << "stopBit:" << stopBit;
    m_ModbusRTUDevice = modbus_new_rtu(comPort, baudRate, parity, dataBit, stopBit);
    if(m_ModbusRTUDevice == NULL) {
        qDebug() << "create modbus device failed";
        return false;
    }
    else {
        qDebug() << "create modbus device success";
    }

    if (MODBUS_ERR == modbus_set_slave(m_ModbusRTUDevice, 1)
        || MODBUS_ERR == modbus_connect(m_ModbusRTUDevice)) {
        modbus_free(m_ModbusRTUDevice);
        qDebug() << "modbus disconnect";
        return false;
    }
    else {
        qDebug() << "modbus connect";
        modbus_set_debug(m_ModbusRTUDevice, false);
        return true;
    }
}

void ModbusRTU::modbusRTUDisconnect()
{
    modbus_close(m_ModbusRTUDevice);
}

int ModbusRTU::read_coil_status(int addr, int nb, uint8_t *dest)
{
    return modbus_read_bits(m_ModbusRTUDevice, addr, nb, dest);
}

int ModbusRTU::read_input_status(int addr, int nb, uint8_t *dest)
{
    return modbus_read_input_bits(m_ModbusRTUDevice, addr, nb, dest);
}

int ModbusRTU::read_holding_register(int addr, int nb, uint16_t *dest)
{
    return modbus_read_registers(m_ModbusRTUDevice, addr, nb, dest);
}

int ModbusRTU::read_input_register(int addr, int nb, uint16_t *dest)
{
    return modbus_read_input_registers(m_ModbusRTUDevice, addr, nb, dest);
}

int ModbusRTU::write_single_coil(int coil_addr, int status)
{
    return modbus_write_bit(m_ModbusRTUDevice, coil_addr, status);
}

int ModbusRTU::write_single_register(int reg_addr, const uint16_t value)
{
    return modbus_write_register(m_ModbusRTUDevice, reg_addr, value);
}

int ModbusRTU::write_multiple_coil(int addr, int nb, const uint8_t *data)
{
    return modbus_write_bits(m_ModbusRTUDevice, addr, nb, data);
}

int ModbusRTU::write_multiple_registers(int addr, int nb, const uint16_t *data)
{
    return modbus_write_registers(m_ModbusRTUDevice, addr, nb, data);
}
