#include "CompareItemThread.h" #include "ThreadManager.h" #include "CalculateDBPhaseThread.h" #include "NoiseDetectThread.h" #include "CompareDoubleThread.h" #include "ThreadPool.h" CompareItemThread::CompareItemThread(CalculateThreadInfo_t& threadInfo) : BaseCalculateThread(threadInfo) { } CompareItemThread::~CompareItemThread() { } /* 线程功能函数 */ void CompareItemThread::task() { m_logBase = fmt::format("对比项: {}", m_threadInfo.compareItemInfo.strName.toStdString()); SPDLOG_LOGGER_INFO(m_logger, "{} 线程开始运行, 对比通道: ", m_logBase); for(const auto& road : m_threadInfo.compareItemInfo.mapRoad) { SPDLOG_LOGGER_INFO(m_logger, "通道名称: {}, 通道编号: {}, 声卡通道: {}:{}", road.strCompareRoadName.toStdString(), road.nCompareRoadNum, road.scRoadInfo.strSoundCardName.toStdString(), road.scRoadInfo.roadInfo.nRoadNum); } /* 初始化数据 */ if(!initData()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据失败", m_logBase); return; } while (m_isRunning) { /* 睡眠10ms */ std::this_thread::sleep_for(std::chrono::milliseconds(10)); /* ------------------------------------------------------------------------------------- * 更新数据 * ------------------------------------------------------------------------------------- */ if(!updateResultData()) { continue; } /* ------------------------------------------------------------------------------------- * 处理数据,将报警信息给写报警数据的线程 * ------------------------------------------------------------------------------------- */ processAlarmData(); /* ------------------------------------------------------------------------------------- * 将音量包数据发送到MQTT中 * ------------------------------------------------------------------------------------- */ } /* 清理数据 */ clearData(); SPDLOG_LOGGER_INFO(m_logger, "{} 线程结束运行", m_logBase); } /* 初始化数据 */ bool CompareItemThread::initData() { /* 获取计算音量信息的线程指针 */ for(const auto& road : m_threadInfo.compareItemInfo.mapRoad) { /* 创建计算音量的线程 */ // CalculateDBPhaseThread* pThread = ThreadMan.getCalculateDBPhaseThread(); // if(pThread == nullptr) // { // SPDLOG_LOGGER_ERROR(m_logger, "{} 获取计算音量信息线程失败", m_logBase); // return false; // 获取线程失败 // } // m_vecCalculateDBPhaseThreads.push_back(pThread); } /* 获取计算噪音的线程 */ for(const auto& road : m_threadInfo.compareItemInfo.mapRoad) { NoiseDetectThread* pThread = ThreadMan.getNoiseDetectThread(road.scRoadInfo); if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取噪音检测线程失败", m_logBase); return false; // 获取线程失败 } m_vecNoiseDetectThreads.push_back(pThread); } /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */ if(!dispatchCompareThreads()) { return false; } /* 初始化存储结果的数据结构 */ m_compareResult.compareItemID = m_threadInfo.compareItemInfo.nID; m_compareResult.compareItemName = m_threadInfo.compareItemInfo.strName.toStdString(); m_compareResult.dateTime = QDateTime::currentDateTime(); m_compareResult.isClientAlarm = false; // 默认不报警 m_compareResult.vecRoadVolumes.clear(); // 清空之前的数据 for(const auto& road : m_threadInfo.compareItemInfo.mapRoad) { OneRoadVolume_t oneRoadVolume; oneRoadVolume.roadInfo = road; // 设置通道信息 oneRoadVolume.dateTime = QDateTime::currentDateTime(); // 初始化时间 m_compareResult.vecRoadVolumes.push_back(oneRoadVolume); } int roadCount = m_threadInfo.compareItemInfo.mapRoad.size(); m_vecCDBPhaseUpdated.reserve(roadCount); for(int i = 0; i < m_threadInfo.compareItemInfo.mapRoad.size(); ++i) { m_vecCDBPhaseUpdated.push_back(false); // 初始化为未更新 } /* 初始化报警信息 */ m_vecAlarmSilence.reserve(roadCount); m_vecAlarmOverload.reserve(roadCount); m_vecAlarmPhase.reserve(roadCount); m_vecAlarmSilenceLast.reserve(roadCount); m_vecAlarmOverloadLast.reserve(roadCount); m_vecAlarmPhaseLast.reserve(roadCount); return true; } /* 清理数据 */ void CompareItemThread::clearData() { /* 停止所有的比对线程 */ for(auto& thread : m_vecCompareDoubleThreads) { if(thread != nullptr) { thread->stopThread(); delete thread; thread = nullptr; } } m_vecCompareDoubleThreads.clear(); } /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */ bool CompareItemThread::dispatchCompareThreads() { auto it = m_threadInfo.compareItemInfo.mapRoad.begin(); auto mainRoad = it.value(); // 主通道信息 uint64_t size = m_threadInfo.compareItemInfo.mapRoad.size(); for(uint64_t i = 1; i < size; ++i) { it++; CalculateThreadInfo_t compareThreadInfo; compareThreadInfo.compareItemInfo = m_threadInfo.compareItemInfo; compareThreadInfo.compareItemInfo.mapRoad.clear(); // 清空通道信息 compareThreadInfo.compareItemInfo.mapRoad.insert(mainRoad.nCompareRoadNum, mainRoad); // 添加主通道 compareThreadInfo.compareItemInfo.mapRoad.insert(it.key(), it.value()); // 添加当前通道 compareThreadInfo.threadState = EThreadState::State_Inited; CompareDoubleThread* pThread = new CompareDoubleThread(compareThreadInfo); if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 创建对比线程 {} - {} 失败", m_logBase, mainRoad.strCompareRoadName.toStdString(), it.value().strCompareRoadName.toStdString()); return false; } m_vecCompareDoubleThreads.push_back(pThread); /* 添加到线程池开始运行 */ CPPTP.add_task(&CompareDoubleThread::threadTask, pThread); } return true; } /** * @brief 更新数据 * 更新数据逻辑: * 1、先从音量计算线程获取最新的音量包信息,如果没有全部更新,则等待下次获取,不进行后面的操作 * 2、获取噪音检测线程的噪音信息和获取一致性信息的线程的结果无需关系是否是最新的 * */ bool CompareItemThread::updateResultData() { const int size = m_threadInfo.compareItemInfo.mapRoad.size(); /* 先从音量计算数据中获取音量包信息和报警信息 */ for(int i = 0; i < size; ++i) { if(m_vecCDBPhaseUpdated[i] == true) { continue; // 已经更新过了 } CalculateDBPhaseThread* pThread = m_vecCalculateDBPhaseThreads[i]; if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取音量计算线程失败", m_logBase); continue; // 跳过这个线程 } /* 获取最新的音量数据 */ if(pThread->getlastVolumeInfo(m_compareResult.vecRoadVolumes[i])) { m_vecCDBPhaseUpdated[i] = true; // 标记为已更新 } /* 更新报警信息 */ m_vecAlarmSilence[i] = pThread->getAlarm(EAlarmType::EAT_Silent); m_vecAlarmOverload[i] = pThread->getAlarm(EAlarmType::EAT_Overload); m_vecAlarmPhase[i] = pThread->getAlarm(EAlarmType::EAT_Reversed); } /* 判断是否全部更新,如果没有则返回,等待下次再次获取 */ for(int i = 0; i < size; ++i) { if(m_vecCDBPhaseUpdated[i] == false) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 音量计算线程数据未全部更新,等待下次获取", m_logBase); return false; } } /* 获取噪音计算的结果 */ for(int i = 0; i < size; ++i) { NoiseDetectThread* pThread = m_vecNoiseDetectThreads[i]; if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取噪音检测线程失败", m_logBase); continue; // 跳过这个线程 } /* 获取最新的噪音数据,噪音报警那个标志位貌似没用到 */ m_compareResult.vecRoadVolumes[i].isNoise = pThread->isNoise(); } /* 从对比项中获取核对过后的结果 */ for(int i = 1; i < size; ++i) { CompareDoubleThread* pThread = m_vecCompareDoubleThreads[i-1]; if(pThread == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取对比线程失败", m_logBase); continue; // 跳过这个线程 } /* 获取最新的一致性结果 */ OneRoadVolume_t roadVolume; if(pThread->getlastVolumeInfo(roadVolume)) { m_compareResult.vecRoadVolumes[i].isConsistency = roadVolume.isConsistency; m_compareResult.vecRoadVolumes[i].isNotConsistencyWarning = roadVolume.isNotConsistencyWarning; } } return true; } /* 发送数据 */ void CompareItemThread::sendResultData() { /* 生成json数据 */ /* 发送到mqtt中 */ } /* 处理报警数据,主要是和之前的数据尽情对比,是否是一样的 */ void CompareItemThread::processAlarmData() { m_listAlarm.clear(); /* 处理静音报警数据 */ for(size_t i = 0; i < m_vecAlarmSilence.size(); ++i) { auto& nowAlarm = m_vecAlarmSilence[i]; auto& lastAlarm = m_vecAlarmSilenceLast[i]; if(nowAlarm.isAlarm) { if(lastAlarm == nowAlarm) { continue; // 和上次的报警信息一样,不需要处理 }else { nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID; nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString(); m_listAlarm.push_back(nowAlarm); m_vecAlarmSilenceLast[i] = nowAlarm; } } } /* 处理过载报警数据 */ for(size_t i = 0; i < m_vecAlarmOverload.size(); ++i) { auto& nowAlarm = m_vecAlarmOverload[i]; auto& lastAlarm = m_vecAlarmOverloadLast[i]; if(nowAlarm.isAlarm) { if(lastAlarm == nowAlarm) { continue; // 和上次的报警信息一样,不需要处理 }else { nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID; nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString(); m_listAlarm.push_back(nowAlarm); m_vecAlarmOverloadLast[i] = nowAlarm; } } } /* 处理反相报警数据 */ for(size_t i = 0; i < m_vecAlarmPhase.size(); ++i) { auto& nowAlarm = m_vecAlarmPhase[i]; auto& lastAlarm = m_vecAlarmPhaseLast[i]; if(nowAlarm.isAlarm) { if(lastAlarm == nowAlarm) { continue; // 和上次的报警信息一样,不需要处理 }else { nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID; nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString(); m_listAlarm.push_back(nowAlarm); m_vecAlarmPhaseLast[i] = nowAlarm; } } } /* 将报警列表写入到处理报警数据的线程中 */ }