CompareItemThread.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. #include "CompareItemThread.h"
  2. #include "FromMQTT.h"
  3. #include "GlobalInfo.h"
  4. #include "ThreadManager.h"
  5. #include "CalculateDBThread.h"
  6. #include "NoiseDetectThread.h"
  7. #include "CompareDoubleThread.h"
  8. #include "ThreadPool.h"
  9. #include "commonDefine.h"
  10. #include "ThreadAlarmManager.h"
  11. #include "spdlog.h"
  12. #include <qdatetime.h>
  13. CompareItemThread::CompareItemThread(CalculateThreadInfo_t& threadInfo)
  14. : QObject(nullptr), BaseCalculateThread(threadInfo)
  15. {
  16. }
  17. CompareItemThread::~CompareItemThread()
  18. {
  19. }
  20. /* 重写父类的线程函数,这里重新实现 */
  21. void CompareItemThread::threadTask()
  22. {
  23. m_logBase = fmt::format("对比项: {}", m_threadInfo.compareItemInfo.strName.toStdString());
  24. SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
  25. SPDLOG_LOGGER_INFO(m_logger, "{} 线程开始运行, 对比通道: ", m_logBase);
  26. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  27. {
  28. SPDLOG_LOGGER_INFO(m_logger, " 通道名称: {}, 通道编号: {}, 声卡通道: {}:{}",
  29. road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
  30. }
  31. SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
  32. /* 初始化数据 */
  33. if(!initData())
  34. {
  35. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
  36. return;
  37. }
  38. /* 更新线程状态标志 */
  39. m_threadInfo.threadState = EThreadState::State_Running;
  40. m_isStop = false;
  41. m_pTimer = new QTimer();
  42. if(m_pTimer == nullptr)
  43. {
  44. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建定时器失败", m_logBase);
  45. }
  46. // SPDLOG_LOGGER_WARN(m_logger, "{} 创建定时器成功,开启定时器", m_logBase);
  47. m_pTimer->setTimerType(Qt::PreciseTimer);
  48. m_pTimer->setSingleShot(false); // 设置为非单次定时器
  49. m_pTimer->setInterval(50);
  50. m_eventLoop.connect(m_pTimer, &QTimer::timeout, this, &CompareItemThread::do_timeout);
  51. m_pTimer->start();
  52. /* 开启事件循环 */
  53. m_eventLoop.exec();
  54. /* 等待 */
  55. // std::this_thread::sleep_for(std::chrono::seconds(20));
  56. /* 线程结束,清理数据 */
  57. clearData();
  58. m_threadInfo.threadState = EThreadState::State_Stopped;
  59. m_isStop = true;
  60. SPDLOG_LOGGER_WARN(m_logger, "★ {} 线程结束运行", m_logBase);
  61. }
  62. /* 停止线程函数 */
  63. void CompareItemThread::stopThread()
  64. {
  65. if(m_pTimer != nullptr)
  66. {
  67. if(m_pTimer->isActive())
  68. {
  69. m_pTimer->stop();
  70. }
  71. disconnect(m_pTimer, &QTimer::timeout, this, &CompareItemThread::do_timeout);
  72. delete m_pTimer;
  73. m_pTimer = nullptr;
  74. }
  75. /* 停止事件循环 */
  76. m_eventLoop.quit();
  77. }
  78. void CompareItemThread::stopThreadBlock()
  79. {
  80. stopThread();
  81. while(!m_isStop) // 等待线程停止
  82. {
  83. std::this_thread::sleep_for(std::chrono::milliseconds(1));
  84. }
  85. }
  86. /* 设置检测时段 */
  87. void CompareItemThread::setDetectPeriod(const DetectPeriodConfig_t& detectPeriod)
  88. {
  89. std::lock_guard<std::mutex> lock(m_mutexDetectPeriod);
  90. if(detectPeriod.nID != m_detectPeriod.nID)
  91. {
  92. SPDLOG_LOGGER_ERROR(m_logger, "{} 设置检测时段失败,ID不匹配: {}, 当前ID: {}", m_logBase, detectPeriod.nID, m_detectPeriod.nID);
  93. return;
  94. }
  95. m_detectPeriod = detectPeriod;
  96. // m_isDetectPeriodUpdated = true; // 标记检测时段已更新
  97. }
  98. /* 线程功能函数 */
  99. void CompareItemThread::task()
  100. {
  101. m_logBase = fmt::format("对比项: {}", m_threadInfo.compareItemInfo.strName.toStdString());
  102. SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
  103. SPDLOG_LOGGER_INFO(m_logger, "{} 线程开始运行, 对比通道: ", m_logBase);
  104. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  105. {
  106. SPDLOG_LOGGER_INFO(m_logger, " 通道名称: {}, 通道编号: {}, 声卡通道: {}:{}",
  107. road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum);
  108. }
  109. SPDLOG_LOGGER_INFO(m_logger, "----------------------------------------------------------------");
  110. /* 初始化数据 */
  111. if(!initData())
  112. {
  113. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase);
  114. return;
  115. }
  116. // SPDLOG_LOGGER_WARN(m_logger, "{} 初始化数据完成,开始对比检测, isRunning: {}", m_logBase, m_isRunning.load());
  117. while (m_isRunning)
  118. {
  119. /* 睡眠100ms */
  120. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  121. /* -------------------------------------------------------------------------------------
  122. * 更新对比项信息
  123. * ------------------------------------------------------------------------------------- */
  124. if(updateThreadInfoInternal())
  125. {
  126. SPDLOG_LOGGER_INFO(m_logger, "{} 暂停对比检测,更新对比项信息");
  127. m_threadInfo.compareItemInfo = m_threadInfoNew.compareItemInfo;
  128. initData();
  129. SPDLOG_LOGGER_INFO(m_logger, "{} 更新对比项信息完成,继续检测对比");
  130. }
  131. /* -------------------------------------------------------------------------------------
  132. * 更新数据
  133. * ------------------------------------------------------------------------------------- */
  134. if(!updateResultData())
  135. {
  136. continue;
  137. // return;
  138. }
  139. /* -------------------------------------------------------------------------------------
  140. * 处理数据,将报警信息给写报警数据的线程
  141. * ------------------------------------------------------------------------------------- */
  142. // processAlarmData();
  143. /* -------------------------------------------------------------------------------------
  144. * 将音量包数据发送到MQTT中
  145. * ------------------------------------------------------------------------------------- */
  146. sendResultData();
  147. /* 清除标志位 */
  148. clearUpdateFlags();
  149. SPDLOG_LOGGER_WARN(m_logger, "{} 发送对比项数据到MQTT中", m_logBase);
  150. }
  151. /* 清理数据 */
  152. clearData();
  153. SPDLOG_LOGGER_WARN(m_logger, "★ {} 线程结束运行", m_logBase);
  154. }
  155. /* 定时器任务 */
  156. void CompareItemThread::timerTask()
  157. {
  158. /* -------------------------------------------------------------------------------------
  159. * 更新对比项信息
  160. * ------------------------------------------------------------------------------------- */
  161. if(updateThreadInfoInternal())
  162. {
  163. SPDLOG_LOGGER_INFO(m_logger, "{} 暂停对比检测,更新对比项信息");
  164. m_threadInfo.compareItemInfo = m_threadInfoNew.compareItemInfo;
  165. initData();
  166. SPDLOG_LOGGER_INFO(m_logger, "{} 更新对比项信息完成,继续检测对比");
  167. }
  168. /* 判断检测时段 */
  169. if(!checkDetectPeriod())
  170. {
  171. // 不在检测时段内,不进行对比检测
  172. // SPDLOG_LOGGER_WARN(m_logger, "{} 当前不在检测时段内,停止对比检测", m_logBase);
  173. return;
  174. }
  175. /* -------------------------------------------------------------------------------------
  176. * 更新数据
  177. * ------------------------------------------------------------------------------------- */
  178. if(!updateResultData())
  179. {
  180. return;
  181. }
  182. /* -------------------------------------------------------------------------------------
  183. * 处理数据,将报警信息给写报警数据的线程,直接由各个计算线程直接写入
  184. * ------------------------------------------------------------------------------------- */
  185. // processAlarmData();
  186. /* -------------------------------------------------------------------------------------
  187. * 将音量包数据发送到MQTT中
  188. * ------------------------------------------------------------------------------------- */
  189. sendResultData();
  190. /* 清除标志位 */
  191. clearUpdateFlags();
  192. // SPDLOG_LOGGER_WARN(m_logger, "{} 发送对比项数据到MQTT中", m_logBase);
  193. }
  194. /* 初始化数据 */
  195. bool CompareItemThread::initData()
  196. {
  197. /* 创建录音通道线程 */
  198. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  199. {
  200. ThreadMan.createRecordThread(road.scRoadInfo, m_threadInfo.compareItemInfo.nID);
  201. }
  202. /* 创建计算音量报警信息的线程指针 */
  203. destroyCalculateDBThreads(); // 清理之前的线程
  204. createCalculateDBThreads();
  205. /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
  206. destroyCompareThreads();
  207. createCompareThreads();
  208. /* 获取计算噪音的线程 */
  209. destroyNoiseDetectThreads();
  210. createNoiseDetectThreads();
  211. /* 初始化存储结果的数据结构 */
  212. m_compareResult = CompareResult_t();
  213. m_compareResult.compareItemID = m_threadInfo.compareItemInfo.nID;
  214. m_compareResult.compareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
  215. m_compareResult.dateTime = QDateTime::currentDateTime();
  216. m_compareResult.isClientAlarm = false; // 默认不报警
  217. m_compareResult.mapRoadVolumes.clear(); // 清空之前的数据
  218. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  219. {
  220. OneRoadVolume_t oneRoadVolume;
  221. oneRoadVolume.roadInfo = road; // 设置通道信息
  222. oneRoadVolume.dateTime = QDateTime::currentDateTime(); // 初始化时间
  223. m_compareResult.mapRoadVolumes.insert({road.nCompareRoadNum, oneRoadVolume});
  224. }
  225. m_mapCDBUpdated.clear();
  226. for(auto it : m_threadInfo.compareItemInfo.mapRoad)
  227. {
  228. m_mapCDBUpdated.insert({it.nCompareRoadNum, false}); // 初始化更新标志位为false
  229. }
  230. /* 初始化报警信息 */
  231. // m_mapAlarmSilence.clear();
  232. // m_mapAlarmOverload.clear();
  233. // m_mapAlarmPhase.clear();
  234. // for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  235. // {
  236. // m_mapAlarmSilence.insert({road.nCompareRoadNum, AlarmInfo_t()});
  237. // m_mapAlarmOverload.insert({road.nCompareRoadNum, AlarmInfo_t()});
  238. // m_mapAlarmPhase.insert({road.nCompareRoadNum, AlarmInfo_t()});
  239. // }
  240. // m_mapAlarmSilenceLast.clear();
  241. // m_mapAlarmOverloadLast.clear();
  242. // m_mapAlarmPhaseLast.clear();
  243. // for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  244. // {
  245. // m_mapAlarmSilenceLast.insert({road.nCompareRoadNum, AlarmInfo_t()});
  246. // m_mapAlarmOverloadLast.insert({road.nCompareRoadNum, AlarmInfo_t()});
  247. // m_mapAlarmPhaseLast.insert({road.nCompareRoadNum, AlarmInfo_t()});
  248. // }
  249. return true;
  250. }
  251. /* 清理数据 */
  252. void CompareItemThread::clearData()
  253. {
  254. /* 停止所有的比对线程 */
  255. destroyCompareThreads();
  256. /* 销毁音量报警线程 */
  257. destroyCalculateDBThreads();
  258. /* 移除噪音检测线程 */
  259. // removeNoiseDetectThreads();
  260. destroyNoiseDetectThreads();
  261. /* 移除使用到的录音通道 */
  262. for(auto& it : m_threadInfo.compareItemInfo.mapRoad)
  263. {
  264. SoundCardRoadInfo_t roadInfo = it.scRoadInfo;
  265. if(!ThreadMan.removeRecordThread(roadInfo, m_threadInfo.compareItemInfo.nID))
  266. {
  267. SPDLOG_LOGGER_ERROR(m_logger, "{} 移除录音通道 {}:{} 失败", m_logBase, roadInfo.strSoundCardName.toStdString(), roadInfo.roadInfo.nRoadNum);
  268. }
  269. }
  270. if(m_pFromMQTT != nullptr)
  271. {
  272. delete m_pFromMQTT; // 删除MQTT对象
  273. m_pFromMQTT = nullptr; // 设置为nullptr
  274. }
  275. }
  276. /* 定时器槽函数 */
  277. void CompareItemThread::do_timeout()
  278. {
  279. // SPDLOG_LOGGER_WARN(m_logger, "{} 定时器触发,开始执行定时任务", m_logBase);
  280. if(m_pFromMQTT == nullptr)
  281. {
  282. initMQTT();
  283. }
  284. timerTask();
  285. }
  286. /* 初始化MQTT */
  287. void CompareItemThread::initMQTT()
  288. {
  289. if(m_pFromMQTT == nullptr)
  290. {
  291. m_pFromMQTT = new FromMQTT();
  292. if(m_pFromMQTT == nullptr)
  293. {
  294. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建MQTT对象失败", m_logBase);
  295. return; // 创建MQTT对象失败
  296. }
  297. }
  298. /* 登陆MQTT */
  299. m_pFromMQTT->setIPAndPort(GInfo.mqttIP(), GInfo.mqttPort());
  300. m_pFromMQTT->connectToServer();
  301. m_pubTopic = QString("%1/%2").arg(GInfo.mqttPubTopicDB()).arg(QString::number(m_threadInfo.compareItemInfo.nID));
  302. SPDLOG_LOGGER_INFO(m_logger, "☆ {} 连接MQTT服务器: {}:{}, 音量包订阅主题: {}", m_logBase, GInfo.mqttIP().toStdString(), GInfo.mqttPort(), m_pubTopic.toStdString());
  303. }
  304. /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
  305. bool CompareItemThread::createCompareThreads()
  306. {
  307. auto it = m_threadInfo.compareItemInfo.mapRoad.begin();
  308. auto mainRoad = it.value(); // 主通道信息
  309. it++; // 移动到下一个通道
  310. // uint64_t size = m_threadInfo.compareItemInfo.mapRoad.size();
  311. for(; it != m_threadInfo.compareItemInfo.mapRoad.end(); it++)
  312. {
  313. CalculateThreadInfo_t compareThreadInfo;
  314. compareThreadInfo.compareItemInfo = m_threadInfo.compareItemInfo;
  315. compareThreadInfo.compareItemInfo.mapRoad.clear(); // 清空通道信息
  316. compareThreadInfo.compareItemInfo.mapRoad.insert(mainRoad.nCompareRoadNum, mainRoad); // 添加主通道
  317. compareThreadInfo.compareItemInfo.mapRoad.insert(it.key(), it.value()); // 添加当前通道
  318. compareThreadInfo.threadState = EThreadState::State_Inited;
  319. CompareDoubleThread* pThread = new CompareDoubleThread(compareThreadInfo);
  320. if(pThread == nullptr)
  321. {
  322. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建对比线程 {} - {} 失败", m_logBase, mainRoad.strCompareRoadName.toStdString(), it.value().strCompareRoadName.toStdString());
  323. return false;
  324. }
  325. m_mapCompareDoubleThreads.insert({it.key(), pThread}); // 保存线程指针
  326. /* 开始运行 */
  327. CPPTP.add_task(&CompareDoubleThread::threadTask, pThread);
  328. }
  329. return true;
  330. }
  331. /* 销毁两两对比线程 */
  332. void CompareItemThread::destroyCompareThreads()
  333. {
  334. if(m_mapCompareDoubleThreads.size() == 0)
  335. {
  336. return; // 没有对比线程
  337. }
  338. SPDLOG_LOGGER_INFO(m_logger, "{} 销毁对比线程", m_logBase);
  339. for(auto& pair : m_mapCompareDoubleThreads)
  340. {
  341. if(pair.second != nullptr)
  342. {
  343. pair.second->stopThreadBlock(); // 停止线程
  344. delete pair.second; // 删除线程
  345. pair.second = nullptr; // 设置为nullptr
  346. }
  347. }
  348. m_mapCompareDoubleThreads.clear();
  349. m_mapCDBUpdated.clear(); // 清空更新标志位
  350. SPDLOG_LOGGER_INFO(m_logger, "{} 对比线程销毁完成", m_logBase);
  351. }
  352. /* 创建计算音量报警的线程 */
  353. bool CompareItemThread::createCalculateDBThreads()
  354. {
  355. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  356. {
  357. CalculateThreadInfo_t threadInfo;
  358. threadInfo.compareItemInfo.mapRoad.clear(); // 清空通道信息
  359. threadInfo.compareItemInfo.mapRoad.insert(road.nCompareRoadNum, road); // 添加当前通道
  360. threadInfo.threadState = EThreadState::State_Inited; // 初始化线程状态
  361. threadInfo.threadType = EThreadType::Type_CalculateDB;
  362. CalculateDBThread* pThread = new CalculateDBThread(threadInfo);
  363. if(pThread == nullptr)
  364. {
  365. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建音量计算线程失败", m_logBase);
  366. // return false; // 获取线程失败
  367. }
  368. CPPTP.add_task(&CalculateDBThread::threadTask, pThread);
  369. m_mapCalculateDBThreads.insert({road.nCompareRoadNum, pThread}); // 保存线程指针
  370. }
  371. return true;
  372. }
  373. /* 销毁音量计算的线程 */
  374. void CompareItemThread::destroyCalculateDBThreads()
  375. {
  376. if(m_mapCalculateDBThreads.size() == 0)
  377. {
  378. return; // 没有音量计算线程
  379. }
  380. SPDLOG_LOGGER_INFO(m_logger, "{} 销毁音量计算线程", m_logBase);
  381. for(auto& pair : m_mapCalculateDBThreads)
  382. {
  383. if(pair.second != nullptr)
  384. {
  385. pair.second->stopThreadBlock(); // 停止线程
  386. delete pair.second; // 删除线程
  387. pair.second = nullptr; // 设置为nullptr
  388. }
  389. }
  390. m_mapCalculateDBThreads.clear();
  391. m_mapCDBUpdated.clear(); // 清空更新标志位
  392. SPDLOG_LOGGER_INFO(m_logger, "{} 音量计算线程销毁完成", m_logBase);
  393. }
  394. /* 创建噪音检测线程 */
  395. void CompareItemThread::createNoiseDetectThreads()
  396. {
  397. for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  398. {
  399. CalculateThreadInfo_t threadInfo;
  400. threadInfo.compareItemInfo.mapRoad.clear(); // 清空通道信息
  401. threadInfo.compareItemInfo.mapRoad.insert(road.nCompareRoadNum, road); // 添加当前通道
  402. threadInfo.threadState = EThreadState::State_Inited; // 初始化线程状态
  403. threadInfo.threadType = EThreadType::Type_CalculateDB;
  404. NoiseDetectThread* pThread = new NoiseDetectThread(threadInfo);
  405. if(pThread == nullptr)
  406. {
  407. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建噪音检测线程失败", m_logBase);
  408. return; // 获取线程失败
  409. }
  410. m_mapNoiseDetectThreads.insert({road.nCompareRoadNum, pThread});
  411. }
  412. }
  413. /* 销毁噪音检测线程 */
  414. void CompareItemThread::destroyNoiseDetectThreads()
  415. {
  416. if(m_mapNoiseDetectThreads.size() == 0)
  417. {
  418. return; // 没有噪音检测线程
  419. }
  420. SPDLOG_LOGGER_INFO(m_logger, "{} 销毁噪音检测线程", m_logBase);
  421. for(auto& pair : m_mapNoiseDetectThreads)
  422. {
  423. if(pair.second != nullptr)
  424. {
  425. pair.second->stopThreadBlock(); // 停止线程
  426. delete pair.second; // 删除线程
  427. pair.second = nullptr; // 设置为nullptr
  428. }
  429. }
  430. m_mapNoiseDetectThreads.clear();
  431. SPDLOG_LOGGER_INFO(m_logger, "{} 噪音检测线程销毁完成", m_logBase);
  432. }
  433. /* 获取噪音检测的线程 */
  434. // bool CompareItemThread::getNoiseDetectThreads()
  435. // {
  436. // for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
  437. // {
  438. // NoiseDetectThread* pThread = ThreadMan.getNoiseDetectThread(road.scRoadInfo, m_threadInfo.compareItemInfo.nID);
  439. // if(pThread == nullptr)
  440. // {
  441. // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取噪音检测线程失败", m_logBase);
  442. // return false; // 获取线程失败
  443. // }
  444. // /* 向噪音检测线程写入对比项通道信息 */
  445. // pThread->startCompareItemNoiseAlarm(m_threadInfo.compareItemInfo.nID, m_threadInfo.compareItemInfo.strName, road);
  446. // m_mapNoiseDetectThreads.insert({road.nCompareRoadNum, pThread});
  447. // }
  448. // return true;
  449. // }
  450. /* 移除噪音检测的线程 */
  451. // void CompareItemThread::removeNoiseDetectThreads()
  452. // {
  453. // if(m_mapNoiseDetectThreads.size() == 0)
  454. // {
  455. // return; // 没有噪音检测线程
  456. // }
  457. // SPDLOG_LOGGER_INFO(m_logger, "{} 移除噪音检测线程", m_logBase);
  458. // for(auto& pair : m_mapNoiseDetectThreads)
  459. // {
  460. // if(pair.second != nullptr)
  461. // {
  462. // ThreadMan.removeNoiseDetectThread(pair.second->getRoadInfo(), m_threadInfo.compareItemInfo.nID);
  463. // }
  464. // }
  465. // m_mapNoiseDetectThreads.clear();
  466. // SPDLOG_LOGGER_INFO(m_logger, "{} 噪音检测线程移除完成", m_logBase);
  467. // }
  468. /**
  469. * @brief 更新数据
  470. * 更新数据逻辑:
  471. * 1、先从音量计算线程获取最新的音量包信息,如果没有全部更新,则等待下次获取,不进行后面的操作
  472. * 2、获取噪音检测线程的噪音信息和获取一致性信息的线程的结果无需关系是否是最新的
  473. *
  474. */
  475. bool CompareItemThread::updateResultData()
  476. {
  477. /* -------------------------------------------------------------------------------------
  478. * 先从音量计算数据中获取音量包信息和报警信息(静音、过载、反相)
  479. * ------------------------------------------------------------------------------------- */
  480. for(auto& pair : m_mapCDBUpdated)
  481. {
  482. if(pair.second == true)
  483. {
  484. /* 已经更新过了 */
  485. continue;
  486. }
  487. CalculateDBThread* pThread = m_mapCalculateDBThreads[pair.first];
  488. if(pThread == nullptr)
  489. {
  490. SPDLOG_LOGGER_ERROR(m_logger, "{} 音量计算线程失效", m_logBase);
  491. continue;
  492. }
  493. /* 获取最新的音量数据,包括静音、过载、反向等报警信息 */
  494. if(!pThread->getlastVolumeInfo(m_compareResult.mapRoadVolumes[pair.first]))
  495. {
  496. continue; // 没有获取到最新数据,继续等待
  497. }
  498. /* 更新报警信息 */
  499. // m_mapAlarmSilence[pair.first] = pThread->getAlarm(EAlarmType::EAT_Silent);
  500. // m_mapAlarmOverload[pair.first] = pThread->getAlarm(EAlarmType::EAT_Overload);
  501. // m_mapAlarmPhase[pair.first] = pThread->getAlarm(EAlarmType::EAT_Reversed);
  502. pair.second = true; // 设置更新标志位为true
  503. }
  504. /* 判断是否全部更新,如果没有则返回,等待下次再次获取 */
  505. for(auto& pair : m_mapCDBUpdated)
  506. {
  507. if(false == pair.second)
  508. {
  509. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 音量计算线程数据未全部更新,等待下次获取", m_logBase);
  510. return false;
  511. }
  512. }
  513. /* -------------------------------------------------------------------------------------
  514. * 获取噪音计算的结果(从噪音对比线程中获取)
  515. * ------------------------------------------------------------------------------------- */
  516. for(auto& pair : m_mapNoiseDetectThreads)
  517. {
  518. NoiseDetectThread* pThread = pair.second;
  519. if(pThread == nullptr)
  520. {
  521. SPDLOG_LOGGER_ERROR(m_logger, "{} 噪音检测线程失效", m_logBase);
  522. continue; // 跳过这个线程
  523. }
  524. /* 获取最新的噪音数据,噪音报警那个标志位貌似没用到 */
  525. m_compareResult.mapRoadVolumes[pair.first].isNoise = pThread->isNoise();
  526. }
  527. /* -------------------------------------------------------------------------------------
  528. * 从对比项中获取核对过后的一致性结果
  529. * ------------------------------------------------------------------------------------- */
  530. for(auto& pair : m_mapCompareDoubleThreads)
  531. {
  532. CompareDoubleThread* pThread = pair.second;
  533. if(pThread == nullptr)
  534. {
  535. SPDLOG_LOGGER_ERROR(m_logger, "{} 一致性对比线程失效", m_logBase);
  536. continue;
  537. }
  538. /* 获取最新的一致性结果 */
  539. OneRoadVolume_t roadVolume;
  540. if(pThread->getlastResult(roadVolume))
  541. {
  542. m_compareResult.mapRoadVolumes[pair.first].isConsistency = roadVolume.isConsistency;
  543. m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = roadVolume.isNotConsistencyWarning;
  544. }
  545. }
  546. return true;
  547. }
  548. /**
  549. 处理报警数据,现在的报警信息都是实时的,不再是报警结束后得到的数据了
  550. 处理逻辑:
  551. 1、如果是开始报警了,将报警信息发送给录制报警文件的线程,开始录音
  552. 2、如果是结束报警了,将报警结束信息再次通知录制报警文件的线程,结束录音
  553. 然后将报警信息发送给写入数据库的线程,写入到数据库中
  554. 3、静音、过载、反相报警信息直接从计算音量的线程中获取,一致性报警从对比项线程中获取,
  555. 噪音报警从噪音检测线程中获取
  556. */
  557. // void CompareItemThread::processAlarmData()
  558. // {
  559. // m_listWriteAlarm.clear();
  560. // /* 处理静音报警数据 */
  561. // for(auto& pair : m_mapAlarmSilence)
  562. // {
  563. // auto& nowAlarm = pair.second;
  564. // auto& lastAlarm = m_mapAlarmSilenceLast[pair.first];
  565. // if(nowAlarm.isAlarm)
  566. // {
  567. // if(lastAlarm == nowAlarm)
  568. // {
  569. // continue; // 和上次的报警信息一样,不需要处理
  570. // }else {
  571. // nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
  572. // nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
  573. // m_listWriteAlarm.push_back(nowAlarm);
  574. // m_mapAlarmSilenceLast[pair.first] = nowAlarm;
  575. // }
  576. // }
  577. // }
  578. // /* 处理过载报警数据 */
  579. // for(auto& pair : m_mapAlarmOverload)
  580. // {
  581. // auto& nowAlarm = pair.second;
  582. // auto& lastAlarm = m_mapAlarmOverloadLast[pair.first];
  583. // if(nowAlarm.isAlarm)
  584. // {
  585. // if(lastAlarm == nowAlarm)
  586. // {
  587. // continue; // 和上次的报警信息一样,不需要处理
  588. // }else {
  589. // nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
  590. // nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
  591. // m_listWriteAlarm.push_back(nowAlarm);
  592. // m_mapAlarmOverloadLast[pair.first] = nowAlarm;
  593. // }
  594. // }
  595. // }
  596. // /* 处理反相报警数据 */
  597. // for(auto& pair : m_mapAlarmPhase)
  598. // {
  599. // auto& nowAlarm = pair.second;
  600. // auto& lastAlarm = m_mapAlarmPhaseLast[pair.first];
  601. // if(nowAlarm.isAlarm)
  602. // {
  603. // if(lastAlarm == nowAlarm)
  604. // {
  605. // continue; // 和上次的报警信息一样,不需要处理
  606. // }else {
  607. // nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
  608. // nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
  609. // m_listWriteAlarm.push_back(nowAlarm);
  610. // m_mapAlarmPhaseLast[pair.first] = nowAlarm;
  611. // }
  612. // }
  613. // }
  614. // /* 处理一致性报警信息 */
  615. // /* 处理噪音报警信息 */
  616. // /* 将报警列表写入到处理报警数据的线程中 */
  617. // AlarmManager.addAlarmInfo(m_listWriteAlarm);
  618. // }
  619. /* 发送数据 */
  620. void CompareItemThread::sendResultData()
  621. {
  622. if(m_pFromMQTT == nullptr)
  623. {
  624. SPDLOG_LOGGER_WARN(m_logger, "{} MQTT连接未初始化,无法发送数据", m_logBase);
  625. return;
  626. }
  627. /* 生成json数据 */
  628. QByteArray jsonData;
  629. if(!generateMQTTJsonData(m_compareResult, jsonData))
  630. {
  631. SPDLOG_LOGGER_WARN(m_logger, "{} 生成音量包 JSON数据失败", m_logBase);
  632. return;
  633. }
  634. /* 发送到mqtt中 */
  635. int errorCode = 0;
  636. if(!m_pFromMQTT->sendMessage(m_pubTopic, jsonData, 0, errorCode))
  637. {
  638. SPDLOG_LOGGER_ERROR(m_logger, "{} 发送音量包数据到 {} 失败,错误代码: {}", m_logBase, m_pubTopic.toStdString(), errorCode);
  639. }else {
  640. SPDLOG_LOGGER_DEBUG(m_logger, "{} 发送音量包数据到 {} 成功", m_logBase, m_pubTopic.toStdString());
  641. }
  642. }
  643. /* 清除标志更新位 */
  644. void CompareItemThread::clearUpdateFlags()
  645. {
  646. for(auto& pair : m_mapCDBUpdated)
  647. {
  648. pair.second = false; // 清除更新标志位
  649. }
  650. }
  651. /* 生成发送至MQTT的JSON数据 */
  652. bool CompareItemThread::generateMQTTJsonData(const CompareResult_t& compareResult, QByteArray& jsonData)
  653. {
  654. try
  655. {
  656. /* 生成基础信息 */
  657. nJson json0;
  658. json0["compareItem_id"] = compareResult.compareItemID;
  659. json0["compareItem_name"] = compareResult.compareItemName.c_str();
  660. json0["date_time"] = compareResult.dateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
  661. json0["is_client_alarm"] = compareResult.isClientAlarm;
  662. for(const auto& roadVolume : compareResult.mapRoadVolumes)
  663. {
  664. nJson json1;
  665. json1["soundCard_id"] = roadVolume.second.roadInfo.scRoadInfo.strSoundCardID.toStdString(); /* 声卡id和声卡通道id */
  666. json1["soundCard_road_id"] = roadVolume.second.roadInfo.scRoadInfo.roadInfo.nRoadNum;
  667. /* 对比项通道编号和名称 */
  668. json1["item_road_num"] = roadVolume.second.roadInfo.nCompareRoadNum;
  669. json1["item_road_name"] = roadVolume.second.roadInfo.strCompareRoadName.toStdString();
  670. json1["similarity"] = roadVolume.second.similarity;
  671. json1["is_silence"] = roadVolume.second.isSilence;
  672. json1["is_overload"] = roadVolume.second.isOverload;
  673. json1["is_reversed"] = roadVolume.second.isReversed;
  674. json1["is_noise"] = roadVolume.second.isNoise;
  675. json1["is_noise_warning"] = roadVolume.second.isNoiseWarning;
  676. json1["is_consistency"] = roadVolume.second.isConsistency;
  677. json1["is_not_consistency_warning"] = roadVolume.second.isNotConsistencyWarning;
  678. json1["left_real_time_db"] = roadVolume.second.leftRealTimeDB;
  679. json1["right_real_time_db"] = roadVolume.second.rightRealTimeDB;
  680. /* 添加音量包信息 */
  681. for(const auto& db : roadVolume.second.vecleftDB)
  682. {
  683. json1["left_db_array"].push_back(db);
  684. }
  685. for(const auto& db : roadVolume.second.vecrightDB)
  686. {
  687. json1["right_db_array"].push_back(db);
  688. }
  689. /* 添加到基础信息中 */
  690. json0["road_volumes"].push_back(json1);
  691. }
  692. /* 转换为字符串 */
  693. jsonData.clear();
  694. jsonData = QByteArray::fromStdString(json0.dump());
  695. }nJsonCatch
  696. return true;
  697. }
  698. /* 检查是否在检测时间段内,返回false,不开启检测 */
  699. bool CompareItemThread::checkDetectPeriod()
  700. {
  701. std::lock_guard<std::mutex> lock(m_mutexDetectPeriod);
  702. /* 先判断是否启用了该对比项,这个设置在对比项中设置 */
  703. if(!m_threadInfo.compareItemInfo.isEnable)
  704. {
  705. return false; // 对比项未启用,不进行检测
  706. }
  707. QDateTime currentTime = QDateTime::currentDateTime();
  708. int currentWeekday = currentTime.date().dayOfWeek(); // 获取当前星期几,1-7表示周日到周六
  709. /* 判断时段 */
  710. bool isInDetectPeriod = false;
  711. for(const auto& period : m_detectPeriod.listDetect)
  712. {
  713. /* 先判断是否有符合的周几 */
  714. if(static_cast<int>(period.weekType) == currentWeekday)
  715. {
  716. /* 判断当前时间是否在检测时段内 */
  717. if(currentTime.time() >= period.timeStart && currentTime.time() <= period.timeEnd)
  718. {
  719. isInDetectPeriod = true;
  720. break;
  721. }
  722. }
  723. }
  724. /* 再判断是否在非检测时间段内 */
  725. for(const auto& period : m_detectPeriod.listNoDetect)
  726. {
  727. /* 先判断日期 */
  728. if(period.date == currentTime.date())
  729. {
  730. /* 判断当前时间是否在非检测时段内 */
  731. if(currentTime.time() >= period.timeStart && currentTime.time() <= period.timeEnd)
  732. {
  733. isInDetectPeriod = false; // 在非检测时段内,不进行检测
  734. break;
  735. }
  736. }
  737. }
  738. /* 应用于对比项检测,对比项不设置日期不会进行检测 */
  739. for(auto& pThread : m_mapCompareDoubleThreads)
  740. {
  741. pThread.second->setInDetectPeriod(isInDetectPeriod);
  742. }
  743. /* 判断是否应用于静音、过载、反相检测 */
  744. for(auto& pThread : m_mapCalculateDBThreads)
  745. {
  746. if(m_detectPeriod.isApplySlient)
  747. {
  748. pThread.second->setSilenceInDetectPeriod(isInDetectPeriod);
  749. }else {
  750. /* 没有应用于静音检测,就一直检测 */
  751. pThread.second->setSilenceInDetectPeriod(true);
  752. }
  753. if(m_detectPeriod.isApplyOverload)
  754. {
  755. pThread.second->setOverloadInDetectPeriod(isInDetectPeriod);
  756. } else {
  757. /* 没有应用于过载检测,就一直检测 */
  758. pThread.second->setOverloadInDetectPeriod(true);
  759. }
  760. if(m_detectPeriod.isApplyPhase)
  761. {
  762. pThread.second->setPhaseInDetectPeriod(isInDetectPeriod);
  763. }else
  764. {
  765. /* 没有应用于反相检测,就一直检测 */
  766. pThread.second->setPhaseInDetectPeriod(true);
  767. }
  768. }
  769. /* 应用于噪音检测 */
  770. for(auto& pThread : m_mapNoiseDetectThreads)
  771. {
  772. if(m_detectPeriod.isApplyNoise)
  773. {
  774. pThread.second->setInDetectPeriod(isInDetectPeriod);
  775. }else
  776. {
  777. /* 没有应用于噪音检测,就一直检测 */
  778. pThread.second->setInDetectPeriod(true);
  779. }
  780. }
  781. return true;
  782. }