#include "QThreadHttpClient.h" #include "DataManager.h" #include #include #include #include // 添加线程支持 #include "AsioUDPNetDLL.h" #include "TaskMNG.h" #include "ElectricityVOC.h" #ifdef Q_OS_WIN #pragma execution_character_set("utf-8") #endif QThreadHttpClient* QThreadHttpClient::g_HttpSingle; QMutex QThreadHttpClient::m_clientMutex; QThreadHttpClient& QThreadHttpClient::instance() { if (g_HttpSingle == NULL) { QMutexLocker lock(&m_clientMutex); if (g_HttpSingle == NULL) { g_HttpSingle = new (std::nothrow) QThreadHttpClient(nullptr); } } return *g_HttpSingle; } void QThreadHttpClient::destroyInstance() { QMutexLocker lock(&m_clientMutex); if (g_HttpSingle) { g_HttpSingle->stopReconnectTimer(); // 停止定时器 delete g_HttpSingle; g_HttpSingle = NULL; } } QThreadHttpClient::QThreadHttpClient(QObject* parent) : QObject(parent), pClient(nullptr), m_reconnectTimer(nullptr), m_bReconnectSuccess(false), m_reconnectAttemptCount(0), m_maxReconnectAttempts(5) // 默认最大尝试5次 { qRegisterMetaType("std::string"); connect(this, SIGNAL(signal_SignalData(std::string, std::string)), this, SLOT(slot_SendPost(std::string, std::string)), Qt::QueuedConnection); } QThreadHttpClient::~QThreadHttpClient() { stopReconnectTimer(); if (pClient) { delete pClient; pClient = nullptr; } } void QThreadHttpClient::initHttpClient() { QString strHost = ""; int nPort = 0; QString strGetPath = QApplication::applicationDirPath(); strGetPath.append("/config"); QSettings settings(strGetPath, QSettings::IniFormat); settings.setIniCodec("GBK"); int nTimeOut = READ_INI_INT("HttpClient/HttpTimeOut", 2); strHost = READ_INI_STR("HttpClient/IP", "127.0.0.1"); nPort = READ_INI_INT("HttpClient/port", 8090); qDebug() << "HttpClient:" << strHost << " port:" << nPort; // 创建客户端 pClient = new httplib::Client(strHost.toStdString(), nPort); pClient->set_connection_timeout(nTimeOut); pClient->set_write_timeout(nTimeOut); pClient->set_read_timeout(nTimeOut); // 初始化连接状态 m_bReconnectSuccess = (pClient != nullptr); // 启动定时器检查连接 startReconnectTimer(); } bool QThreadHttpClient::HttpPost(const std::string& strUrl, const std::string& strRequest, std::string& strResponse) { QMutexLocker lock(&m_clientMutex); if (!pClient || !m_bReconnectSuccess) { if (!reconnectNoLock()) { AddLogJson(strRequest, "Client is null or not connected, reconnect failed", strUrl, false); return false; } } try { auto result = pClient->Post(strUrl.c_str(), strRequest, "application/json"); if (!result) { // 请求失败,更新连接状态并尝试重连 m_bReconnectSuccess = false; if (reconnectNoLock()) { result = pClient->Post(strUrl.c_str(), strRequest, "application/json"); } if (!result) { AddLogJson(strRequest, "Request failed or timeout", strUrl, false); return false; } } strResponse = result->body; AddLogJson(strRequest, strResponse, strUrl, result->status); return (result->status == 200); } catch (const std::exception& e) { m_bReconnectSuccess = false; AddLogJson(strRequest, std::string("Exception: ") + e.what(), strUrl, false); reconnect(); // 发生异常后重连 return false; } catch (...) { m_bReconnectSuccess = false; AddLogJson(strRequest, "Unknown exception", strUrl, false); reconnect(); // 发生异常后重连 return false; } } bool QThreadHttpClient::reconnect() { QMutexLocker lock(&m_clientMutex); return reconnectNoLock(); } bool QThreadHttpClient::isConnected() { QMutexLocker lock(&m_clientMutex); if (!pClient) return false; // 简单的连接测试 auto result = pClient->Get("/"); bool connected = (result != nullptr && result->status == 200); if (m_bReconnectSuccess != connected) { m_bReconnectSuccess = connected; //emit signal_ConnectionStatusChanged(connected); } return connected; } bool QThreadHttpClient::reconnectNoLock() { // 注意:调用此函数前必须已经获取 m_clientMutex 锁 // 检查是否达到最大重连次数 if (m_reconnectAttemptCount >= m_maxReconnectAttempts) { qDebug() << "Maximum reconnect attempts reached: " << m_maxReconnectAttempts; //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false); return false; } m_reconnectAttemptCount++; qDebug() << "Reconnect attempt " << m_reconnectAttemptCount << "/" << m_maxReconnectAttempts; if (pClient) { delete pClient; pClient = nullptr; } QString strHost = ""; int nPort = 0; QString strGetPath = QApplication::applicationDirPath(); strGetPath.append("/config"); QSettings settings(strGetPath, QSettings::IniFormat); settings.setIniCodec("GBK"); int nTimeOut = READ_INI_INT("HttpClient/HttpTimeOut", 2); strHost = READ_INI_STR("HttpClient/IP", "127.0.0.1"); nPort = READ_INI_INT("HttpClient/port", 8090); try { pClient = new httplib::Client(strHost.toStdString(), nPort); if (pClient) { pClient->set_connection_timeout(nTimeOut); pClient->set_write_timeout(nTimeOut); pClient->set_read_timeout(nTimeOut); } // 测试连接 bool connected = false; if (pClient) { auto result = pClient->Get("/"); connected = (result != nullptr && result->status == 200); } if (connected) { m_bReconnectSuccess = true; m_reconnectAttemptCount = 0; // 重置重连计数 qDebug() << "Reconnect successful!"; // 通知等待的线程 m_connectionCondition.wakeAll(); // 发出连接成功信号 //emit signal_ConnectionStatusChanged(true); //emit signal_ReconnectAttempt(m_reconnectAttemptCount, true); // 停止定时器重连 stopReconnectTimer(); } else { m_bReconnectSuccess = false; qDebug() << "Reconnect failed!"; //emit signal_ConnectionStatusChanged(false); //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false); // 如果客户端创建失败,清理 if (pClient) { delete pClient; pClient = nullptr; } // 启动定时器继续尝试 startReconnectTimer(); } return connected; } catch (...) { m_bReconnectSuccess = false; qDebug() << "Exception during reconnect"; //emit signal_ConnectionStatusChanged(false); //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false); // 清理客户端 if (pClient) { delete pClient; pClient = nullptr; } // 启动定时器继续尝试 startReconnectTimer(); return false; } } bool QThreadHttpClient::waitForConnection(int timeoutMs) { QMutexLocker lock(&m_connectionMutex); // 如果已经连接,直接返回 if (m_bReconnectSuccess && isConnected()) { return true; } // 如果不是在连接状态,开始重连 if (!m_bReconnectSuccess) { reconnect(); } // 等待连接完成 return m_connectionCondition.wait(&m_connectionMutex, timeoutMs); } void QThreadHttpClient::startReconnectTimer() { if (!m_reconnectTimer) { m_reconnectTimer = new QTimer(this); connect(m_reconnectTimer, &QTimer::timeout, this, &QThreadHttpClient::slot_ReconnectTimer); } if (!m_reconnectTimer->isActive()) { m_reconnectTimer->start(5000); // 5秒重连一次 qDebug() << "Start reconnect timer"; } } void QThreadHttpClient::stopReconnectTimer() { if (m_reconnectTimer && m_reconnectTimer->isActive()) { m_reconnectTimer->stop(); qDebug() << "Stop reconnect timer"; } } void QThreadHttpClient::slot_ReconnectTimer() { qDebug() << "Reconnect timer triggered"; if (!m_bReconnectSuccess) { reconnect(); } else { // 如果已经连接成功,停止定时器 stopReconnectTimer(); } } // 其他函数保持原样... void QThreadHttpClient::InitConnect(QObject* pCMD) { qRegisterMetaType("OCCCOMMAND"); connect(pCMD, SIGNAL(signal_Command2Server(int, OCCCOMMAND)), this, SLOT(slot_CMDPop(int, OCCCOMMAND)), Qt::QueuedConnection); } void QThreadHttpClient::slot_CMDPop(int nCmdID, OCCCOMMAND pCmdData) { // 原有代码保持不变... NetDll_SendUDPDataToMulti(HDDSType::HDDSType_sOCCCMD, &pCmdData, pCmdData.DateLen + 32); switch (nCmdID) { case OCCCOMMAND::eUpdateEqpmtStatus: { ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC(); if (!pElcVoc) { return; } Json::Value pJson; pJson["LineID"] = pElcVoc->m_nRunLineID; pJson["CmdType"] = 0;//设备控制 pJson["EqpmtID"] = pCmdData.Net_DH_EqpmtUpdate.EqpmtStrID; pJson["Status"] = pCmdData.Net_DH_EqpmtUpdate.Status; pJson["CtrlType"] = pCmdData.Net_DH_EqpmtUpdate.CtrlType; pJson["CtrlLock"] = pCmdData.Net_DH_EqpmtUpdate.CtrlLock; pJson["FaultLock"] = pCmdData.Net_DH_EqpmtUpdate.FaultLock; pJson["RemoteLock"] = pCmdData.Net_DH_EqpmtUpdate.RemoteLock; pJson["CtrlArea"] = pCmdData.Net_DH_EqpmtUpdate.CtrlArea; pJson["fValue"] = ""; pJson["nValueType"] = ""; pJson["IsReset"] = ""; Json::FastWriter pfastW; std::string strJson = pfastW.write(pJson); emit signal_SignalData("/courserun/eqpmtstatus", strJson); } break; case OCCCOMMAND::eUpdateEqpmtTelemeteryValue: { ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC(); if (!pElcVoc) { return; } Json::Value pJson; pJson["LineID"] = pElcVoc->m_nRunLineID; pJson["CmdType"] = 1;//设备数据 pJson["EqpmtID"] = pCmdData.Net_DH_EqpmtTelemtryValue.EqpmtStrID; pJson["Status"] = ""; pJson["CtrlType"] = ""; pJson["CtrlLock"] = ""; pJson["FaultLock"] = ""; pJson["RemoteLock"] = ""; pJson["CtrlArea"] = ""; pJson["fValue"] = pCmdData.Net_DH_EqpmtTelemtryValue.fValue; pJson["nValueType"] = pCmdData.Net_DH_EqpmtTelemtryValue.nType; pJson["IsReset"] = pCmdData.Net_DH_EqpmtTelemtryValue.IsReset; Json::FastWriter pfastW; std::string strJson = pfastW.write(pJson); emit signal_SignalData("/courserun/eqpmtstatus", strJson); } break; case OCCCOMMAND::eUpdateEvaOperStatus: { Json::Value pJson; pJson["CtrlType"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperItemSubType1; pJson["CtrlSubType"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperItemSubType2; pJson["CtrlFrom"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperClientID; std::string strData = std::to_string(pCmdData.Net_JY_UpdateEvaOperStatus.OperStuID); pJson["CtrlUser"] = strData; pJson["Param1"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara1; pJson["Param2"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara2; pJson["Param3"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara3; pJson["Param4"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara4; pJson["Param5"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara5; Json::FastWriter pfastW; std::string strJson = pfastW.write(pJson); emit signal_SignalData("/courserun/add_ctrl_log", strJson); } break; case OCCCOMMAND::eUpdateAccident: { if (pCmdData.Net_ELC_Accident.ClientType== OperClient_Tech) { break; } if (pCmdData.Net_ELC_Accident.EventType == POWER_ERORR_OCCAR) //故障发生 { ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC(); if (!pElcVoc) { return; } ELEEQPMTMAP* pEqpmtList = pElcVoc->getElectricEqpmtMap(); if (pEqpmtList) { auto iterEqpmt = pEqpmtList->find(pCmdData.Net_ELC_Accident.EqpmtStrID); if (iterEqpmt != pEqpmtList->end()) { DataManager::instance().addEqpmFault(pCmdData.Net_ELC_Accident.EqpmtStrID, iterEqpmt->second->GetBaseType(), pCmdData.Net_ELC_Accident.parm); } else { DataManager::instance().addEqpmFault(pCmdData.Net_ELC_Accident.EqpmtStrID, 0, pCmdData.Net_ELC_Accident.parm); } } } if (pCmdData.Net_ELC_Accident.EventType == POWER_ERORR_REVERT) //恢复故障 { DataManager::instance().DeleteEqpmtFault(pCmdData.Net_ELC_Accident.EqpmtStrID, pCmdData.Net_ELC_Accident.parm); } } break; default: break; } } void QThreadHttpClient::slot_SendPost(std::string strUrl, std::string strRequest) { std::string strReData; HttpPost(strUrl, strRequest, strReData); } void QThreadHttpClient::AddLogJson(std::string strRequest, std::string strResponse, std::string nAPIID, bool bStatus) { // 原有代码保持不变... std::string strShow = "", strRetrun = ""; if (!DataManager::JsonToStyled(strRequest, strShow)) { strShow = DataManager::UTF8_to_string(strRequest); } else { strShow = DataManager::UTF8_to_string(strShow); } if (!DataManager::JsonToStyled(strResponse, strRetrun)) { strRetrun = strResponse; } LogJson pData(strShow, strRetrun, nAPIID, bStatus); DataManager::instance().AddHttpLog(pData); }