ThreadCompareItemManager.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. #include "ThreadCompareItemManager.h"
  2. #include "GlobalInfo.h"
  3. #include "SystemConfig.h"
  4. #include "CompareItemThread.h"
  5. #include "ThreadPool.h"
  6. #include "FromMQTT.h"
  7. #include "commonDefine.h"
  8. /* 给对比项套一层壳,这个函数就是新的线程,在里面new出新的对比项实例,防止Qt报线程归属权错误
  9. 在函数中将对比项实例插入到线程管理器中 */
  10. void ThreadCompareItemManager::thread_compareItem(CalculateThreadInfo_t threadInfo)
  11. {
  12. auto pThread = new CompareItemThread(threadInfo);
  13. if(pThread == nullptr)
  14. {
  15. SPDLOG_ERROR("ThreadCompareItemManager: 创建对比项线程失败");
  16. return;
  17. }
  18. CompareItemManager.addCompareItemThread(pThread);
  19. /* 启动线程,就会一直阻塞在这里了 */
  20. pThread->thread_task();
  21. }
  22. ThreadCompareItemManager::ThreadCompareItemManager()
  23. {
  24. }
  25. ThreadCompareItemManager::~ThreadCompareItemManager()
  26. {
  27. }
  28. /* 线程函数 */
  29. void ThreadCompareItemManager::thread_CompareItemManager()
  30. {
  31. m_logger = spdlog::get("CompareItemManager");
  32. if(m_logger == nullptr)
  33. {
  34. fmt::print("ThreadCompareItemManager: CompareItemManager Logger not found.\n");
  35. return;
  36. }
  37. /* 创建定时器和事件循环 */
  38. m_pEventLoop = new QEventLoop();
  39. m_pTimer = new QTimer();
  40. // m_pTimer->setInterval(10000);
  41. m_pTimer->setTimerType(Qt::PreciseTimer);
  42. m_pTimer->setSingleShot(false); // 设置为非单次定时器
  43. /* 这里要设置直接连接,才会在子线程中调用槽函数 */
  44. connect(m_pTimer, &QTimer::timeout, this, &ThreadCompareItemManager::do_task, Qt::DirectConnection);
  45. /* 初始化webapi */
  46. m_webAPIUrl = GInfo.webAPIUrl();
  47. m_webAPIID = GInfo.webAPIID();
  48. m_webAPIAppType = GInfo.webApiAppType();
  49. if(!m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_webAPIAppType))
  50. {
  51. SPDLOG_LOGGER_ERROR(m_logger, "ThreadCompareItemManager: 初始化WebAPI失败");
  52. return;
  53. }
  54. /* 获取MQTT发布订阅 */
  55. m_pubTopic = GInfo.mqttPubTopicCompareItem();
  56. initMQTT();
  57. /* 获取基础配置,目前只获取一次 */
  58. updateBaseSettings();
  59. SPDLOG_LOGGER_INFO(m_logger, "开启对比项管理线程");
  60. m_pTimer->start(2000);
  61. /* 连接mqtt服务 */
  62. m_pFromMQTT->connectToServer();
  63. m_pEventLoop->exec();
  64. SPDLOG_LOGGER_INFO(m_logger, "ThreadCompareItemManager: 线程结束");
  65. }
  66. /* 通过对比项ID和通道ID获取声卡通道信息 */
  67. OneSoundCardPCMInfo_t ThreadCompareItemManager::getSoundCardRoadInfo(int compareItemID, int roadNum)
  68. {
  69. std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
  70. auto it = m_mapThreads.find(compareItemID);
  71. if(it == m_mapThreads.end())
  72. {
  73. SPDLOG_LOGGER_WARN(m_logger, "对比项线程不存在,ID: {}", compareItemID);
  74. return OneSoundCardPCMInfo_t();
  75. }
  76. auto compareInfo = it.value()->getThreadInfo().compareItemInfo;
  77. OneSoundCardPCMInfo_t roadInfo;
  78. for(const auto& road : compareInfo.mapRoad)
  79. {
  80. if(road.nCompareRoadNum == roadNum)
  81. {
  82. roadInfo = road.scRoadInfo;
  83. break;
  84. }
  85. }
  86. return roadInfo;
  87. }
  88. /* 任务函数 */
  89. void ThreadCompareItemManager::do_task()
  90. {
  91. /* 如果定时间隔小于10秒,则设置成10秒,一开始小是为了线程开启后立马执行一次 */
  92. if(m_pTimer->interval() < 2000)
  93. {
  94. m_pTimer->setInterval(2000);
  95. }
  96. /* 判断MQTT是否连接成功,未连接则再次连接 */
  97. if(m_pFromMQTT->connectState() != QMQTT::ConnectionState::STATE_CONNECTED)
  98. {
  99. SPDLOG_LOGGER_WARN(m_logger, "MQTT未连接,尝试重新连接");
  100. m_pFromMQTT->connectToServer();
  101. }
  102. m_currentTime = QDateTime::currentDateTime();
  103. /* ------------------------------------------------------------------
  104. * 处理对比项信息
  105. * ------------------------------------------------------------------ */
  106. processCompareItemInfo();
  107. /* ------------------------------------------------------------------
  108. * 更新检测时段
  109. * ------------------------------------------------------------------ */
  110. processDetectPeriodInfo();
  111. /* ------------------------------------------------------------------
  112. * 更新对比项信息到MQTT
  113. * ------------------------------------------------------------------ */
  114. updateCompareItemInfoToMQTT();
  115. }
  116. /* 添加对比项实例 */
  117. void ThreadCompareItemManager::addCompareItemThread(CompareItemThread* pThread)
  118. {
  119. if(pThread == nullptr)
  120. {
  121. SPDLOG_LOGGER_ERROR(m_logger, "添加对比项线程失败,线程指针为空");
  122. return;
  123. }
  124. std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
  125. int compareItemID = pThread->getThreadInfo().compareItemInfo.nID;
  126. if(m_mapThreads.contains(compareItemID))
  127. {
  128. SPDLOG_LOGGER_WARN(m_logger, "对比项线程已存在,ID: {}", compareItemID);
  129. return; // 对比项线程已存在
  130. }
  131. m_mapThreads.insert(compareItemID, pThread);
  132. SPDLOG_LOGGER_INFO(m_logger, "添加对比项线程成功,ID: {}", compareItemID);
  133. }
  134. /* 更新基础设置信息,如数据库设置,噪音参数等 */
  135. bool ThreadCompareItemManager::updateBaseSettings()
  136. {
  137. /* 更新基础数据 */
  138. QMap<std::string, std::string> baseSettings;
  139. if(!m_fromWebAPI.getSystemConfig(baseSettings))
  140. {
  141. SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置失败");
  142. return false;
  143. }
  144. /* 将获取到的配置转换成结构体 */
  145. SysConfig.parseConfigFromDatabase(baseSettings);
  146. /* 检测时段单独获取 */
  147. QMap<int, DetectPeriodConfig_t> mapDetectConfig;
  148. if(!m_fromWebAPI.getDetectPeriodConfig(mapDetectConfig))
  149. {
  150. SPDLOG_ERROR("获取对比项检测时段配置失败");
  151. return false;
  152. }
  153. SysConfig.setDetectPeriodConfig(mapDetectConfig);
  154. return true;
  155. }
  156. /* 对比项信息处理函数 */
  157. void ThreadCompareItemManager::processCompareItemInfo()
  158. {
  159. /* 获取对比项信息 */
  160. QList<CompareItemInfo_t> listNewItems;
  161. if(!m_fromWebAPI.getCompareItemInfo(listNewItems))
  162. {
  163. SPDLOG_LOGGER_DEBUG(m_logger, "ThreadCompareItemManager: 获取对比项失败");
  164. return;
  165. }
  166. bool isDeleteAll = false; /* 删除所有对比项 */
  167. // if(listNewItems.size() == 0)
  168. // {
  169. // isDeleteAll = true;
  170. // }else {
  171. checkCompareItemInfo(listNewItems, m_listCreateItems, m_listDeleteItems);
  172. // }
  173. SPDLOG_LOGGER_DEBUG(m_logger, "要退出的对比项个数: {}, 要创建的对比项个数: {}",
  174. m_listDeleteItems.size(), m_listCreateItems.size());
  175. /* 先删除已消失的对比项信息 */
  176. processDeleteCompareItemThreads(m_listDeleteItems, isDeleteAll);
  177. /* 更新需要更新的线程 */
  178. // updateRunningThreads(m_listUpdateItems);
  179. /* 再创建新的对比项线程 */
  180. createNewCompareItemThreads(m_listCreateItems);
  181. SPDLOG_LOGGER_DEBUG(m_logger, "当前对比项个数: {}", m_mapNowCompareItem.size());
  182. }
  183. /**
  184. * @brief 处理对比项信息,新获取的和已有的对比,会在这里更新 m_mapNowCompareItem 内容
  185. *
  186. * @param createList 创建列表
  187. * @param updateList 更新列表,根据对比项ID进行更新信息,没有更新列表了,对比项有更新就删除重建
  188. * @param deleteList 删除列表
  189. */
  190. void ThreadCompareItemManager::checkCompareItemInfo(QList<CompareItemInfo_t>& newList, QList<CompareItemInfo_t>& createList, QList<int>& deleteList)
  191. {
  192. createList.clear();
  193. // updateList.clear();
  194. deleteList.clear();
  195. m_mapNowCompareItem.clear();
  196. // QMap<int, CompareItemInfo_t> mapNowItems;
  197. /* 先从对比项线程中获取对比项信息 */
  198. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
  199. {
  200. BaseCalculateThread* pThread = it.value();
  201. if(pThread == nullptr)
  202. {
  203. continue;
  204. }
  205. /* 获取对比项信息 */
  206. CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo;
  207. m_mapNowCompareItem.insert(itemInfo.nID, itemInfo);
  208. }
  209. /* 遍历新获取的对比项信息,找出需要新增的对比项和需要更新的对比项 */
  210. for(const CompareItemInfo_t& item : newList)
  211. {
  212. if(!m_mapNowCompareItem.contains(item.nID))
  213. {
  214. /* 判断这个是否被启用 */
  215. if(item.isEnable == false)
  216. {
  217. continue;
  218. }
  219. /* 新对比项,添加到创建列表 */
  220. createList.append(item);
  221. } else
  222. {
  223. /* 已有对比项,检查是否需要更新 */
  224. const CompareItemInfo_t& existingItem = m_mapNowCompareItem.value(item.nID);
  225. /* 先对比基础信息 */
  226. if(!existingItem.isEqualBase(item))
  227. {
  228. /* 基础信息不同,需要更新,也可能是被禁用了导致的不同 */
  229. if(item.isEnable == false)
  230. {
  231. /* 如果新对比项被禁用,则需要删除 */
  232. deleteList.append(item.nID);
  233. continue;
  234. }
  235. // updateList.append(item);
  236. deleteList.append(item.nID); // 先删除再创建
  237. createList.append(item); // 添加到创建列表
  238. continue;
  239. }
  240. /* 在对比对比项通道信息 */
  241. if(!existingItem.isEqualRoads(item))
  242. {
  243. /* 通道信息不同,需要更新 */
  244. // updateList.append(item);
  245. deleteList.append(item.nID); // 先删除再创建
  246. createList.append(item); // 添加到创建列表
  247. continue;
  248. }
  249. }
  250. }
  251. /* 遍历当前对比项信息,找出需要删除的对比项 */
  252. for(auto it : m_mapNowCompareItem)
  253. {
  254. bool isFound = false;
  255. for(const CompareItemInfo_t& newItem : newList)
  256. {
  257. if(it.nID == newItem.nID)
  258. {
  259. /* 找到对应的对比项,跳过 */
  260. isFound = true;
  261. break;
  262. }
  263. }
  264. if(!isFound)
  265. {
  266. /* 当前对比项不在新获取的对比项中,说明需要删除 */
  267. deleteList.append(it.nID);
  268. }
  269. }
  270. }
  271. /**
  272. * @brief 处理需要删除的对比项线程
  273. * 1、先处理已经停止的线程,初始化失败的对比项会设置错误状态
  274. * 2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程
  275. *
  276. * @param deleteList
  277. */
  278. void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList<int>& deleteList, bool isDeleteAll)
  279. {
  280. if(m_mapThreads.empty())
  281. {
  282. return;
  283. }
  284. /* 判断是否是删除全部线程 */
  285. if(isDeleteAll)
  286. {
  287. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
  288. {
  289. if(it.value() == nullptr)
  290. {
  291. continue;
  292. }
  293. std::string compareItemName = it.value()->getThreadInfo().compareItemInfo.strName.toStdString();
  294. /* 设置线程停止标志,阻塞等待线程停止,然后再删除 */
  295. it.value()->thread_stop_block();
  296. delete it.value();
  297. it.value() = nullptr; // 设置为nullptr,防止悬空指针
  298. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已删除", compareItemName);
  299. }
  300. m_mapThreads.clear();
  301. return;
  302. }
  303. /* 先处理已经停止运行的线程,是上次循环停止的线程 */
  304. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end();)
  305. {
  306. BaseCalculateThread* pThread = it.value();
  307. if(pThread == nullptr)
  308. {
  309. SPDLOG_LOGGER_WARN(m_logger, "对比项线程指针为空,即将删除该线程指针");
  310. it = m_mapThreads.erase(it);
  311. continue;
  312. }
  313. if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped ||
  314. pThread->getThreadInfo().threadState == EThreadState::State_Error )
  315. {
  316. /* 确保线程已经停止 */
  317. pThread->thread_stop_block();
  318. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
  319. delete pThread;
  320. it = m_mapThreads.erase(it);
  321. continue;
  322. }
  323. ++it;
  324. }
  325. /* 停止本次需要停止的线程 */
  326. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); )
  327. {
  328. int compareItemID = it.value()->getThreadInfo().compareItemInfo.nID;
  329. if(deleteList.contains(compareItemID))
  330. {
  331. std::string compareItemName = it.value()->getThreadInfo().compareItemInfo.strName.toStdString();
  332. /* 设置线程停止标志,阻塞等待线程停止,然后再删除 */
  333. it.value()->thread_stop_block();
  334. delete it.value();
  335. it.value() = nullptr; // 设置为nullptr,防止悬空指针
  336. it = m_mapThreads.erase(it); // 从列表中删除
  337. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已删除", compareItemName);
  338. }else {
  339. ++it;
  340. }
  341. }
  342. }
  343. /* 更新正在运行的线程信息 */
  344. void ThreadCompareItemManager::updateRunningThreads(const QList<CompareItemInfo_t>& updateList)
  345. {
  346. if(updateList.isEmpty())
  347. {
  348. return;
  349. }
  350. for(const CompareItemInfo_t& item : updateList)
  351. {
  352. auto it = m_mapThreads.find(item.nID);
  353. if(it == m_mapThreads.end())
  354. {
  355. SPDLOG_LOGGER_WARN(m_logger, "对比项线程 {} 不存在,无法更新信息", item.strName.toStdString());
  356. continue;
  357. }
  358. BaseCalculateThread* pThread = it.value();
  359. if(pThread == nullptr)
  360. {
  361. continue;
  362. }
  363. CalculateThreadInfo_t threadInfo;
  364. threadInfo.compareItemInfo = item;
  365. pThread->updateThreadInfo(threadInfo);
  366. }
  367. }
  368. /* 创建新的线程 */
  369. bool ThreadCompareItemManager::createNewCompareItemThreads(const QList<CompareItemInfo_t>& createList)
  370. {
  371. if(createList.isEmpty())
  372. {
  373. // SPDLOG_LOGGER_DEBUG(m_logger, "没有新的对比项需要创建");
  374. return true;
  375. }
  376. for(auto& it : createList)
  377. {
  378. /* 创建新的对比项线程 */
  379. CalculateThreadInfo_t threadInfo;
  380. threadInfo.compareItemInfo = it;
  381. threadInfo.threadType = EThreadType::Type_CompareItem;
  382. threadInfo.threadState.store(EThreadState::State_Inited);
  383. CPPTP.add_task(&ThreadCompareItemManager::thread_compareItem, threadInfo);
  384. /* 创建线程对象 */
  385. // CompareItemThread* pThread = new CompareItemThread(threadInfo);
  386. // if(pThread == nullptr)
  387. // {
  388. // SPDLOG_LOGGER_ERROR(m_logger, "创建对比项线程 {} 失败", it.strName.toStdString());
  389. // return false;
  390. // }
  391. /* 启动线程 */
  392. // CPPTP.add_task(&CompareItemThread::threadTask, pThread);
  393. /* 添加到线程列表中 */
  394. // m_mapThreads.insert(it.nID, pThread);
  395. }
  396. return true;
  397. }
  398. /* 处理检测时段信息
  399. 设置检测时段信息有两种方式
  400. 1、某个对比项的检测计划更新了,会主动将这个对比项计划设置过去
  401. 2、某个对比项刚刚启动,设置标志位需要设置这个计划,则将当前的计划设置过去
  402. */
  403. void ThreadCompareItemManager::processDetectPeriodInfo()
  404. {
  405. QMap<int, DetectPeriodConfig_t> mapUpdateDetectConfig;
  406. /* 获取计划信息,10秒获取一次 */
  407. if(m_currentTime.toSecsSinceEpoch() - m_latestDetectPeriod.toSecsSinceEpoch() > 10)
  408. {
  409. QMap<int, DetectPeriodConfig_t> mapNewDetectConfig;
  410. if(!m_fromWebAPI.getDetectPeriodConfig(mapNewDetectConfig))
  411. {
  412. SPDLOG_LOGGER_ERROR(m_logger, "获取检测时段配置失败");
  413. return;
  414. }
  415. checkDetectPeriodInfo(m_mapDetectPeriod, mapNewDetectConfig, mapUpdateDetectConfig);
  416. /* 更新当前检测时段信息 */
  417. m_mapDetectPeriod = mapNewDetectConfig;
  418. m_latestDetectPeriod = m_currentTime;
  419. }
  420. /* 更新检测时段 */
  421. for(const auto& it : mapUpdateDetectConfig)
  422. {
  423. auto threadIt = m_mapThreads.find(it.nID);
  424. if(threadIt != m_mapThreads.end())
  425. {
  426. /* 找到对应的对比项线程,更新检测时段 */
  427. CompareItemThread* pThread = dynamic_cast<CompareItemThread*>(threadIt.value());
  428. if(pThread != nullptr)
  429. {
  430. pThread->setDetectPeriod(it);
  431. SPDLOG_LOGGER_TRACE(m_logger, "更新对比项 {} 的检测时段", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
  432. }
  433. }
  434. }
  435. /* 设置需要计划的对比项 */
  436. for(auto& pThread : m_mapThreads)
  437. {
  438. if(pThread != nullptr && !pThread->isHadDetectPlan())
  439. {
  440. /* 找到这个对比项的计划 */
  441. auto detectPlan = m_mapDetectPeriod.find(pThread->getThreadInfo().compareItemInfo.nID);
  442. if(detectPlan != m_mapDetectPeriod.end())
  443. {
  444. pThread->setDetectPeriod(detectPlan.value());
  445. }
  446. }
  447. }
  448. }
  449. /* 检查获取出更新的对比项信息 */
  450. void ThreadCompareItemManager::checkDetectPeriodInfo(QMap<int, DetectPeriodConfig_t>& nowDetectInfo, QMap<int, DetectPeriodConfig_t> newDetectInfo, QMap<int, DetectPeriodConfig_t>& updateList)
  451. {
  452. for(const auto& it : newDetectInfo)
  453. {
  454. int compareItemID = it.nID;
  455. bool isFound = false;
  456. for(const auto& existingItem : nowDetectInfo)
  457. {
  458. if(existingItem.nID == compareItemID)
  459. {
  460. isFound = true;
  461. /* 已经存在的对比项,检查是否需要更新 */
  462. if(existingItem == it)
  463. {
  464. /* 对比项信息相同,不需要更新 */
  465. continue;
  466. } else
  467. {
  468. /* 对比项信息不同,需要更新 */
  469. updateList.insert(compareItemID, it);
  470. }
  471. return;
  472. }
  473. }
  474. if(isFound == false)
  475. {
  476. /* 新对比项,添加到更新列表 */
  477. updateList.insert(compareItemID, it);
  478. }
  479. }
  480. }
  481. /* 更新对比项信息到MQTT */
  482. void ThreadCompareItemManager::updateCompareItemInfoToMQTT()
  483. {
  484. QMap<int, CompareItemInfo_t> newMap;
  485. /* 获取当前的对比项信息 */
  486. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
  487. {
  488. BaseCalculateThread* pThread = it.value();
  489. if(pThread == nullptr)
  490. {
  491. continue;
  492. }
  493. /* 获取对比项信息 */
  494. CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo;
  495. newMap.insert(itemInfo.nID, itemInfo);
  496. }
  497. /* 和之前的对比,对比项是否有更新,有更新则发送 */
  498. bool isUpdated = false;
  499. if(newMap.size() != m_mapMQTTItemInfo.size())
  500. {
  501. isUpdated = true;
  502. } else
  503. {
  504. /* 进一步对比相信信息 */
  505. for(const auto& newItem : newMap)
  506. {
  507. auto nowIt = m_mapMQTTItemInfo.find(newItem.nID);
  508. if(nowIt == m_mapMQTTItemInfo.end())
  509. {
  510. isUpdated = true;
  511. break;
  512. }
  513. /* 比较对比项通道数量和对比项名称 */
  514. if(nowIt.value().strName != newItem.strName || nowIt.value().mapRoad.size() != newItem.mapRoad.size())
  515. {
  516. isUpdated = true;
  517. break;
  518. }
  519. /* 挨个比较对比项通道信息 */
  520. for(const auto& road : newItem.mapRoad)
  521. {
  522. auto roadIt = nowIt.value().mapRoad.find(road.nCompareRoadNum);
  523. if(roadIt == nowIt.value().mapRoad.end() || roadIt.value().strCompareRoadName != road.strCompareRoadName)
  524. {
  525. isUpdated = true;
  526. break;
  527. }
  528. }
  529. }
  530. }
  531. /* 服务启动,可能对比项是空的,上面检查结果为false,但是也需要发送一次清空对比项 */
  532. if(isUpdated || m_isOneSend.load())
  533. {
  534. sendCompareItemInfoToMQTT(newMap);
  535. m_mapMQTTItemInfo = newMap;
  536. }
  537. m_isOneSend.store(false);
  538. }
  539. /* 发送到MQTT */
  540. void ThreadCompareItemManager::sendCompareItemInfoToMQTT(const QMap<int, CompareItemInfo_t>& mapCompareItem)
  541. {
  542. /* 生成发送的json文件 */
  543. nJson jsonArray = nJson::array();
  544. for(const auto& it : mapCompareItem)
  545. {
  546. /* 判断这个对比项是否启用,不启用就跳过 */
  547. if(it.isEnable == false)
  548. {
  549. continue;
  550. }
  551. nJson jsonItem;
  552. /* 对比项ID */
  553. jsonItem["compareItem_id"] = it.nID;
  554. /* 对比项名称 */
  555. jsonItem["compareItem_name"] = it.strName.toStdString();
  556. nJson josnItemRoads = nJson::array();
  557. for(const auto& road : it.mapRoad)
  558. {
  559. nJson jsonRoad;
  560. /* 对比项通道编号和名称 */
  561. jsonRoad["road_num"] = road.nCompareRoadNum;
  562. jsonRoad["road_name"] = road.strCompareRoadName.toStdString();
  563. /* 通道使用的声卡编号 */
  564. // jsonRoad["sound_card_num"] = road.scRoadInfo.nSoundCardNum;
  565. // jsonRoad["sound_card_road_num"] = road.scRoadInfo.roadInfo.nRoadNum;
  566. josnItemRoads.push_back(jsonRoad);
  567. }
  568. jsonItem["compareItem_roads"] = josnItemRoads;
  569. // /* 静音条件 */
  570. // jsonItem["silence_switch"] = it.paramMute.isEnable;
  571. // jsonItem["silence_threshold"] = it.paramMute.threshold.nThreshold;
  572. // jsonItem["silence_duration"] = it.paramMute.nLen;
  573. // jsonItem["silence_sensitivity"] = it.paramMute.nSensitivity;
  574. // /* 过载条件 */
  575. // jsonItem["overload_switch"] = it.paramOverload.isEnable;
  576. // jsonItem["overload_threshold"] = it.paramOverload.threshold.nThreshold;
  577. // jsonItem["overload_duration"] = it.paramOverload.nLen;
  578. // jsonItem["overload_sensitivity"] = it.paramOverload.nSensitivity;
  579. // /* 反相条件 */
  580. // jsonItem["reverse_switch"] = it.paramPhase.isEnable;
  581. // jsonItem["reverse_threshold"] = it.paramPhase.threshold.dThreshold;
  582. // jsonItem["reverse_duration"] = it.paramPhase.nLen;
  583. // jsonItem["reverse_sensitivity"] = it.paramPhase.nSensitivity;
  584. jsonArray.push_back(jsonItem);
  585. }
  586. /* 发送到MQTT */
  587. if(m_pFromMQTT->connectState() == QMQTT::ConnectionState::STATE_CONNECTED)
  588. {
  589. QByteArray jsonData = QByteArray::fromStdString(jsonArray.dump());
  590. if(!m_pFromMQTT->sendMessage(m_pubTopic, jsonData, 0, true))
  591. {
  592. SPDLOG_LOGGER_WARN(m_logger, "ThreadCompareItemManager: 发送对比项信息到MQTT失败");
  593. }else
  594. {
  595. SPDLOG_LOGGER_TRACE(m_logger, "ThreadCompareItemManager: 发送对比项信息到MQTT成功");
  596. }
  597. } else
  598. {
  599. SPDLOG_LOGGER_WARN(m_logger, "m_pFromMQTT 未连接到服务器,无法发送");
  600. }
  601. }
  602. /* 初始化MQTT */
  603. void ThreadCompareItemManager::initMQTT()
  604. {
  605. if(m_pFromMQTT == nullptr)
  606. {
  607. m_pFromMQTT = new FromMQTT();
  608. if(m_pFromMQTT == nullptr)
  609. {
  610. SPDLOG_LOGGER_ERROR(m_logger, "创建MQTT对象失败");
  611. return;
  612. }
  613. }
  614. /* 登陆MQTT */
  615. m_pFromMQTT->setIPAndPort(GInfo.mqttIP(), GInfo.mqttPort());
  616. // m_pFromMQTT->addSubcribe("LH_WEBINFO");
  617. m_pFromMQTT->setAutoReconnect(true);
  618. // m_pFromMQTT->connectToServer();
  619. // connect(m_pFromMQTT, &FromMQTT::signal_recvMessage, [this](const QMQTT::Message& message) {
  620. // SPDLOG_LOGGER_WARN(m_logger, "--------------------- 接收到MQTT消息: {}", message.topic().toStdString());
  621. // SPDLOG_LOGGER_WARN(m_logger, "消息内容: {}", message.payload().toStdString());
  622. // });
  623. SPDLOG_LOGGER_INFO(m_logger, "☆ 连接MQTT服务器: {}:{}, 对比项信息订阅主题: {}", GInfo.mqttIP().toStdString(), GInfo.mqttPort(), m_pubTopic.toStdString());
  624. }