| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- #include "QThreadHttpClient.h"
- #include "DataManager.h"
- #include <QSettings>
- #include <QDebug>
- #include <QApplication>
- #include <QThread> // 添加线程支持
- #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>("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>("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);
- }
|