QThreadHttpClient.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #include "QThreadHttpClient.h"
  2. #include "DataManager.h"
  3. #include <QSettings>
  4. #include <QDebug>
  5. #include <QApplication>
  6. #include <QThread> // 添加线程支持
  7. #include "AsioUDPNetDLL.h"
  8. #include "TaskMNG.h"
  9. #include "ElectricityVOC.h"
  10. #ifdef Q_OS_WIN
  11. #pragma execution_character_set("utf-8")
  12. #endif
  13. QThreadHttpClient* QThreadHttpClient::g_HttpSingle;
  14. QMutex QThreadHttpClient::m_clientMutex;
  15. QThreadHttpClient& QThreadHttpClient::instance()
  16. {
  17. if (g_HttpSingle == NULL)
  18. {
  19. QMutexLocker lock(&m_clientMutex);
  20. if (g_HttpSingle == NULL)
  21. {
  22. g_HttpSingle = new (std::nothrow) QThreadHttpClient(nullptr);
  23. }
  24. }
  25. return *g_HttpSingle;
  26. }
  27. void QThreadHttpClient::destroyInstance()
  28. {
  29. QMutexLocker lock(&m_clientMutex);
  30. if (g_HttpSingle)
  31. {
  32. g_HttpSingle->stopReconnectTimer(); // 停止定时器
  33. delete g_HttpSingle;
  34. g_HttpSingle = NULL;
  35. }
  36. }
  37. QThreadHttpClient::QThreadHttpClient(QObject* parent)
  38. : QObject(parent),
  39. pClient(nullptr),
  40. m_reconnectTimer(nullptr),
  41. m_bReconnectSuccess(false),
  42. m_reconnectAttemptCount(0),
  43. m_maxReconnectAttempts(5) // 默认最大尝试5次
  44. {
  45. qRegisterMetaType<std::string>("std::string");
  46. connect(this, SIGNAL(signal_SignalData(std::string, std::string)),
  47. this, SLOT(slot_SendPost(std::string, std::string)), Qt::QueuedConnection);
  48. }
  49. QThreadHttpClient::~QThreadHttpClient()
  50. {
  51. stopReconnectTimer();
  52. if (pClient) {
  53. delete pClient;
  54. pClient = nullptr;
  55. }
  56. }
  57. void QThreadHttpClient::initHttpClient()
  58. {
  59. QString strHost = "";
  60. int nPort = 0;
  61. QString strGetPath = QApplication::applicationDirPath();
  62. strGetPath.append("/config");
  63. QSettings settings(strGetPath, QSettings::IniFormat);
  64. settings.setIniCodec("GBK");
  65. int nTimeOut = READ_INI_INT("HttpClient/HttpTimeOut", 2);
  66. strHost = READ_INI_STR("HttpClient/IP", "127.0.0.1");
  67. nPort = READ_INI_INT("HttpClient/port", 8090);
  68. qDebug() << "HttpClient:" << strHost << " port:" << nPort;
  69. // 创建客户端
  70. pClient = new httplib::Client(strHost.toStdString(), nPort);
  71. pClient->set_connection_timeout(nTimeOut);
  72. pClient->set_write_timeout(nTimeOut);
  73. pClient->set_read_timeout(nTimeOut);
  74. // 初始化连接状态
  75. m_bReconnectSuccess = (pClient != nullptr);
  76. // 启动定时器检查连接
  77. startReconnectTimer();
  78. }
  79. bool QThreadHttpClient::HttpPost(const std::string& strUrl, const std::string& strRequest, std::string& strResponse)
  80. {
  81. QMutexLocker lock(&m_clientMutex);
  82. if (!pClient || !m_bReconnectSuccess) {
  83. if (!reconnectNoLock()) {
  84. AddLogJson(strRequest, "Client is null or not connected, reconnect failed", strUrl, false);
  85. return false;
  86. }
  87. }
  88. try {
  89. auto result = pClient->Post(strUrl.c_str(), strRequest, "application/json");
  90. if (!result) {
  91. // 请求失败,更新连接状态并尝试重连
  92. m_bReconnectSuccess = false;
  93. if (reconnectNoLock()) {
  94. result = pClient->Post(strUrl.c_str(), strRequest, "application/json");
  95. }
  96. if (!result) {
  97. AddLogJson(strRequest, "Request failed or timeout", strUrl, false);
  98. return false;
  99. }
  100. }
  101. strResponse = result->body;
  102. AddLogJson(strRequest, strResponse, strUrl, result->status);
  103. return (result->status == 200);
  104. }
  105. catch (const std::exception& e) {
  106. m_bReconnectSuccess = false;
  107. AddLogJson(strRequest, std::string("Exception: ") + e.what(), strUrl, false);
  108. reconnect(); // 发生异常后重连
  109. return false;
  110. }
  111. catch (...) {
  112. m_bReconnectSuccess = false;
  113. AddLogJson(strRequest, "Unknown exception", strUrl, false);
  114. reconnect(); // 发生异常后重连
  115. return false;
  116. }
  117. }
  118. bool QThreadHttpClient::reconnect()
  119. {
  120. QMutexLocker lock(&m_clientMutex);
  121. return reconnectNoLock();
  122. }
  123. bool QThreadHttpClient::isConnected()
  124. {
  125. QMutexLocker lock(&m_clientMutex);
  126. if (!pClient) return false;
  127. // 简单的连接测试
  128. auto result = pClient->Get("/");
  129. bool connected = (result != nullptr && result->status == 200);
  130. if (m_bReconnectSuccess != connected) {
  131. m_bReconnectSuccess = connected;
  132. //emit signal_ConnectionStatusChanged(connected);
  133. }
  134. return connected;
  135. }
  136. bool QThreadHttpClient::reconnectNoLock()
  137. {
  138. // 注意:调用此函数前必须已经获取 m_clientMutex 锁
  139. // 检查是否达到最大重连次数
  140. if (m_reconnectAttemptCount >= m_maxReconnectAttempts) {
  141. qDebug() << "Maximum reconnect attempts reached: " << m_maxReconnectAttempts;
  142. //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false);
  143. return false;
  144. }
  145. m_reconnectAttemptCount++;
  146. qDebug() << "Reconnect attempt " << m_reconnectAttemptCount << "/" << m_maxReconnectAttempts;
  147. if (pClient) {
  148. delete pClient;
  149. pClient = nullptr;
  150. }
  151. QString strHost = "";
  152. int nPort = 0;
  153. QString strGetPath = QApplication::applicationDirPath();
  154. strGetPath.append("/config");
  155. QSettings settings(strGetPath, QSettings::IniFormat);
  156. settings.setIniCodec("GBK");
  157. int nTimeOut = READ_INI_INT("HttpClient/HttpTimeOut", 2);
  158. strHost = READ_INI_STR("HttpClient/IP", "127.0.0.1");
  159. nPort = READ_INI_INT("HttpClient/port", 8090);
  160. try {
  161. pClient = new httplib::Client(strHost.toStdString(), nPort);
  162. if (pClient) {
  163. pClient->set_connection_timeout(nTimeOut);
  164. pClient->set_write_timeout(nTimeOut);
  165. pClient->set_read_timeout(nTimeOut);
  166. }
  167. // 测试连接
  168. bool connected = false;
  169. if (pClient) {
  170. auto result = pClient->Get("/");
  171. connected = (result != nullptr && result->status == 200);
  172. }
  173. if (connected) {
  174. m_bReconnectSuccess = true;
  175. m_reconnectAttemptCount = 0; // 重置重连计数
  176. qDebug() << "Reconnect successful!";
  177. // 通知等待的线程
  178. m_connectionCondition.wakeAll();
  179. // 发出连接成功信号
  180. //emit signal_ConnectionStatusChanged(true);
  181. //emit signal_ReconnectAttempt(m_reconnectAttemptCount, true);
  182. // 停止定时器重连
  183. stopReconnectTimer();
  184. }
  185. else {
  186. m_bReconnectSuccess = false;
  187. qDebug() << "Reconnect failed!";
  188. //emit signal_ConnectionStatusChanged(false);
  189. //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false);
  190. // 如果客户端创建失败,清理
  191. if (pClient) {
  192. delete pClient;
  193. pClient = nullptr;
  194. }
  195. // 启动定时器继续尝试
  196. startReconnectTimer();
  197. }
  198. return connected;
  199. }
  200. catch (...) {
  201. m_bReconnectSuccess = false;
  202. qDebug() << "Exception during reconnect";
  203. //emit signal_ConnectionStatusChanged(false);
  204. //emit signal_ReconnectAttempt(m_reconnectAttemptCount, false);
  205. // 清理客户端
  206. if (pClient) {
  207. delete pClient;
  208. pClient = nullptr;
  209. }
  210. // 启动定时器继续尝试
  211. startReconnectTimer();
  212. return false;
  213. }
  214. }
  215. bool QThreadHttpClient::waitForConnection(int timeoutMs)
  216. {
  217. QMutexLocker lock(&m_connectionMutex);
  218. // 如果已经连接,直接返回
  219. if (m_bReconnectSuccess && isConnected()) {
  220. return true;
  221. }
  222. // 如果不是在连接状态,开始重连
  223. if (!m_bReconnectSuccess) {
  224. reconnect();
  225. }
  226. // 等待连接完成
  227. return m_connectionCondition.wait(&m_connectionMutex, timeoutMs);
  228. }
  229. void QThreadHttpClient::startReconnectTimer()
  230. {
  231. if (!m_reconnectTimer) {
  232. m_reconnectTimer = new QTimer(this);
  233. connect(m_reconnectTimer, &QTimer::timeout, this, &QThreadHttpClient::slot_ReconnectTimer);
  234. }
  235. if (!m_reconnectTimer->isActive()) {
  236. m_reconnectTimer->start(5000); // 5秒重连一次
  237. qDebug() << "Start reconnect timer";
  238. }
  239. }
  240. void QThreadHttpClient::stopReconnectTimer()
  241. {
  242. if (m_reconnectTimer && m_reconnectTimer->isActive()) {
  243. m_reconnectTimer->stop();
  244. qDebug() << "Stop reconnect timer";
  245. }
  246. }
  247. void QThreadHttpClient::slot_ReconnectTimer()
  248. {
  249. qDebug() << "Reconnect timer triggered";
  250. if (!m_bReconnectSuccess) {
  251. reconnect();
  252. }
  253. else {
  254. // 如果已经连接成功,停止定时器
  255. stopReconnectTimer();
  256. }
  257. }
  258. // 其他函数保持原样...
  259. void QThreadHttpClient::InitConnect(QObject* pCMD)
  260. {
  261. qRegisterMetaType<OCCCOMMAND>("OCCCOMMAND");
  262. connect(pCMD, SIGNAL(signal_Command2Server(int, OCCCOMMAND)),
  263. this, SLOT(slot_CMDPop(int, OCCCOMMAND)), Qt::QueuedConnection);
  264. }
  265. void QThreadHttpClient::slot_CMDPop(int nCmdID, OCCCOMMAND pCmdData)
  266. {
  267. // 原有代码保持不变...
  268. NetDll_SendUDPDataToMulti(HDDSType::HDDSType_sOCCCMD, &pCmdData, pCmdData.DateLen + 32);
  269. switch (nCmdID)
  270. {
  271. case OCCCOMMAND::eUpdateEqpmtStatus:
  272. {
  273. ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC();
  274. if (!pElcVoc)
  275. {
  276. return;
  277. }
  278. Json::Value pJson;
  279. pJson["LineID"] = pElcVoc->m_nRunLineID;
  280. pJson["CmdType"] = 0;//设备控制
  281. pJson["EqpmtID"] = pCmdData.Net_DH_EqpmtUpdate.EqpmtStrID;
  282. pJson["Status"] = pCmdData.Net_DH_EqpmtUpdate.Status;
  283. pJson["CtrlType"] = pCmdData.Net_DH_EqpmtUpdate.CtrlType;
  284. pJson["CtrlLock"] = pCmdData.Net_DH_EqpmtUpdate.CtrlLock;
  285. pJson["FaultLock"] = pCmdData.Net_DH_EqpmtUpdate.FaultLock;
  286. pJson["RemoteLock"] = pCmdData.Net_DH_EqpmtUpdate.RemoteLock;
  287. pJson["CtrlArea"] = pCmdData.Net_DH_EqpmtUpdate.CtrlArea;
  288. pJson["fValue"] = "";
  289. pJson["nValueType"] = "";
  290. pJson["IsReset"] = "";
  291. Json::FastWriter pfastW;
  292. std::string strJson = pfastW.write(pJson);
  293. emit signal_SignalData("/courserun/eqpmtstatus", strJson);
  294. }
  295. break;
  296. case OCCCOMMAND::eUpdateEqpmtTelemeteryValue:
  297. {
  298. ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC();
  299. if (!pElcVoc)
  300. {
  301. return;
  302. }
  303. Json::Value pJson;
  304. pJson["LineID"] = pElcVoc->m_nRunLineID;
  305. pJson["CmdType"] = 1;//设备数据
  306. pJson["EqpmtID"] = pCmdData.Net_DH_EqpmtTelemtryValue.EqpmtStrID;
  307. pJson["Status"] = "";
  308. pJson["CtrlType"] = "";
  309. pJson["CtrlLock"] = "";
  310. pJson["FaultLock"] = "";
  311. pJson["RemoteLock"] = "";
  312. pJson["CtrlArea"] = "";
  313. pJson["fValue"] = pCmdData.Net_DH_EqpmtTelemtryValue.fValue;
  314. pJson["nValueType"] = pCmdData.Net_DH_EqpmtTelemtryValue.nType;
  315. pJson["IsReset"] = pCmdData.Net_DH_EqpmtTelemtryValue.IsReset;
  316. Json::FastWriter pfastW;
  317. std::string strJson = pfastW.write(pJson);
  318. emit signal_SignalData("/courserun/eqpmtstatus", strJson);
  319. }
  320. break;
  321. case OCCCOMMAND::eUpdateEvaOperStatus:
  322. {
  323. Json::Value pJson;
  324. pJson["CtrlType"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperItemSubType1;
  325. pJson["CtrlSubType"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperItemSubType2;
  326. pJson["CtrlFrom"] = pCmdData.Net_JY_UpdateEvaOperStatus.OperClientID;
  327. std::string strData = std::to_string(pCmdData.Net_JY_UpdateEvaOperStatus.OperStuID);
  328. pJson["CtrlUser"] = strData;
  329. pJson["Param1"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara1;
  330. pJson["Param2"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara2;
  331. pJson["Param3"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara3;
  332. pJson["Param4"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara4;
  333. pJson["Param5"] = pCmdData.Net_JY_UpdateEvaOperStatus.AssociPara5;
  334. Json::FastWriter pfastW;
  335. std::string strJson = pfastW.write(pJson);
  336. emit signal_SignalData("/courserun/add_ctrl_log", strJson);
  337. }
  338. break;
  339. case OCCCOMMAND::eUpdateAccident:
  340. {
  341. if (pCmdData.Net_ELC_Accident.ClientType== OperClient_Tech)
  342. {
  343. break;
  344. }
  345. if (pCmdData.Net_ELC_Accident.EventType == POWER_ERORR_OCCAR) //故障发生
  346. {
  347. ElectricityVOC* pElcVoc = (ElectricityVOC*)TaskMNG::instance()->pGetEleVOC();
  348. if (!pElcVoc)
  349. {
  350. return;
  351. }
  352. ELEEQPMTMAP* pEqpmtList = pElcVoc->getElectricEqpmtMap();
  353. if (pEqpmtList)
  354. {
  355. auto iterEqpmt = pEqpmtList->find(pCmdData.Net_ELC_Accident.EqpmtStrID);
  356. if (iterEqpmt != pEqpmtList->end())
  357. {
  358. DataManager::instance().addEqpmFault(pCmdData.Net_ELC_Accident.EqpmtStrID, iterEqpmt->second->GetBaseType(), pCmdData.Net_ELC_Accident.parm);
  359. }
  360. else
  361. {
  362. DataManager::instance().addEqpmFault(pCmdData.Net_ELC_Accident.EqpmtStrID, 0, pCmdData.Net_ELC_Accident.parm);
  363. }
  364. }
  365. }
  366. if (pCmdData.Net_ELC_Accident.EventType == POWER_ERORR_REVERT) //恢复故障
  367. {
  368. DataManager::instance().DeleteEqpmtFault(pCmdData.Net_ELC_Accident.EqpmtStrID, pCmdData.Net_ELC_Accident.parm);
  369. }
  370. }
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. void QThreadHttpClient::slot_SendPost(std::string strUrl, std::string strRequest)
  377. {
  378. std::string strReData;
  379. HttpPost(strUrl, strRequest, strReData);
  380. }
  381. void QThreadHttpClient::AddLogJson(std::string strRequest, std::string strResponse, std::string nAPIID, bool bStatus)
  382. {
  383. // 原有代码保持不变...
  384. std::string strShow = "", strRetrun = "";
  385. if (!DataManager::JsonToStyled(strRequest, strShow))
  386. {
  387. strShow = DataManager::UTF8_to_string(strRequest);
  388. }
  389. else
  390. {
  391. strShow = DataManager::UTF8_to_string(strShow);
  392. }
  393. if (!DataManager::JsonToStyled(strResponse, strRetrun))
  394. {
  395. strRetrun = strResponse;
  396. }
  397. LogJson pData(strShow, strRetrun, nAPIID, bStatus);
  398. DataManager::instance().AddHttpLog(pData);
  399. }