Przeglądaj źródła

V0.2.1
1、完成了对比项的开启和关闭功能

Apple 2 tygodni temu
rodzic
commit
8cf22e4dc7
38 zmienionych plików z 1126 dodań i 133 usunięć
  1. 33 8
      SQL/ACAServer.sql
  2. 169 0
      Server/ACAServer.cpp
  3. 45 2
      Server/ACAServer.h
  4. 35 1
      Server/DataManager/SoundCardData.cpp
  5. 4 1
      Server/DataManager/SoundCardData.h
  6. 12 0
      Server/GlobalInfo/GlobalInfo.cpp
  7. 35 0
      Server/GlobalInfo/GlobalInfo.h
  8. 0 3
      Server/GlobalInfo/ReadConfig.cpp
  9. 0 18
      Server/GlobalInfo/ReadConfig.h
  10. 36 1
      Server/ThreadCalculate/BaseCalculateThread.cpp
  11. 16 4
      Server/ThreadCalculate/BaseCalculateThread.h
  12. 15 15
      Server/ThreadCalculate/CalculateDBThread.cpp
  13. 6 6
      Server/ThreadCalculate/CalculateDBThread.h
  14. 13 3
      Server/ThreadCalculate/CompareItemThread.cpp
  15. 6 4
      Server/ThreadCalculate/CompareItemThread.h
  16. 320 0
      Server/ThreadManager/ThreadCompareItemManager.cpp
  17. 49 0
      Server/ThreadManager/ThreadCompareItemManager.h
  18. 7 6
      Server/ThreadManager/ThreadManager.cpp
  19. 2 1
      Server/ThreadManager/ThreadManager.h
  20. 3 0
      Server/common/LHLog/LHLogInit.cpp
  21. 25 7
      Server/main.cpp
  22. 1 0
      SettingLibrary/DataBase/GlobalInfo.cpp
  23. 42 1
      SettingLibrary/Modules/Basic/basicwidget.cpp
  24. 4 0
      SettingLibrary/Modules/Basic/basicwidget.h
  25. 14 7
      SettingLibrary/Modules/Basic/compareitemdialog.cpp
  26. 7 3
      SettingLibrary/Modules/Basic/compareitemdialog.h
  27. 0 1
      SettingLibrary/Modules/Basic/compareitemlistdialog.h
  28. 17 6
      SettingLibrary/Modules/Basic/singlecompareroadwidget.cpp
  29. 3 1
      SettingLibrary/Modules/Basic/singlecompareroadwidget.h
  30. 8 1
      SettingLibrary/Modules/Basic/singlecompareroadwidget.ui
  31. 1 0
      SettingLibrary/Modules/CheckPeriod/onedetectplan.cpp
  32. 11 2
      SettingLibrary/setinfomanager.cpp
  33. 55 19
      common/DataManager/SoundCardData.cpp
  34. 21 8
      common/DataManager/SoundCardData.h
  35. 66 0
      common/DataManager/SystemConfig.cpp
  36. 37 2
      common/DataManager/SystemConfig.h
  37. 5 0
      common/DataManager/SystemConfigStruct.h
  38. 3 2
      common/GlobalInfo/GlobalVariable.h

+ 33 - 8
SQL/ACAServer.sql

@@ -1,29 +1,54 @@
 -- Active: 1749101595433@@192.1.2.61@5236@EQM_CESHI
 
-#报警信息
+
+#对比项
 SELECT *
-FROM tACAAlarmLog;
+FROM tACACompareItems;
 
-#报警文件
+
+#对比项通道信息
 SELECT *
-FROM tACAAlarmFile;
+FROM tACACompareItemRoad;
 
-#对比项
+
+#ACA系统设置信息
 SELECT *
-FROM tACACompareItem;
+FROM tACASystemConfig;
+
+
+#对比项一致性对比时段信息
+SELECT *
+FROM tACADetectPeriod;
+
+
+
+
+
 
 #记录文件
 SELECT *
 FROM tACARecordFile;
 
+
+
+#通道信息
+SELECT *
+FROM tACARoad;
+
+
+
+
 #记录日志
 SELECT *
 FROM tACARecordLog;
 
-#通道信息
+#报警信息
 SELECT *
-FROM tACARoad;
+FROM tACAAlarmLog;
 
+#报警文件
+SELECT *
+FROM tACAAlarmFile;
 
 SELECT *
 FROM TEQMSETUP;

+ 169 - 0
Server/ACAServer.cpp

@@ -1,3 +1,172 @@
 #include "ACAServer.h"
 
 
+#include "GlobalInfo.h"
+#include "commonDefine.h"
+#include "SoundCardData.h"
+#include "SystemConfig.h"
+#include "ThreadPool.h"
+
+#include <QFile>
+#include <QString>
+#include <QCoreApplication>
+#include <QSettings>
+
+
+
+
+ACAServer::ACAServer()
+{
+    m_logger = spdlog::get("ACAServer");
+    if(m_logger == nullptr)
+    {
+        fmt::print("ACAServer logger is nullptr");
+        return;
+    }
+
+    connect(&m_fromMQTT, &FromMQTT::signal_recvMessage, this, &ACAServer::do_receiveMQTTMessage);
+}
+
+ACAServer::~ACAServer()
+{
+    if(m_threadCompareItemManager != nullptr) {
+        delete m_threadCompareItemManager;
+        m_threadCompareItemManager = nullptr;
+    }
+}
+
+
+
+
+/* 初始化基础信息 */
+bool ACAServer::initGlobalInfo()
+{
+    /*------------------------------------------------------------------------------------*/
+    /* 读取配置文件 */
+    if(!readConfigFile()) {
+        spdlog::error("读取配置文件失败");
+        return false;
+    }
+    /* 设置MQTT服务器信息 */
+    GInfo.setMqttInfo(m_mqttIP, m_mqttPort);
+
+    /* 连接MQTT */
+    m_fromMQTT.setIPAndPort(m_mqttIP, m_mqttPort);
+    m_fromMQTT.addSubcribe(m_webapiTopic, 0); // 订阅WebAPI主题
+    m_fromMQTT.connectToServer();
+
+    /* 等待mqtt回复webapi信息 */
+    if(!waitForWebAPIReply()) 
+    {
+        return false;
+    }
+
+    /* 设置WebAPI信息 */
+    m_webAPIID = "cf6b57fa3d9841e22c3c897e6b8e66b8";
+    GInfo.setWebAPIInfo(m_webAPIUrl, m_webAPIID);
+
+    /* 登录webapi */
+    if(!m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_appType))
+    {
+        return false;
+    }
+
+    /*------------------------------------------------------------------------------------*/
+    /* 获取系统声卡信息 */
+    if(!SoundCards.InitData())
+    {
+        return false;
+    }
+    auto soundCardsInfo = SoundCards.getSoundCardInfo();
+    std::string jsonSoundCards;
+    SysConfig.setSoundCardInfoToJson(soundCardsInfo, jsonSoundCards);
+    // SPDLOG_DEBUG("声卡信息: {}", jsonSoundCards);
+    /* 将声卡信息写入数据库 */
+    if(!m_fromWebAPI.updateSystemConfig(Config_SoundCardInfo, jsonSoundCards, SysConfig.mapSysConfigDesc[eSystemConfigType::eSCT_SoundCardInfo]))
+    {
+        SPDLOG_LOGGER_WARN(m_logger, "更新声卡信息到WebAPI失败");
+    }
+
+
+    return true;
+}
+
+
+/* 开启服务 */
+bool ACAServer::startService()
+{
+    m_threadCompareItemManager = new ThreadCompareItemManager();
+    if(m_threadCompareItemManager == nullptr) 
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "创建对比项管理线程失败");
+        return false;
+    }
+    /* 开启线程 */
+    CPPTP.add_task(&ThreadCompareItemManager::thread_CompareItemManager, m_threadCompareItemManager);
+
+    return true;
+}
+
+
+
+/* 读取配置文件 */
+bool ACAServer::readConfigFile()
+{
+    QString configPath = QCoreApplication::applicationDirPath() + "/config/BaseConfig.ini";
+    QFile file(configPath);
+    if(!file.exists()) {
+        spdlog::error("配置文件 {} 不存在", configPath.toStdString());
+        return false;
+    }
+
+    QSettings settings(configPath, QSettings::IniFormat);
+    settings.beginGroup("MQTT");
+    m_mqttIP = settings.value("MQTT_IP", "").toString();
+    m_mqttPort = settings.value("MQTT_PORT", 1883).toInt();
+    settings.endGroup();
+
+    return true;
+}
+
+/* 等待webapi回复信息 */
+bool ACAServer::waitForWebAPIReply()
+{
+    int timeout = 5000; // 等待5秒
+    int elapsed = 0;
+    while(!m_isGetWebInfoSuccess.load() && elapsed < timeout) 
+    {
+        QCoreApplication::processEvents();
+        std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 每10毫秒检查一次
+        elapsed += 10;
+    }
+
+    if(!m_isGetWebInfoSuccess.load()) 
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "等待MQTT消息超时,未能获取WebAPI信息");
+        return false;
+    }
+
+    return true;
+}
+
+
+/* 处理MQTT消息 */
+void ACAServer::do_receiveMQTTMessage(const QMQTT::Message& message)
+{
+    SPDLOG_LOGGER_TRACE(m_logger, "接收到MQTT消息: {}", message.payload().toStdString());
+    if(message.topic() == m_webapiTopic) 
+    {
+        /* 处理WebAPI消息 */
+        QString payload = QString::fromUtf8(message.payload());
+        try 
+        {
+            nJson jsonMsg = nJson::parse(payload.toStdString());
+            m_webAPIUrl = jsonMsg["webaddr"].is_null() ? "" : jsonMsg["webaddr"].get<std::string>().c_str();
+            m_webAPIID = jsonMsg["serverid"].is_null() ? "" : jsonMsg["serverid"].get<std::string>().c_str();
+
+        }nJsonCatchNoReturn
+        m_isGetWebInfoSuccess.store(true);
+        SPDLOG_LOGGER_TRACE(m_logger, "WebAPI信息获取成功: URL = {}, ID = {}", m_webAPIUrl.toStdString(), m_webAPIID.toStdString());
+    }
+}
+

+ 45 - 2
Server/ACAServer.h

@@ -2,11 +2,54 @@
 #define ACASERVER_H
 
 
-class ACAServer
-{
+#include <QObject>
+#include "FromMQTT.h"
+#include "FromWebAPI.h"
+#include "spdlog/spdlog.h"
+#include "ThreadCompareItemManager.h"
+
 
+class ACAServer : public QObject
+{
+    Q_OBJECT
 public:
+    ACAServer();
+    ~ACAServer();
+    /* 初始化基础信息 */
+    bool initGlobalInfo();
+
+    /* 开启服务 */
+    bool startService();
+    
+
+private:
+    /* 读取配置文件 */
+    bool readConfigFile();
+    /* 等待webapi回复信息 */
+    bool waitForWebAPIReply();
+
+private:
+
+
+private slots:
+    /* 处理MQTT消息 */
+    void do_receiveMQTTMessage(const QMQTT::Message& message);
+
+private:
+    std::shared_ptr<spdlog::logger> m_logger = nullptr;
+    FromMQTT m_fromMQTT;
+
+    const QString m_webapiTopic = "LH_WEBINFO";
+    QString m_mqttIP;
+    int m_mqttPort = 1883; /* MQTT服务器端口 */
+
+    FromWebAPI m_fromWebAPI;
+    QString m_webAPIUrl; /* WebAPI地址 */
+    QString m_webAPIID;  /* WebAPI ID */
+    const QString m_appType = "ACAWatch"; /* 应用类型 */
+    std::atomic_bool m_isGetWebInfoSuccess = false; /* 是否获取WebAPI信息成功 */
 
+    ThreadCompareItemManager* m_threadCompareItemManager = nullptr; /* 对比项管理线程 */
 
 };
 

+ 35 - 1
Server/DataManager/SoundCardData.cpp

@@ -26,12 +26,40 @@ bool SoundCardManager::InitData()
     // } else
     // {
     //     SPDLOG_ERROR("获取PCM设备信息失败");
-    // }
+    // }    
 
 
     return true;
 }
 
+/* 获取声卡信息,转换成系统使用的数据类型 */
+QMap<int, SoundCardInfo_t> SoundCardManager::getSoundCardInfo() const
+{
+    QMap<int, SoundCardInfo_t> soundCardInfoMap;
+
+    for(const auto& device : m_listAudioDevice)
+    {
+        SoundCardInfo_t soundCardInfo;
+        soundCardInfo.nSoundCardNum = device.CardNumber;
+        soundCardInfo.strSoundCardID = QString::fromStdString(device.CardID);
+        soundCardInfo.strSoundCardName = QString::fromStdString(device.CardName);
+        soundCardInfo.strSoundCardDriver = QString::fromStdString(device.CardDriver);
+
+        for(const auto& pcmDevice : device.PCMDevices)
+        {
+            OneRoadInfo_t roadInfo;
+            roadInfo.nRoadNum = pcmDevice.PCMDevice;
+
+            soundCardInfo.listRoad.append(roadInfo);
+        }
+
+        soundCardInfoMap.insert(soundCardInfo.nSoundCardNum, soundCardInfo);
+    }
+
+    return soundCardInfoMap;
+}
+
+
 /* 打印声卡列表 */
 void SoundCardManager::printAudioDevices()
 {
@@ -60,5 +88,11 @@ void SoundCardManager::printAudioDeviceDesc(std::list<AudioDeviceDesc_t>& pcmDev
     }
 }
 
+/* 声卡信息写入数据库 */
+void SoundCardManager::writeAudioDeviceToDB()
+{
+
+}
+
 
 

+ 4 - 1
Server/DataManager/SoundCardData.h

@@ -30,17 +30,20 @@ public:
     bool InitData();
     /* 获取声卡信息 */
     const std::list<AudioDevice_t>& getListAudioDevice() const { return m_listAudioDevice; }
+    /* 获取声卡信息,转换成系统使用的数据类型 */
+    QMap<int, SoundCardInfo_t> getSoundCardInfo() const;
 
 private:
     /* 打印声卡列表 */
     void printAudioDevices();
     /* 打印声卡描述列表 */
     void printAudioDeviceDesc(std::list<AudioDeviceDesc_t>& pcmDevices);
+    /* 声卡信息写入数据库 */
+    void writeAudioDeviceToDB();
 
 private:
     /* 声卡设备列表 */
     std::list<AudioDevice_t> m_listAudioDevice;
-    
 
 };
 

+ 12 - 0
Server/GlobalInfo/GlobalInfo.cpp

@@ -19,6 +19,18 @@ void GlobalInfo::initGlobalInfo()
     initData();
 }
 
+void GlobalInfo::setMqttInfo(const QString& ip, int port)
+{
+    m_mqttIP = ip;          /* 设置MQTT服务器IP */
+    m_mqttPort = port;      /* 设置MQTT服务器端口 */
+}
+
+void GlobalInfo::setWebAPIInfo(const QString& url, const QString& id)
+{
+    m_webAPIUrl = url;      /* 设置WebAPI地址 */
+    m_webAPIID = id;        /* 设置WebAPI ID */
+}
+
 /* 初始化文件夹 */
 void GlobalInfo::initDirectories()
 {

+ 35 - 0
Server/GlobalInfo/GlobalInfo.h

@@ -1,6 +1,20 @@
 #ifndef _GLOBALINFO_H_
 #define _GLOBALINFO_H_
 
+
+/**
+ * @file GlobalInfo.h
+ * @author your name (you@domain.com)
+ * @brief 
+ * @version 0.1
+ * @date 2025-07-15
+ * 
+ * @copyright Copyright (c) 2025
+ * 
+ *    1、Server的全局信息,一些参数通过ReadConfig读取,这个类是ReadConfig友元
+ */
+
+
 #include <string>
 #include <QString>
 
@@ -31,6 +45,17 @@ public:
     /* 初始化全局信息 */
     void initGlobalInfo();
 
+    /* 获取mqtt信息 */
+    QString mqttIP() const {return m_mqttIP;}
+    int mqttPort() const {return m_mqttPort;}
+    void setMqttInfo(const QString& ip, int port);
+    
+    /* 获取WebAPI信息 */
+    QString webAPIUrl() const {return m_webAPIUrl;}
+    QString webAPIID() const {return m_webAPIID;}
+    QString appType() const {return m_appType;}
+    void setWebAPIInfo(const QString& url, const QString& id);
+
 public:
     /* 音频相关数据 */
     uint32_t sampleRate() const {return m_sampleRate;}          /* 获取采样率 */
@@ -111,6 +136,16 @@ private:
     void initData();
 
 private:
+    /******************** 系统基础设置 *********************/
+    /* MQTT信息 */
+    QString m_mqttIP;                  /* MQTT服务器IP */
+    int m_mqttPort = 1883;                 /* MQTT服务器端口 */
+    /* WebAPI地址 */
+    QString m_webAPIUrl;               /* WebAPI地址 */
+    QString m_webAPIID;                /* WebAPI ID */
+    const QString m_appType = "ACAWatch"; /* 应用类型 */
+
+
     /* 环形队列中每个文件的大小,也是生成的wav文件的大小
        这个大小和录音时长相对应,计算方式如下
        48khz * 2字节/采样点 * 2声道 * 时长(秒) = 文件大小(字节)

+ 0 - 3
Server/GlobalInfo/ReadConfig.cpp

@@ -1,3 +0,0 @@
-#include "ReadConfig.h"
-
-

+ 0 - 18
Server/GlobalInfo/ReadConfig.h

@@ -1,18 +0,0 @@
-#ifndef _READCONFIG_H_
-#define _READCONFIG_H_
-
-
-class ReadConfig
-{
-
-public:
-    ReadConfig() = default;
-    ~ReadConfig() = default;
-    /* 读取配置文件 */
-    void readConfigFile();
-
-
-
-};
-
-#endif // _READCONFIG_H_

+ 36 - 1
Server/ThreadCalculate/BaseCalculateThread.cpp

@@ -24,6 +24,7 @@ void BaseCalculateThread::threadTask()
                             static_cast<int>(m_threadInfo.threadType));
     m_threadInfo.threadState = EThreadState::State_Running;
     m_isStop = false;
+    /* 执行任务,并阻塞到这个函数中,直到任务退出 */
     task();
 
     SPDLOG_LOGGER_INFO(m_logger, "{} 执行结束", m_logBase);
@@ -34,8 +35,27 @@ void BaseCalculateThread::threadTask()
     m_isStop.store(true);
 }
 
-/* 停止线程 */
+/* 更新线程信息 */
+void BaseCalculateThread::updateThreadInfo(const CalculateThreadInfo_t& threadInfo)
+{
+    if(threadInfo.compareItemInfo.nID != m_threadInfo.compareItemInfo.nID)
+    {
+        SPDLOG_LOGGER_WARN(m_logger, "新传入的对比项ID {} 和当前线程的对比项ID {} 不匹配,无法更新线程信息",
+                           threadInfo.compareItemInfo.nID, m_threadInfo.compareItemInfo.nID);
+    }
+    m_threadInfoNew = threadInfo;
+    m_isUpdate = true;
+}
+
+/* 停止线程,只设置个停止标志,不阻塞等待 */
 void BaseCalculateThread::stopThread()
+{
+    m_isRunning = false;
+    SPDLOG_LOGGER_INFO(m_logger, "{} 线程设置为停止状态", m_logBase);
+}
+
+/* 停止线程 */
+void BaseCalculateThread::stopThreadBlock()
 {
     m_isRunning = false;
     while(m_isStop.load() == false) 
@@ -44,3 +64,18 @@ void BaseCalculateThread::stopThread()
         std::this_thread::sleep_for(std::chrono::microseconds(100));
     }
 }
+
+/* 更新线程信息 */
+bool BaseCalculateThread::updateThreadInfoInternal()
+{
+    if(!m_isUpdate)
+    {
+        return false;
+    }
+    /* 只更新对比项的信息 */
+    m_threadInfo.compareItemInfo = m_threadInfoNew.compareItemInfo;
+    m_isUpdate = false;
+    // SPDLOG_LOGGER_INFO(m_logger, "{} 更新线程信息", m_logBase);
+
+    return true;
+}

+ 16 - 4
Server/ThreadCalculate/BaseCalculateThread.h

@@ -5,7 +5,12 @@
 #include "GlobalVariable.h"
 
 
-
+/**
+ * @brief 基础计算线程类
+ *          1、线程信息更新,更新的新内容先存储起来,等线程的下一次循环再主动更新
+ *          2、线程停止,m_isRunning设置为false,线程在下一次循环时检查这个标志位,为false时退出
+ * 
+ */
 class BaseCalculateThread
 {
 
@@ -20,10 +25,14 @@ public:
     virtual void threadTask();
 
     /* 获取线程信息 */
-    CalculateThreadInfo_t getThreadInfo() { return m_threadInfo; }
+    const CalculateThreadInfo_t& getThreadInfo() { return m_threadInfo; }
+    /* 更新线程信息 */
+    void updateThreadInfo(const CalculateThreadInfo_t& threadInfo);
 
-    /* 停止线程 */
+    /* 停止线程,只设置个停止标志,不阻塞等待 */
     void stopThread();
+    /* 停止线程 */
+    void stopThreadBlock();
     
 
 protected:
@@ -36,6 +45,8 @@ protected:
     virtual bool initData() = 0;
     /* 清理数据 */
     virtual void clearData() = 0;
+    /* 更新线程信息 */
+    bool updateThreadInfoInternal();
     
 
 protected:
@@ -46,7 +57,8 @@ protected:
     std::atomic_bool m_isStop = false;              /* 线程停止标志 */
 
     CalculateThreadInfo_t m_threadInfo;             /* 线程信息 */
-
+    std::atomic_bool m_isUpdate = false;            /* 是否需要更新线程信息 */
+    CalculateThreadInfo_t m_threadInfoNew;          /* 新的线程信息,用于更新 */
 };
 
 

+ 15 - 15
Server/ThreadCalculate/CalculateDBPhaseThread.cpp → Server/ThreadCalculate/CalculateDBThread.cpp

@@ -1,23 +1,23 @@
-#include "CalculateDBPhaseThread.h"
+#include "CalculateDBThread.h"
 #include "spdlog.h"
 
 #include "ThreadManager.h"
 #include "GlobalInfo.h"
 
 
-CalculateDBPhaseThread::CalculateDBPhaseThread(CalculateThreadInfo_t& threadInfo)
+CalculateDBThread::CalculateDBThread(CalculateThreadInfo_t& threadInfo)
     : BaseCalculateThread(threadInfo)
 {
 
 }
 
-CalculateDBPhaseThread::~CalculateDBPhaseThread()
+CalculateDBThread::~CalculateDBThread()
 {
 
 }
 
 /* 获取结果 */
-OneRoadVolume_t CalculateDBPhaseThread::getVolumeInfo()
+OneRoadVolume_t CalculateDBThread::getVolumeInfo()
 {
     std::lock_guard<std::mutex> lock(m_mutexVolumeInfo);
     return m_roadVolumeInfo;
@@ -26,7 +26,7 @@ OneRoadVolume_t CalculateDBPhaseThread::getVolumeInfo()
 /* 获取最新的结果
  * 结果包括:静音、过载、反相和音量包信息
  */
-bool CalculateDBPhaseThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
+bool CalculateDBThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
 {
     std::lock_guard<std::mutex> lock(m_mutexVolumeInfo);
     if(m_caculateDBData.ringQueue.isEmpty())
@@ -49,7 +49,7 @@ bool CalculateDBPhaseThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
 }
 
 /* 获取报警数据 */
-AlarmInfo_t CalculateDBPhaseThread::getAlarm(EAlarmType alarmType)
+AlarmInfo_t CalculateDBThread::getAlarm(EAlarmType alarmType)
 {
     std::lock_guard<std::mutex> lock(m_mutexVolumeInfo);
     switch(alarmType)
@@ -67,7 +67,7 @@ AlarmInfo_t CalculateDBPhaseThread::getAlarm(EAlarmType alarmType)
 }
 
 /* 线程功能函数 */
-void CalculateDBPhaseThread::task()
+void CalculateDBThread::task()
 {
     SPDLOG_LOGGER_INFO(m_logger, "{} 开启计算静音、过载和反相等报警的线程", m_logBase);
     /* 初始化数据 */
@@ -106,7 +106,7 @@ void CalculateDBPhaseThread::task()
 }
 
 /* 初始化数据 */
-bool CalculateDBPhaseThread::initData()
+bool CalculateDBThread::initData()
 {
     /* 对于单个录音通道的线程来说,直接取map中的第一个通道 */
     auto begin = m_threadInfo.compareItemInfo.mapRoad.begin();
@@ -130,13 +130,13 @@ bool CalculateDBPhaseThread::initData()
 }
 
 /* 清理数据 */
-void CalculateDBPhaseThread::clearData()
+void CalculateDBThread::clearData()
 {
 
 }
 
 /* 计算静音过载反相 */
-void CalculateDBPhaseThread::calcuDBPhase()
+void CalculateDBThread::calcuDBPhase()
 {
     /* 有最新数据,进行计算 */
     m_mutexVolumeInfo.lock();
@@ -171,7 +171,7 @@ void CalculateDBPhaseThread::calcuDBPhase()
  *           所以需要真正计算出静音开始的时间
  * 
  */
-void CalculateDBPhaseThread::processAlarm()
+void CalculateDBThread::processAlarm()
 {
     /* ----------------------- 处理静音报警 ----------------------- */
     processAlarm();
@@ -183,7 +183,7 @@ void CalculateDBPhaseThread::processAlarm()
 }
 
 /* 处理静音报警 */
-void CalculateDBPhaseThread::processSilence()
+void CalculateDBThread::processSilence()
 {
     if(m_roadVolumeInfo.isSilence)
     {
@@ -247,7 +247,7 @@ void CalculateDBPhaseThread::processSilence()
 }
 
 /* 处理过载报警 */
-void CalculateDBPhaseThread::processOverload()
+void CalculateDBThread::processOverload()
 {
     if(m_roadVolumeInfo.isOverload)
     {
@@ -312,7 +312,7 @@ void CalculateDBPhaseThread::processOverload()
 }
 
 /* 处理反相报警 */
-void CalculateDBPhaseThread::processPhase()
+void CalculateDBThread::processPhase()
 {
     if(m_roadVolumeInfo.isReversed)
     {
@@ -376,7 +376,7 @@ void CalculateDBPhaseThread::processPhase()
 
 
 /* 生成报警文件路径 */
-std::string CalculateDBPhaseThread::generateAlarmFilePath(const AlarmInfo_t& alarmInfo)
+std::string CalculateDBThread::generateAlarmFilePath(const AlarmInfo_t& alarmInfo)
 {
     std::string filePath = fmt::format("Alarm_{}_{}_{}.wav", 
         alarmInfo.strCompareItemName, 

+ 6 - 6
Server/ThreadCalculate/CalculateDBPhaseThread.h → Server/ThreadCalculate/CalculateDBThread.h

@@ -1,5 +1,5 @@
-#ifndef _CALCULATEDBPHASETHREAD_H_
-#define _CALCULATEDBPHASETHREAD_H_
+#ifndef _CALCULATEDBTHREAD_H_
+#define _CALCULATEDBTHREAD_H_
 
 #include "AudioData.h"
 #include "BaseCalculateThread.h"
@@ -21,12 +21,12 @@
  *      3、反相报警信息
  *      4、音量包信息
  */
-class CalculateDBPhaseThread : public BaseCalculateThread
+class CalculateDBThread : public BaseCalculateThread
 {
 
 public:
-    CalculateDBPhaseThread(CalculateThreadInfo_t& threadInfo);
-    ~CalculateDBPhaseThread() override;
+    CalculateDBThread(CalculateThreadInfo_t& threadInfo);
+    ~CalculateDBThread() override;
 
     /* 获取线程通道信息 */
     CompareItemRoadInfo_t getRoadInfo() const { return m_roadInfo; }
@@ -100,4 +100,4 @@ private:
 };
 
 
-#endif // _CALCULATEDBPHASETHREAD_H_
+#endif // _CALCULATEDBTHREAD_H_

+ 13 - 3
Server/ThreadCalculate/CompareItemThread.cpp

@@ -1,7 +1,7 @@
 #include "CompareItemThread.h"
 
 #include "ThreadManager.h"
-#include "CalculateDBPhaseThread.h"
+#include "CalculateDBThread.h"
 #include "NoiseDetectThread.h"
 #include "CompareDoubleThread.h"
 #include "ThreadPool.h"
@@ -42,6 +42,16 @@ void CompareItemThread::task()
         /* 睡眠10ms */
         std::this_thread::sleep_for(std::chrono::milliseconds(10));
 
+        /* -------------------------------------------------------------------------------------
+         * 更新对比项信息
+         * ------------------------------------------------------------------------------------- */
+        if(updateThreadInfoInternal())
+        {
+            SPDLOG_LOGGER_INFO(m_logger, "{} 暂停对比检测,更新对比项信息");
+
+            SPDLOG_LOGGER_INFO(m_logger, "{} 更新对比项信息完成,继续检测对比");
+        }
+
         /* -------------------------------------------------------------------------------------
          * 更新数据
          * ------------------------------------------------------------------------------------- */
@@ -140,7 +150,7 @@ void CompareItemThread::clearData()
     {
         if(thread != nullptr)
         {
-            thread->stopThread();
+            thread->stopThreadBlock();
             delete thread;
             thread = nullptr;
         }
@@ -195,7 +205,7 @@ bool CompareItemThread::updateResultData()
         {
             continue; // 已经更新过了
         }
-        CalculateDBPhaseThread* pThread = m_vecCalculateDBPhaseThreads[i];
+        CalculateDBThread* pThread = m_vecCalculateDBPhaseThreads[i];
         if(pThread == nullptr)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "{} 获取音量计算线程失败", m_logBase);

+ 6 - 4
Server/ThreadCalculate/CompareItemThread.h

@@ -6,18 +6,20 @@
 #include "CompareResult.h"
 #include "AlarmInfo.h"
 
-class CalculateDBPhaseThread;
+class CalculateDBThread;
 class NoiseDetectThread;
 class CompareDoubleThread;
 
 
 /**
- * 对比项信息
+ * 对比项功能线程
  *      功能:
  *          1、对比两个录音通道的数据,通道1是主通道,和其他通道挨个对比
  *          2、这里处理各个通道的报警信息,写入数据库
  *          3、从这里开启各个比对线程,获取比对结果信息,并组合
- * 
+ *          4、这里创建的线程包含两两对比线程和音量检测线程,这两个都和对比项相关联
+ *          5、噪音检测线程从线程管理器中获取的,这里不负责创建和销毁
+ *
  */
 class CompareItemThread : public BaseCalculateThread
 {
@@ -48,7 +50,7 @@ private:
 
 private:
     /* 计算音量信息的线程指针,第一个是主通道线程 */
-    std::vector<CalculateDBPhaseThread*> m_vecCalculateDBPhaseThreads;
+    std::vector<CalculateDBThread*> m_vecCalculateDBPhaseThreads;
     std::vector<bool> m_vecCDBPhaseUpdated;             /* 音量包更新标志位 */
     /* 计算噪音的线程指针 */
     std::vector<NoiseDetectThread*> m_vecNoiseDetectThreads;

+ 320 - 0
Server/ThreadManager/ThreadCompareItemManager.cpp

@@ -0,0 +1,320 @@
+#include "ThreadCompareItemManager.h"
+
+#include "GlobalInfo.h"
+#include "SystemConfig.h"
+#include "CompareItemThread.h"
+#include "ThreadPool.h"
+
+
+ThreadCompareItemManager::ThreadCompareItemManager()
+{
+    m_logger = spdlog::get("CompareItemManager");
+    if(m_logger == nullptr)
+    {
+        fmt::print("ThreadCompareItemManager: CompareItemManager Logger not found.\n");
+        return;
+    }
+    
+    
+}
+
+ThreadCompareItemManager::~ThreadCompareItemManager()
+{
+
+}
+
+/* 线程函数 */
+void ThreadCompareItemManager::thread_CompareItemManager()
+{
+    /* 初始化webapi */
+    m_webAPIUrl = GInfo.webAPIUrl();
+    m_webAPIID = GInfo.webAPIID();
+    m_appType = GInfo.appType();
+    if(m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_appType))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "ThreadCompareItemManager: 初始化WebAPI失败");
+        return;
+    }
+
+    /* 创建一些变量 */
+    int threadSleepTime = 2; // 线程休眠时间,单位秒
+    QList<CompareItemInfo_t> listCreateItems; // 新创建的对比项列表
+    QList<CompareItemInfo_t> listUpdateItems; // 更新的对比项列表
+    QList<int> listDeleteItems; // 删除的对比项列表
+
+    /* 获取基础配置,目前只获取一次 */
+    updateBaseSettings();
+
+    SPDLOG_LOGGER_INFO(m_logger, "开启对比项管理线程");
+    while(true)
+    {
+        std::this_thread::sleep_for(std::chrono::seconds(threadSleepTime));
+        if(threadSleepTime < 10)
+        {
+            /* 线程睡眠时间恢复为10秒 */
+            threadSleepTime = 10;
+        }
+        /* ------------------------------ 处理对比项信息 ------------------------------ */
+        if(!m_fromWebAPI.getCompareItemInfo(m_listNewItems))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger, "ThreadCompareItemManager: 获取对比项失败");
+            continue;
+        }
+        listCreateItems.clear();
+        listUpdateItems.clear();
+        listDeleteItems.clear();
+        processCompareItemInfo(listCreateItems, listUpdateItems, listDeleteItems);
+
+        /* 先删除已消失的对比项信息 */
+        processDeleteCompareItemThreads(listDeleteItems);
+        /* 更新需要更新的线程 */
+        updateRunningThreads(listUpdateItems);
+        /* 再创建新的对比项线程 */
+        createNewCompareItemThreads(listCreateItems);
+    }
+
+    SPDLOG_LOGGER_INFO(m_logger, "ThreadCompareItemManager: 线程结束");
+
+}
+
+/* 更新基础设置信息,如数据库设置,噪音参数等 */
+bool ThreadCompareItemManager::updateBaseSettings()
+{
+    /* 更新基础数据 */
+    QMap<std::string, std::string> baseSettings;
+    if(!m_fromWebAPI.getSystemConfig(baseSettings))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置失败");
+        return false;
+    }
+    /* 将获取到的配置转换成结构体 */
+    for(auto it = baseSettings.begin(); it != baseSettings.end(); ++it)
+    {
+
+        if(Config_Base == it.key())
+        {
+            if(!SysConfig.getBaseConfigFromJson(it.value()))
+            {
+                SPDLOG_ERROR("获取基础配置失败");
+            }
+        }
+        else if(Config_CompareAI == it.key())
+        {
+            if(!SysConfig.getAICompareConfigFromJson(it.value()))
+            {
+                SPDLOG_ERROR("获取AI对比配置失败");
+            }
+        }
+        else if(Config_NoiseBase == it.key())
+        {
+            if(!SysConfig.getNoiseDetectBaseConfigFromJson(it.value()))
+            {
+                SPDLOG_ERROR("获取噪音检测基础配置失败");
+            }
+        }
+        else if(Config_NoiseParam == it.key())
+        {
+            if(!SysConfig.getNoiseDetectParamFromJson(it.value()))
+            {
+                SPDLOG_ERROR("获取噪音检测参数失败");
+            }
+        }
+        else if(Config_Database == it.key())
+        {
+            if(!SysConfig.getDatabaseConfigFromJson(it.value()))
+            {
+                SPDLOG_ERROR("获取数据库设置失败");
+            }
+        }
+        else
+        {
+            SPDLOG_DEBUG("未知的系统配置项: {}", it.key());
+        }
+    }
+
+    /* 检测时段单独获取 */
+    QMap<int, DetectPeriodConfig_t> mapDetectConfig;
+    if(!m_fromWebAPI.getDetectPeriodConfig(mapDetectConfig))
+    {
+        SPDLOG_ERROR("获取对比项检测时段配置失败");
+        return false;
+    }
+    SysConfig.setDetectPeriodConfig(mapDetectConfig);
+
+    return true;
+}
+
+
+/**
+ * @brief 处理对比项信息,新获取的和已有的对比
+ * 
+ * @param createList 创建列表
+ * @param updateList 更新列表,根据对比项ID进行更新信息
+ * @param deleteList 删除列表
+ */
+void ThreadCompareItemManager::processCompareItemInfo(QList<CompareItemInfo_t>& createList, QList<CompareItemInfo_t>& updateList, QList<int>& deleteList)
+{
+    QMap<int, CompareItemInfo_t> mapNowItems;
+    /* 先从对比项线程中获取对比项信息 */
+    for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
+    {
+        BaseCalculateThread* pThread = it.value();
+        if(pThread == nullptr)
+        {
+            continue;
+        }
+        
+        /* 获取对比项信息 */
+        CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo;
+        mapNowItems.insert(itemInfo.nID, itemInfo);
+    }
+
+    /* 遍历新获取的对比项信息,找出需要新增的对比项和需要更新的对比项 */
+    for(const CompareItemInfo_t& item : m_listNewItems)
+    {
+        if(!mapNowItems.contains(item.nID))
+        {
+            /* 新对比项,添加到创建列表 */
+            createList.append(item);
+        } else
+        {
+            /* 已有对比项,检查是否需要更新 */
+            const CompareItemInfo_t& existingItem = mapNowItems.value(item.nID);
+            /* 先对比基础信息 */
+            if(!existingItem.isEqualBase(item))
+            {
+                /* 基础信息不同,需要更新 */
+                updateList.append(item);
+                continue;
+            }
+            /* 在对比对比项通道信息 */
+            if(!existingItem.isEqualRoads(item))
+            {
+                /* 通道信息不同,需要更新 */
+                updateList.append(item);
+                continue;
+            }
+        }
+    }
+    /* 遍历当前对比项信息,找出需要删除的对比项 */
+    for(auto it : mapNowItems)
+    {
+        for(const CompareItemInfo_t& newItem : m_listNewItems)
+        {
+            if(it.nID == newItem.nID)
+            {
+                break; // 找到对应的对比项,不需要删除
+            }
+        }
+        /* 当前对比项不在新获取的对比项中,说明需要删除 */
+        deleteList.append(it.nID);
+    }
+
+}
+
+
+/**
+ * @brief 处理需要删除的对比项线程
+ *        1、先处理已经停止的线程
+ *        2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程
+ * 
+ * @param deleteList 
+ */
+void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList<int>& deleteList)
+{
+    /* 先处理已经停止运行的线程 */
+    for(auto it = m_mapThreads.begin(); it != m_mapThreads.end();)
+    {
+        BaseCalculateThread* pThread = it.value();
+        if(pThread == nullptr)
+        {
+            SPDLOG_LOGGER_WARN(m_logger, "对比项线程指针为空,即将删除该线程指针");
+            it = m_mapThreads.erase(it);
+            continue;
+        }
+        if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped)
+        {
+            /* 线程已经停止,直接删除 */
+            SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
+            delete pThread;
+            it = m_mapThreads.erase(it);
+            continue;
+        }
+        ++it;
+
+    }
+
+    /* 停止本次需要停止的线程 */
+    for(auto it : m_mapThreads)
+    {
+        int compareItemID = it->getThreadInfo().compareItemInfo.nID;
+        if(deleteList.contains(compareItemID))
+        {
+            /* 设置线程停止标志 */
+            it->stopThread();
+            SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 设置为停止状态", it->getThreadInfo().compareItemInfo.strName.toStdString());
+        }
+    }
+}
+
+/* 更新正在运行的线程信息 */
+void ThreadCompareItemManager::updateRunningThreads(const QList<CompareItemInfo_t>& updateList)
+{
+    if(updateList.isEmpty())
+    {
+        return;
+    }
+    for(const CompareItemInfo_t& item : updateList)
+    {
+        auto it = m_mapThreads.find(item.nID);
+        if(it == m_mapThreads.end())
+        {
+            SPDLOG_LOGGER_WARN(m_logger, "对比项线程 {} 不存在,无法更新信息", item.strName.toStdString());
+            continue;
+        }
+        BaseCalculateThread* pThread = it.value();
+        if(pThread == nullptr)
+        {
+            continue;
+        }
+        CalculateThreadInfo_t threadInfo;
+        threadInfo.compareItemInfo = item;
+        pThread->updateThreadInfo(threadInfo);
+    }
+}
+
+/* 创建新的线程 */
+bool ThreadCompareItemManager::createNewCompareItemThreads(const QList<CompareItemInfo_t>& createList)
+{
+    if(createList.isEmpty())
+    {
+        SPDLOG_LOGGER_DEBUG(m_logger, "没有新的对比项需要创建");
+        return true;
+    }
+
+    for(auto& it : createList)
+    {
+        /* 创建新的对比项线程 */
+        CalculateThreadInfo_t threadInfo;
+        threadInfo.compareItemInfo = it;
+        threadInfo.threadType = EThreadType::Type_CompareItem;
+        threadInfo.threadState = EThreadState::State_Inited;
+
+        /* 创建线程对象 */
+        BaseCalculateThread* pThread = new CompareItemThread(threadInfo);
+        if(pThread == nullptr)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "创建对比项线程 {} 失败", it.strName.toStdString());
+            return false;
+        }
+        
+        /* 启动线程 */
+        CPPTP.add_task(&CompareItemThread::threadTask, pThread);
+        
+        /* 添加到线程列表中 */
+        m_mapThreads.insert(it.nID, pThread);
+    }
+
+    return true;
+}
+

+ 49 - 0
Server/ThreadManager/ThreadCompareItemManager.h

@@ -0,0 +1,49 @@
+#ifndef __THREADCOMPAREITEMMANAGER_H__
+#define __THREADCOMPAREITEMMANAGER_H__
+
+
+#include "spdlog/spdlog.h"
+#include "FromWebAPI.h"
+#include "BaseCalculateThread.h"
+
+
+class ThreadCompareItemManager
+{
+
+public:
+    ThreadCompareItemManager();
+    ~ThreadCompareItemManager();
+
+    /* 线程函数 */
+    void thread_CompareItemManager();
+
+private:
+    /* 更新基础设置信息,如数据库设置,噪音参数等 */
+    bool updateBaseSettings();
+    /* 处理对比项信息,新获取的和已有的对比 */
+    void processCompareItemInfo(QList<CompareItemInfo_t>& createList,
+                                QList<CompareItemInfo_t>& updateList,
+                                QList<int>& deleteList);
+
+    /* 处理需要删除的对比项线程 */
+    void processDeleteCompareItemThreads(const QList<int>& deleteList);
+    /* 更新正在运行的线程信息 */
+    void updateRunningThreads(const QList<CompareItemInfo_t>& updateList);
+    /* 创建新的线程 */
+    bool createNewCompareItemThreads(const QList<CompareItemInfo_t>& createList);
+
+private:
+    std::shared_ptr<spdlog::logger> m_logger = nullptr;
+    FromWebAPI m_fromWebAPI;                /* WebAPI处理类 */
+    QString m_webAPIUrl;                    /* WebAPI地址 */
+    QString m_webAPIID;                     /* WebAPI ID */
+    QString m_appType;                      /* 应用类型 */
+
+
+    QList<CompareItemInfo_t> m_listNewItems;   /* 对比项列表 */
+    QMap<int, BaseCalculateThread*> m_mapThreads; /* 对比项线程列表,key是对比项ID,value是对应的线程指针 */
+
+};
+
+
+#endif

+ 7 - 6
Server/ThreadManager/ThreadManager.cpp

@@ -3,7 +3,7 @@
 #include "CreateWAVThread.h"
 #include "CreateDBPhaseThread.h"
 
-#include "CalculateDBPhaseThread.h"
+#include "CalculateDBThread.h"
 #include "ConsistencyCompareThread.h"
 #include "GlobalVariable.h"
 #include "NoiseDetectThread.h"
@@ -23,10 +23,10 @@ ThreadManager::ThreadManager()
 }
 
 /* 启动所有线程 */
-void ThreadManager::startAllThreads()
-{
+// void ThreadManager::startAllThreads()
+// {
 
-}
+// }
 
 /* 停止所有线程 */
 void ThreadManager::stopAllThreads()
@@ -221,7 +221,8 @@ bool ThreadManager::removeConsistencyCompareThread(SoundCardRoadInfo_t& roadInfo
     m_referCountConsistencyCompare--; // 引用计数减一
     if(m_referCountConsistencyCompare <= 0)
     {
-        pThreadToRemove->stopThread(); // 停止线程
+        /* 停止线程,并一直等待其停止 */
+        pThreadToRemove->stopThreadBlock();
         m_listConsistencyCompareThreads.remove(pThreadToRemove); // 从列表中移除
         delete pThreadToRemove; // 删除线程
         pThreadToRemove = nullptr;
@@ -288,7 +289,7 @@ bool ThreadManager::removeNoiseDetectThread(SoundCardRoadInfo_t& roadInfo)
     m_referCountNoiseDetect--; // 引用计数减一
     if(m_referCountNoiseDetect <= 0)
     {
-        pThreadToRemove->stopThread(); // 停止线程
+        pThreadToRemove->stopThreadBlock(); // 停止线程
         m_listNoiseDetectThreads.remove(pThreadToRemove); // 从列表中移除
         delete pThreadToRemove; // 删除线程
         pThreadToRemove = nullptr;

+ 2 - 1
Server/ThreadManager/ThreadManager.h

@@ -40,7 +40,7 @@ public:
     }
 
     /* 启动所有线程 */
-    void startAllThreads();
+    // void startAllThreads();
     /* 停止所有线程 */
     void stopAllThreads();
 
@@ -65,6 +65,7 @@ public:
      * 当不需要此线程后,调用remove()函数去掉该线程
      * 补充:
      *      1、能在这里获取的线程是为了尽可能复用线程,这些都是和对比项无关的计算线程
+     *      2、和对比项有关的计算线程由对比项线程启动和管理
      * -------------------------------------------------------------------------------------------- */
     /* 获取一致性比对线程,线程不存在则创建 */
     ConsistencyCompareThread* getConsistencyCompareThread(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2);

+ 3 - 0
Server/common/LHLog/LHLogInit.cpp

@@ -80,6 +80,8 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
 
         /* 创建一个RTP服务的logger */
         auto logger_rtpserver = std::make_shared<spdlog::logger>("RTPServer",begin(sinks),end(sinks));
+        /* 创建一个对比项管理线程的logger */
+        auto logger_compareitem = std::make_shared<spdlog::logger>("CompareItemManager",begin(sinks),end(sinks));
 
 
         /* 注册到注册表 */
@@ -88,6 +90,7 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
         spdlog::register_logger(logger_acaserver);
         spdlog::register_logger(logger_record);
         spdlog::register_logger(logger_rtpserver);
+        spdlog::register_logger(logger_compareitem);
 
 
         /* 设置spdlog输出级别,默认的估计不输出debug这个级别

+ 25 - 7
Server/main.cpp

@@ -8,7 +8,7 @@
 
 #include "LHCompareAPI.h"
 #include "signalstats_wrapper.h"
-#include "SoundCardData.h"
+#include "ACAServer.h"
 
 #include <QDir>
 #include <QFile>
@@ -33,25 +33,43 @@ int main(int argc, char* argv[])
     SPDLOG_LOGGER_INFO(logger, "★  ★  ★  ★  ★  ★  ☆  ☆  ACAServer  ☆  ☆  ★  ★  ★  ★  ★  ★");
     SPDLOG_LOGGER_INFO(logger, "ACServer Version: {}", "6.0.0.0");
     /* 设置线程池最大线程个数 */
-    CPPTP.setThreadMaxNum(512);
-
-    /* 获取声卡信息 */
-    SoundCards.InitData();
+    CPPTP.setThreadMaxNum(1024);
 
+    /* 加载第三方库 */
     void LoadLibrary();
     /* 初始化噪音检测功能 */
     signalstats_wrapper::initialize();
 
+
+    ACAServer acas;
+    /* 初始化一些系统信息 */
+    if(!acas.initGlobalInfo())
+    {
+        SPDLOG_LOGGER_ERROR(logger, "ACAServer 初始化失败!");
+    }
+    
+
     // test();
     // CPPTP.add_task(test1);
 
-    a.exec();
+    /* 启动服务 */
+    if(acas.startService())
+    {
+        SPDLOG_LOGGER_INFO(logger, "ACAServer 服务启动成功");
+    } else
+    {
+        SPDLOG_LOGGER_ERROR(logger, "ACAServer 服务启动失败");
+        return -1;
+    }
+
+
+    int result = a.exec();
 
     /* 释放资源 */
     signalstats_wrapper::finalize();
     SPDLOG_LOGGER_INFO(logger, "ACAServer 结束运行");
 
-    return 0;
+    return result;
 }
 
 /* 加载第三方动态库 */

+ 1 - 0
SettingLibrary/DataBase/GlobalInfo.cpp

@@ -14,6 +14,7 @@ bool GlobalInfo::initGlobalInfo()
     return true;
 }
 
+
 /* 设置对比项默认的参数 */
 void GlobalInfo::setDefaultCompareItem(const CompareItemInfo_t& item)
 {

+ 42 - 1
SettingLibrary/Modules/Basic/basicwidget.cpp

@@ -10,6 +10,8 @@
 #include "SystemConfigStruct.h"
 #include "SystemConfig.h"
 #include "GlobalInfo.h"
+#include "SoundCardData.h"
+
 #include <string>
 
 
@@ -59,7 +61,11 @@ BasicWidget::BasicWidget(QWidget *parent) :
     ui->checkBox_clearHistoryDir->setChecked(baseConfig.isClearDirSystemOn);
     ui->checkBox_enableSoundCardName->setChecked(baseConfig.isUsingSoundCardName);
 
-
+    /* 连接信号和槽 */
+    connect(ui->comBox_driverName, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &BasicWidget::do_soundCardChanged);
+    /* 设置声卡信息 */
+    setSoundCardInfo();
+    
 }
 
 BasicWidget::~BasicWidget()
@@ -98,6 +104,41 @@ void BasicWidget::do_pBtn_CompareItemClicked()
     dlg.exec();
 }
 
+/* 修改了选择了声卡 */
+void BasicWidget::do_soundCardChanged(int nIndex)
+{
+    int nSoundCardNum = ui->comBox_driverName->currentData().toInt();
+    if(nSoundCardNum < 0)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "选择的声卡无效,无法设置通道信息");
+        return;
+    }
+    /* 设置当前声卡信息 */
+    if(!SoundCards.setCurrentSoundCard(nSoundCardNum))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "设置当前声卡失败,声卡编号: {}", nSoundCardNum);
+        return;
+    }
+}
+
+
+/* 设置声卡信息 */
+void BasicWidget::setSoundCardInfo()
+{
+    const auto& soundCardInfo = SoundCards.getSoundCardInfo();
+
+    /* 清空现有的声卡信息 */
+    ui->comBox_driverName->clear();
+    /* 添加声卡信息到下拉框 */
+    for(const auto& it : soundCardInfo)
+    {
+        ui->comBox_driverName->addItem(it.strSoundCardName, it.nSoundCardNum);
+    }
+    /* 设置当前信息 */
+    ui->comBox_driverName->setCurrentIndex(0);
+}
+
+
 /* 保存基础信息 */
 bool BasicWidget::saveBasicSettingInfo()
 {

+ 4 - 0
SettingLibrary/Modules/Basic/basicwidget.h

@@ -30,8 +30,12 @@ public:
 private slots:
     /* 对比项配置 */
     void do_pBtn_CompareItemClicked();
+    /* 修改了选择了声卡 */
+    void do_soundCardChanged(int nIndex);
 
 private:
+    /* 设置声卡信息 */
+    void setSoundCardInfo();
     /* 保存基础信息 */
     bool saveBasicSettingInfo();
     /* 保存对比项信息 */

+ 14 - 7
SettingLibrary/Modules/Basic/compareitemdialog.cpp

@@ -28,10 +28,8 @@ CompareItemDialog::CompareItemDialog(QWidget *parent)
     ui->checkBoxOverload->setChecked(true);
     ui->checkBoxPhase->setChecked(true);
 
-    /* 设置已有两个通道的可选录音通道 */
-    ui->widget_mainRoad->setSoundCardRoadList(SoundCards.getSoundCardRoadList());
-    ui->widget_secondRoad->setSoundCardRoadList(SoundCards.getSoundCardRoadList());
-
+    /* 设置可选的声卡通道信息 */
+    setSoundCardRoadList(SoundCards.getCurrentSoundCardInfo());
 
     /* 连接信号和槽 */
     connect(ui->pBtn_add, &QPushButton::clicked, this, &CompareItemDialog::do_pBtn_add_clicked);
@@ -50,6 +48,15 @@ CompareItemDialog::~CompareItemDialog()
     delete ui;
 }
 
+/* 设置可选的声卡通道信息 */
+void CompareItemDialog::setSoundCardRoadList(const SoundCardInfo_t& soundCardInfo)
+{
+    m_soundCardInfo = soundCardInfo;
+    /* 设置已有两个通道的可选录音通道 */
+    ui->widget_mainRoad->setSoundCardRoadList(m_soundCardInfo);
+    ui->widget_secondRoad->setSoundCardRoadList(m_soundCardInfo);
+}
+
 
 /* 设置默认的参数 */
 void CompareItemDialog::setDefaultParams(const CompareItemInfo_t& item)
@@ -83,12 +90,12 @@ void CompareItemDialog::setDefaultParams(const CompareItemInfo_t& item)
     {
         if(road.nCompareRoadNum == 1) // 主通道
         {
-            ui->widget_mainRoad->setSoundCardRoadList(SoundCards.getSoundCardRoadList());
+            ui->widget_mainRoad->setSoundCardRoadList(m_soundCardInfo);
             ui->widget_mainRoad->setDefaultParams(road);
         }
         else if(road.nCompareRoadNum == 2) // 第二通道
         {
-            ui->widget_secondRoad->setSoundCardRoadList(SoundCards.getSoundCardRoadList());
+            ui->widget_secondRoad->setSoundCardRoadList(m_soundCardInfo);
             ui->widget_secondRoad->setDefaultParams(road);
         }
     }
@@ -274,7 +281,7 @@ SingleCompareRoadWidget* CompareItemDialog::addOneRoadWidget(int nIndex, bool bD
     pWgt->setIndex(nIndex);
     pWgt->setDelBtnVisible(bDelBtnVisible);
     /* 设置可选通道列表 */
-    pWgt->setSoundCardRoadList(SoundCards.getSoundCardRoadList());
+    pWgt->setSoundCardRoadList(m_soundCardInfo);
     pWgt->setStyleSheet(m_qssRecordRoad);
     pLayout->insertWidget(m_listOtherRoadWgt.size(), pWgt);
     m_listOtherRoadWgt.append(pWgt);

+ 7 - 3
SettingLibrary/Modules/Basic/compareitemdialog.h

@@ -33,6 +33,10 @@ public:
     explicit CompareItemDialog(QWidget *parent = nullptr);
     ~CompareItemDialog();
 
+    /* 设置可选的声卡通道信息 */
+    void setSoundCardRoadList(const SoundCardInfo_t& soundCardInfo);
+    
+
     /* 设置默认的参数 */
     void setDefaultParams(const CompareItemInfo_t& item);
 
@@ -75,12 +79,12 @@ private:
 
 private:
     Ui::CompareItemWidget *ui;
-    QList<SingleCompareRoadWidget*> m_listOtherRoadWgt;
 
-    CompareItemInfo_t m_compareItemInfo;    /* 对比项信息 */
+    SoundCardInfo_t m_soundCardInfo;        /* 声卡信息 */
 
+    QList<SingleCompareRoadWidget*> m_listOtherRoadWgt;
+    CompareItemInfo_t m_compareItemInfo;    /* 对比项信息 */
     QString m_qssRecordRoad;                /* 录音通道的样式表 */
-
 };
 
 #endif // COMPAREITEMDIALOG_H

+ 0 - 1
SettingLibrary/Modules/Basic/compareitemlistdialog.h

@@ -68,7 +68,6 @@ private:
 private:
     Ui::CompareItemListWidget *ui;
 
-
     QStandardItemModel* m_model;    /* 表格模型,存储数据 */
     CSortModel* m_sortModel;        /* 排序模型 */
 

+ 17 - 6
SettingLibrary/Modules/Basic/singlecompareroadwidget.cpp

@@ -1,5 +1,7 @@
 #include "singlecompareroadwidget.h"
 #include "ui_singlecompareroadwidget.h"
+#include "customcombobox.h"
+
 
 SingleCompareRoadWidget::SingleCompareRoadWidget(QWidget *parent)
     : QWidget(parent)
@@ -8,6 +10,9 @@ SingleCompareRoadWidget::SingleCompareRoadWidget(QWidget *parent)
 {
     ui->setupUi(this);
 
+    /* 设置comboBox阴影 */
+    ui->comboBox_soundCardNum->setViewShadowEffect();
+
     connect(ui->btnDel, &QPushButton::clicked, this, [this]{emit deleted(m_nIndex);});
 }
 
@@ -28,15 +33,18 @@ void SingleCompareRoadWidget::setDelBtnVisible(bool bVisible)
 
 
 /* 设置声卡通道列表 */
-void SingleCompareRoadWidget::setSoundCardRoadList(const QList<SoundCardRoadInfo_t>& listRoad)
+void SingleCompareRoadWidget::setSoundCardRoadList(const SoundCardInfo_t& soundCard)
 {
+    m_soundCardInfo = soundCard;
+
     ui->comboBox_soundCardNum->clear();
-    for(const auto& road : listRoad)
+    for(const auto& it : m_soundCardInfo.listRoad)
     {
-        /* 显示的内容 声卡名:通道号 */
-        QString str = QString("%1:%2").arg(road.strSoundCardName).arg(road.roadInfo.nRoadNum);
-        ui->comboBox_soundCardNum->addItem(str, QVariant::fromValue(road));
+        QString strRoadName = QString("%1:%2").arg(m_soundCardInfo.strSoundCardName).arg(it.nRoadNum);
+        ui->comboBox_soundCardNum->addItem(strRoadName, QVariant::fromValue(it.nRoadNum));
     }
+    /* 默认选择第一个 */
+    ui->comboBox_soundCardNum->setCurrentIndex(0);
 }
 
 /* 设置默认参数,设置之前需要先设置完成声卡可选通道列表 */
@@ -85,7 +93,10 @@ QString SingleCompareRoadWidget::getRoadName() const
 SoundCardRoadInfo_t SingleCompareRoadWidget::getSoundCardRoadInfo()
 {
     SoundCardRoadInfo_t roadInfo;
-    roadInfo = ui->comboBox_soundCardNum->currentData().value<SoundCardRoadInfo_t>();
+    roadInfo.nSoundCardNum = m_soundCardInfo.nSoundCardNum;
+    roadInfo.strSoundCardID = m_soundCardInfo.strSoundCardID;
+    roadInfo.strSoundCardName = m_soundCardInfo.strSoundCardName;
+    roadInfo.roadInfo.nRoadNum = ui->comboBox_soundCardNum->currentData().value<int>();
     return roadInfo;
 }
 

+ 3 - 1
SettingLibrary/Modules/Basic/singlecompareroadwidget.h

@@ -25,7 +25,7 @@ public:
     void setDelBtnVisible(bool bVisible);
 
     /* 设置声卡通道列表 */
-    void setSoundCardRoadList(const QList<SoundCardRoadInfo_t>& listRoad);
+    void setSoundCardRoadList(const SoundCardInfo_t& sounCard);
     /* 设置默认参数,设置之前需要先设置完成声卡可选通道列表 */
     void setDefaultParams(const CompareItemRoadInfo_t& roadInfo);
 
@@ -48,6 +48,8 @@ signals:
 private:
     Ui::SingleCompareRoadWidget *ui;
 
+    SoundCardInfo_t m_soundCardInfo;  /* 声卡信息 */
+
     int m_nIndex;
 };
 

+ 8 - 1
SettingLibrary/Modules/Basic/singlecompareroadwidget.ui

@@ -190,7 +190,7 @@ QPushButton#btnDel:hover
        </widget>
       </item>
       <item>
-       <widget class="QComboBox" name="comboBox_soundCardNum">
+       <widget class="CustomComboBox" name="comboBox_soundCardNum">
         <property name="minimumSize">
          <size>
           <width>300</width>
@@ -261,6 +261,13 @@ QPushButton#btnDel:hover
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>CustomComboBox</class>
+   <extends>QComboBox</extends>
+   <header location="global">customcombobox.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>

+ 1 - 0
SettingLibrary/Modules/CheckPeriod/onedetectplan.cpp

@@ -45,6 +45,7 @@ OneDetectPlan::OneDetectPlan(eWeekType type, QWidget *parent) :
     ui->dateEdit->setDisplayFormat("yyyy-MM-dd");
     /* 禁止修改日期 */
     ui->dateEdit->setManualDisableEdit(true, true);
+    ui->dateEdit->setCalendarPopup(true);
 
     /* 禁用comboBox滚动修改 */
     ui->comboBox->setWheelDisabled(true);

+ 11 - 2
SettingLibrary/setinfomanager.cpp

@@ -13,6 +13,8 @@
 #include "GlobalVariable.h"
 #include "CompareItemData.h"
 #include "setinfowidget.h"
+#include "SoundCardData.h"
+
 
 SetInfoManager::SetInfoManager(QObject *parent)
     : QObject(parent)
@@ -240,9 +242,16 @@ bool SetInfoManager::getSystemConfig()
                 SPDLOG_ERROR("获取数据库设置失败");
             }
         }
-        else if(Config_DetectPeriod == it.key())
+        else if(Config_SoundCardInfo == it.key())
         {
-        } else
+            QMap<int, SoundCardInfo_t> soundCardInfo;
+            if(!SysConfig.getSoundCardInfoFromJson(it.value(), soundCardInfo))
+            {
+                SPDLOG_ERROR("获取声卡信息失败");
+            }
+            SoundCards.setSoundCardInfo(soundCardInfo); // 设置声卡信息到全局管理器
+        } 
+        else
         {
             SPDLOG_DEBUG("未知的系统配置项: {}", it.key());
         }

+ 55 - 19
common/DataManager/SoundCardData.cpp

@@ -3,38 +3,74 @@
 
 SoundCardDataManager::~SoundCardDataManager()
 {
-    m_listSoundCard.clear();
 }
 
-/* 初始化声卡列表 */
-void SoundCardDataManager::initSoundCardList(QList<SoundCardInfo_t>& listSoundCard)
+/* 设置声卡列表 */
+void SoundCardDataManager::setSoundCardInfo(QMap<int, SoundCardInfo_t>& soundInfo)
 {
-    m_listSoundCard.clear();
-    m_listSoundCard = listSoundCard;
+    m_mapSoundCardInfo.clear();
+    m_mapSoundCardInfo = soundInfo;
+}
 
-    for(const auto& soundCard : m_listSoundCard)
+/* 获取单个声卡信息 */
+SoundCardInfo_t SoundCardDataManager::getOneSoundCardInfo(int nSoundCardNum) const
+{
+    auto it = m_mapSoundCardInfo.find(nSoundCardNum);
+    if(it != m_mapSoundCardInfo.end())
     {
-        SoundCardRoadInfo_t roadInfo;
-        roadInfo.nSoundCardNum = soundCard.nSoundCardNum;
-        roadInfo.strSoundCardID = soundCard.strSoundCardID;
-        roadInfo.strSoundCardName = soundCard.strSoundCardName;
+        return it.value(); // 返回找到的声卡信息
+    }
+    SoundCardInfo_t emptyInfo;
+    emptyInfo.nSoundCardNum = -1; // 未找到时返回无效信息
+    emptyInfo.strSoundCardID = "";
+    emptyInfo.strSoundCardName = "";
+    return emptyInfo;
+}
 
-        for(const auto& road : soundCard.listRoad)
-        {
-            roadInfo.roadInfo = road; // 直接使用通道信息
-            m_listSoundCardRoad.append(roadInfo);
-        }
+/* 设置当前声卡 */
+bool SoundCardDataManager::setCurrentSoundCard(int nSoundCardNum)
+{
+    auto it = m_mapSoundCardInfo.find(nSoundCardNum);
+    if(it == m_mapSoundCardInfo.end())
+    {
+        return false;
     }
+    m_currentSoundCardInfo = it.value(); // 设置当前声卡信息
+    m_listSoundCardRoad.clear(); // 清空现有的通道列表
+    const SoundCardInfo_t& soundCardInfo = it.value();
+    for(const auto& road : soundCardInfo.listRoad)
+    {
+        SoundCardRoadInfo_t roadInfo;
+        roadInfo.nSoundCardNum = soundCardInfo.nSoundCardNum;
+        roadInfo.strSoundCardID = soundCardInfo.strSoundCardID;
+        roadInfo.strSoundCardName = soundCardInfo.strSoundCardName;
+        roadInfo.roadInfo = road; // 设置通道信息
+        m_listSoundCardRoad.append(roadInfo); // 添加到列表中
+    }
+
+    return true;
 }
 
+
 /* 根据声卡编号和录音通道编号获取声卡信息 */
 SoundCardRoadInfo_t SoundCardDataManager::getSoundCardRoadInfo(int nSoundCardNum, int nChannelID)
 {
-    for(const auto& soundCard : m_listSoundCardRoad)
+    for(const auto& soundCard : m_mapSoundCardInfo)
     {
-        if(soundCard.nSoundCardNum == nSoundCardNum && soundCard.roadInfo.nChannelID == nChannelID)
+        if(nSoundCardNum == soundCard.nSoundCardNum)
         {
-            return soundCard; // 找到匹配的声卡和通道信息
+            for(const auto& road : soundCard.listRoad)
+            {
+                if(road.nRoadNum == nChannelID)
+                {
+                    SoundCardRoadInfo_t roadInfo;
+                    roadInfo.nSoundCardNum = soundCard.nSoundCardNum;
+                    roadInfo.strSoundCardID = soundCard.strSoundCardID;
+                    roadInfo.strSoundCardName = soundCard.strSoundCardName;
+                    roadInfo.roadInfo = road; // 设置通道信息
+                    return roadInfo; // 返回找到的声卡通道信息
+                }
+            }
         }
     }
     SoundCardRoadInfo_t emptyInfo;
@@ -46,7 +82,7 @@ SoundCardRoadInfo_t SoundCardDataManager::getSoundCardRoadInfo(int nSoundCardNum
 }
 
 /* 获取带有声卡信息的通道列表 */
-const QList<SoundCardRoadInfo_t>& SoundCardDataManager::getSoundCardRoadList() const
+const QList<SoundCardRoadInfo_t>& SoundCardDataManager::getCurrSoundCardRoadList() const
 {
     return m_listSoundCardRoad;
 }

+ 21 - 8
common/DataManager/SoundCardData.h

@@ -7,6 +7,7 @@
 
 /**
  * @brief 声卡信息管理器
+ *        1、这里可以设置当前声卡信息,获取当前选择的声卡信息,以免多个窗口声卡传递链特别长
  * 
  */
 
@@ -26,20 +27,32 @@ public:
         static SoundCardDataManager instance;
         return instance;
     }
-    /* 初始化声卡列表 */
-    void initSoundCardList(QList<SoundCardInfo_t>& listSoundCard);
-
+    /* 设置声卡列表 */
+    void setSoundCardInfo(QMap<int, SoundCardInfo_t>& soundInfo);
     /* 获取声卡列表 */
-    const QList<SoundCardInfo_t>& getSoundCardList() const { return m_listSoundCard; }
+    const QMap<int, SoundCardInfo_t>& getSoundCardInfo() const { return m_mapSoundCardInfo; }
+
+    /* 获取单个声卡信息 */
+    SoundCardInfo_t getOneSoundCardInfo(int nSoundCardNum) const;
+    /* 设置当前声卡 */
+    bool setCurrentSoundCard(int nSoundCardNum);
+    /* 获取当前声卡信息 */
+    const SoundCardInfo_t& getCurrentSoundCardInfo() const { return m_currentSoundCardInfo; }
 
     /* 根据声卡编号和录音通道编号获取声卡信息 */
     SoundCardRoadInfo_t getSoundCardRoadInfo(int nSoundCardNum, int nChannelID);
-    /* 获取带有声卡信息的通道列表 */
-    const QList<SoundCardRoadInfo_t>& getSoundCardRoadList() const;
+    /* 获取当前带有声卡信息的通道列表 */
+    const QList<SoundCardRoadInfo_t>& getCurrSoundCardRoadList() const;
+    
 
 private:
-    QList<SoundCardInfo_t> m_listSoundCard;             /* 声卡信息列表 */
-    QList<SoundCardRoadInfo_t> m_listSoundCardRoad;     /* 带有声卡信息的通道列表,数据以上面的为准 */
+    
+    /* 声卡信息,key为声卡编号 */
+    QMap<int, SoundCardInfo_t> m_mapSoundCardInfo;
+    /* 当前选择的声卡编号 */
+    SoundCardInfo_t m_currentSoundCardInfo;
+    /* 带有声卡信息的通道列表,设置当前声卡信息的时候会更新 */
+    QList<SoundCardRoadInfo_t> m_listSoundCardRoad;
 };
 
 

+ 66 - 0
common/DataManager/SystemConfig.cpp

@@ -228,3 +228,69 @@ void SystemConfigInfo::setDetectPeriodConfig(const QMap<int, DetectPeriodConfig_
 }
 
 
+/* 将声卡信息转换成json */
+bool SystemConfigInfo::setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const
+{
+    try {
+        nJson jsonConfig;
+        for (const auto& soundCard : soundCardInfo) 
+        {
+            nJson soundCardJson;
+            soundCardJson["SoundCardNum"] = soundCard.nSoundCardNum;
+            soundCardJson["SoundCardID"] = soundCard.strSoundCardID.toStdString();
+            soundCardJson["SoundCardName"] = soundCard.strSoundCardName.toStdString();
+            soundCardJson["SoundCardDriver"] = soundCard.strSoundCardDriver.toStdString();
+
+            nJson roadArray = nJson::array();
+            for (const auto& road : soundCard.listRoad) {
+                nJson roadJson;
+                roadJson["RoadNum"] = road.nRoadNum;
+                // roadJson["ChannelID"] = road.nChannelID;
+                // roadJson["ChannelName"] = road.strChannelName.toStdString();
+                roadArray.push_back(roadJson);
+            }
+            soundCardJson["Roads"] = roadArray;
+
+            jsonConfig[std::to_string(soundCard.nSoundCardNum)] = soundCardJson;
+        }
+
+        strJson = jsonConfig.dump();
+    }nJsonCatch
+
+    return true;
+}
+
+/* 将json转换成声卡信息 */
+bool SystemConfigInfo::getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo)
+{
+    try {
+        nJson jsonConfig = nJson::parse(jsonStr);
+        soundCardInfo.clear();
+
+        for (auto& item : jsonConfig) 
+        {
+            SoundCardInfo_t soundCard;
+            soundCard.nSoundCardNum = item["SoundCardNum"].get<int>();
+            soundCard.strSoundCardID = QString::fromStdString(item["SoundCardID"].get<std::string>());
+            soundCard.strSoundCardName = QString::fromStdString(item["SoundCardName"].get<std::string>());
+            soundCard.strSoundCardDriver = QString::fromStdString(item["SoundCardDriver"].get<std::string>());
+            
+            soundCard.listRoad.clear();
+            auto roadsArray = item["Roads"];
+            for (const auto& roadItem : roadsArray) 
+            {
+                OneRoadInfo_t road;
+                road.nRoadNum = roadItem["RoadNum"].get<int>();
+                // road.nChannelID = roadItem["ChannelID"].get<int>();
+                // road.strChannelName = QString::fromStdString(roadItem["ChannelName"].get<std::string>());
+                soundCard.listRoad.append(road);
+            }
+
+            soundCardInfo[soundCard.nSoundCardNum] = soundCard;
+        }
+    }nJsonCatch
+
+    return true;
+}
+
+

+ 37 - 2
common/DataManager/SystemConfig.h

@@ -1,6 +1,19 @@
 #ifndef __SYSTEMCONFIG_H__
 #define __SYSTEMCONFIG_H__
 
+/**
+ * @file SystemConfig.h
+ * @author your name (you@domain.com)
+ * @brief 
+ * @version 0.1
+ * @date 2025-07-15
+ * 
+ * @copyright Copyright (c) 2025
+ *
+ *  1、这个类是Server和Setting共用的系统配置类
+ * 
+ */
+
 
 #include "GlobalVariable.h"
 #include "SystemConfigStruct.h"
@@ -15,7 +28,8 @@ enum class eSystemConfigType
     eSCT_NoiseBase,             // 噪音检测基础
     eSCT_NoiseParam,            // 噪音检测参数
     eSCT_Database,              // 数据库设置
-    eSCT_DetectPeriod           // 检测时段
+    eSCT_DetectPeriod,          // 检测时段
+    eSCT_SoundCardInfo,         // 声卡信息
 };
 
 
@@ -25,6 +39,8 @@ enum class eSystemConfigType
 #define Config_NoiseParam "ACAS_NoiseParam"     // 噪音检测参数
 #define Config_Database "ACAS_Database"         // 数据库设置
 #define Config_DetectPeriod "ACAS_DetectPeriod" // 检测时段配置
+#define Config_SoundCardInfo "ACAS_SoundCardInfo" // 声卡信息配置
+
 
 /**
  * @brief ACA系统的设置信息
@@ -46,6 +62,17 @@ public:
         return instance;
     }
 
+    /*系统配置的Key  */
+    // const QMap<eSystemConfigType, QString> mapSysConfigKey = {
+    //     {eSystemConfigType::eSCT_BaseConfig, "ACAS_Base"},
+    //     {eSystemConfigType::eSCT_CompareAI, "ACAS_CompareAI"},
+    //     {eSystemConfigType::eSCT_NoiseBase, "ACAS_NoiseBase"},
+    //     {eSystemConfigType::eSCT_NoiseParam, "ACAS_NoiseParam"},
+    //     {eSystemConfigType::eSCT_Database, "ACAS_Database"},
+    //     {eSystemConfigType::eSCT_DetectPeriod, "ACAS_DetectPeriod"},
+    //     {eSystemConfigType::eSCT_SoundCardInfo, "ACAS_SoundCardInfo"}
+    // };
+
     /* 系统设置类型 */
     const QMap<eSystemConfigType, std::string> mapSysConfigDesc = {
         {eSystemConfigType::eSCT_BaseConfig, "基础配置"},
@@ -53,7 +80,8 @@ public:
         {eSystemConfigType::eSCT_NoiseBase, "噪音检测基础设置"},
         {eSystemConfigType::eSCT_NoiseParam, "噪音检测参数"},
         {eSystemConfigType::eSCT_Database, "数据库设置信息"},
-        {eSystemConfigType::eSCT_DetectPeriod, "检测时段信息"}
+        {eSystemConfigType::eSCT_DetectPeriod, "检测时段信息"}, 
+        {eSystemConfigType::eSCT_SoundCardInfo, "系统的声卡信息"}
     };
 
     /*-------------------------------------------------------------------------------------*/
@@ -111,6 +139,13 @@ public:
     /* 设置检测时段配置 */
     void setDetectPeriodConfig(const QMap<int, DetectPeriodConfig_t>& config);
 
+    /*-------------------------------------------------------------------------------------*/
+    /* 声卡信息有单独的声卡信息类,不在这里存储 */
+    /* 将声卡信息转换成json */
+    bool setSoundCardInfoToJson(const QMap<int, SoundCardInfo_t>& soundCardInfo, std::string& strJson) const;
+    /* 将json转换成声卡信息 */
+    bool getSoundCardInfoFromJson(const std::string& jsonStr, QMap<int, SoundCardInfo_t>& soundCardInfo);
+
 public:
     
 

+ 5 - 0
common/DataManager/SystemConfigStruct.h

@@ -114,6 +114,11 @@ struct DatabaseConfig_t
 };
 
 
+/* =============================================================================
+ * 声卡信息结构体
+ * ============================================================================= */
+
+
 
 
 #endif // __SYSTEMCONFIGSTRUCT_H__

+ 3 - 2
common/GlobalInfo/GlobalVariable.h

@@ -74,7 +74,7 @@ struct OneRoadInfo_t
  */
 struct SoundCardInfo_t
 {
-    int nSoundCardNum = -1;             /* 声卡编号 */
+    int nSoundCardNum = -1;             /* 声卡编号,系统上的物理编号 */
     QString strSoundCardID;             /* 声卡ID,这个是声卡名称,可以用来打开 */
     QString strSoundCardName;           /* 声卡名称 */
     QString strSoundCardDriver;         /* 声卡驱动名称 */
@@ -321,7 +321,8 @@ enum class EThreadType
     Type_CreateLongWAV,         /* 生成长文件线程 */
     Type_RtpSend,               /* RTP发送线程 */
     Type_ConsistencyCheck,      /* 一致性检查线程 */
-    Type_CheckDBAndPhase        /* 检查音量和反相线程 */
+    Type_CheckDBAndPhase,       /* 检查音量和反相线程 */
+    Type_CompareItem,           /* 对比项线程 */
 };
 
 /**