Kaynağa Gözat

V0.6
1、修复了一些问题

Apple 1 ay önce
ebeveyn
işleme
d665abace5
32 değiştirilmiş dosya ile 804 ekleme ve 353 silme
  1. 38 46
      SQL/ACAServer.sql
  2. 0 0
      SQL/CreateProcedures.sqlbook
  3. 48 0
      SQL/CreateTable.sqlbook
  4. 2 2
      Server/ACAServer.cpp
  5. 3 3
      Server/DataStruct/CalculateAudio.cpp
  6. 17 14
      Server/GlobalInfo/GlobalInfo.h
  7. 20 15
      Server/ThreadCalculate/CalculateDBThread.cpp
  8. 5 5
      Server/ThreadCalculate/CompareDoubleThread.cpp__
  9. 3 1
      Server/ThreadCalculate/CompareItemThread.cpp
  10. 15 9
      Server/ThreadCalculate/ConsistencyCompareThread.cpp
  11. 3 0
      Server/ThreadCalculate/ConsistencyCompareThread.h
  12. 8 8
      Server/ThreadCalculate/NoiseDetectThread.cpp
  13. 0 152
      Server/ThreadManager/ThreadAlarmManager.cpp
  14. 268 0
      Server/ThreadManager/ThreadWriteDBManager.cpp
  15. 36 14
      Server/ThreadManager/ThreadWriteDBManager.h
  16. 47 13
      Server/ThreadRecord/CreateRecordFileThread.cpp
  17. 4 2
      Server/ThreadRecord/CreateRecordFileThread.h
  18. 4 4
      Server/ThreadRecord/CreateWAVThread.cpp
  19. 1 0
      Server/ThreadRecord/RecordThread.h
  20. 1 1
      Server/common/LHLog/LHLogInit.cpp
  21. 3 0
      SettingLibrary/CMakeLists.txt
  22. 8 0
      SettingLibrary/Modules/Database/databasewidget.cpp
  23. 106 54
      SettingLibrary/Modules/Database/databasewidget.ui
  24. BIN
      ThreeLib/libsignalcompare-v1.1.so
  25. BIN
      ThreeLib/libsignalcompare_bck.so
  26. 4 0
      common/DataManager/SystemConfig.cpp
  27. 3 1
      common/DataManager/SystemConfigStruct.cpp
  28. 2 0
      common/DataManager/SystemConfigStruct.h
  29. 28 1
      common/GlobalInfo/GlobalVariable.cpp
  30. 27 2
      common/GlobalInfo/GlobalVariable.h
  31. 93 6
      common/Network/FromWebAPI.cpp
  32. 7 0
      common/Network/FromWebAPI.h

+ 38 - 46
SQL/ACAServer.sql

@@ -25,14 +25,33 @@ FROM tACADetectPeriod;
 SELECT *
 FROM tACAAlarmInfo;
 
+#倒叙获取报警信息
+SELECT *
+FROM tACAAlarmInfo
+ORDER BY PKID DESC;
+
+
+
+#录音文件信息
+SELECT *
+FROM tACARecordFile;
+
 
 
+#录音文件根据对比项ID归为一组
+SELECT ItemID, COUNT(*) AS FileCount
+FROM tACARecordFile
+GROUP BY ItemID;
 
 
 #清空报警信息内容
 DELETE FROM tACAAlarmInfo;
 
 
+SELECT *
+FROM tSystemConfig;
+
+
 #插入报警信息
 INSERT INTO tACAAlarmInfo (
     ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType, 
@@ -113,52 +132,25 @@ CALL ACAS_InsertTwoAlarmInfo(
     @alarmFilePath2, @fileAlarmStartPos2
 );
 
-"itemID1": 2,
-"itemName1": "two",
-"alarmType1": 4,
-"soundCardNum1": 1,
-"soundCardName1": "主通道",
-"soundCardRoadNum1": 0,
-"compareRoadNum1": 1,
-"compareRoadName1": "主通道",
-"compareRoadType1": 0,
-"alarmStartTime1": "2025-08-07 16:14:12",
-"alarmEndTime1": "2025-08-07 16:14:37",
-"alarmDuration1": 24,
-"alarmFilePath1": "/data/home/Apple/Work/11-ACAServer/RecordFile/AlarmWav/2025-08-07/CompareItemID_2/Road1_Consistency_20250807_161412-20250807_161437.wav",
-"fileAlarmStartPos1": 0,
-"itemID2": 2,
-"itemName2": "two",
-"alarmType2": 4,
-"soundCardNum2": 2,
-"soundCardName2": "第2通道",
-"soundCardRoadNum2": 0,
-"compareRoadNum2": 2,
-"compareRoadName2": "第2通道",
-"compareRoadType2": 1,
-"alarmStartTime2": "2025-08-07 16:14:12",
-"alarmEndTime2": "2025-08-07 16:14:37",
-"alarmDuration2": 24,
-"alarmFilePath2": "/data/home/Apple/Work/11-ACAServer/RecordFile/AlarmWav/2025-08-07/CompareItemID_2/Road2_Consistency_20250807_161412-20250807_161437.wav",
-"fileAlarmStartPos2": 0
-
-"EQM_CESHI"."ACAS_InsertTwoAlarmInfo"(
-    :"itemID1", :"itemName1", :"alarmType1", :"soundCardNum1", :"soundCardName1", :"soundCardRoadNum1", :"compareRoadNum1", :"compareRoadName1", :"compareRoadType1", 
-    :"alarmStartTime1", :"alarmEndTime1",
-     :"alarmDuration1", :"alarmFilePath1", 
-     :"fileAlarmStartPos1", 
-     :"itemID2", 
-     :"itemName2", :"alarmType2", :"soundCardNum2",
-      :"soundCardName2", :"soundCardRoadNum2", :"compareRoadNum2", 
-      :"compareRoadName2", :"compareRoadType2", :"alarmStartTime2",
-       :"alarmEndTime2", :"alarmDuration2", :"alarmFilePath2", :"fileAlarmStartPos2");
-"EQM_CESHI"."ACAS_InsertTwoAlarmInfo"(
-    2, 'two', 4, 1, '主通道', 0, 1, '主通道', 0, '2025-08-07 16:14:12', '2025-08-07 16:14:37',
-    24, '/data/home/Apple/Work/11-ACAServer/RecordFile/AlarmWav/2025-08-07/CompareItemID_2/Road1_Consistency_20250807_161412-20250807_161437.wav', 0,
-    2, 'two', 4, 2, '第2通道', 0, 2, '第2通道', 1, '2025-08-07 16:14:12', '2025-08-07 16:14:37', 24, 
-    '/data/home/Apple/Work/11-ACAServer/RecordFile/AlarmWav/2025-08-07/CompareItemID_2/Road2_Consistency_20250807_161412-20250807_161437.wav', 0
+
+
+#插入录音文件信息
+INSERT INTO tACARecordFile (
+    ItemID, ItemName, ItemRoadNum, ItemRoadName, SoundCardNum, SoundCardRoadNum,
+    FileStartTime, FileEndTime, FileDuration, FilePath
+) VALUES (
+    @itemID, @itemName, @itemRoadNum, @itemRoadName, @soundCardNum, @soundCardRoadNum,
+    @fileStartTime, @fileEndTime, @fileDuration, @filePath
 );
 
-"EQM_CESHI"."ACAS_InsertTwoAlarmInfo"(
-    2, 'two', 4, 1, '主通道', 0, 1, '主通道', 0, '2025-08-07 16:14:12', 
+
+#更新录音文件信息
+UPDATE tACARecordFile
+SET FileEndTime = @fileEndTime, FilePath = @filePath, FileDuration = @fileDuration
+WHERE ItemID = @itemID AND ItemRoadNum = @itemRoadNum 
+    AND SoundCardNum = @soundCardNum AND SoundCardRoadNum = @soundCardRoadNum
+    AND FileStartTime = @fileStartTime;
+
+
+
 

+ 0 - 0
SQL/ACAServer.sqlbook → SQL/CreateProcedures.sqlbook


+ 48 - 0
SQL/ACASetting.sqlbook → SQL/CreateTable.sqlbook

@@ -192,3 +192,51 @@ CREATE INDEX idx_tACAAlarmInfo_SoundCardRoadNum ON tACAAlarmInfo (SoundCardRoadN
 CREATE INDEX idx_tACAAlarmInfo_CompareRoadNum ON tACAAlarmInfo (CompareRoadNum);
 CREATE INDEX idx_tACAAlarmInfo_AlarmStartTime ON tACAAlarmInfo (AlarmStartTime);
 CREATE INDEX idx_tACAAlarmInfo_AlarmEndTime ON tACAAlarmInfo (AlarmEndTime);
+
+-- SQLBook: Code
+-- Active: 1752718919967@@192.1.2.61@5236@EQM_CESHI
+#创建记录录音文件的表格
+CREATE TABLE tACARecordFile
+(
+    PKID INT PRIMARY KEY AUTO_INCREMENT,
+    ItemID INT NOT NULL,                -- 对比项ID
+    ItemName VARCHAR(64) NOT NULL,    -- 对比项名称
+    ItemRoadNum INT NOT NULL,           -- 通道编号
+    ItemRoadName VARCHAR(64) NOT NULL, -- 通道名称
+    SoundCardNum INT NOT NULL,          -- 声卡编号
+    SoundCardRoadNum INT NOT NULL,      -- 声卡通道编号
+    FileStartTime VARCHAR(32) NOT NULL, -- 录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)
+    FileEndTime VARCHAR(32) NOT NULL,   -- 录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)
+    FileDuration INT NOT NULL,          -- 录音文件持续时间(秒数)
+    FilePath VARCHAR(256) NOT NULL,     -- 录音文件路径
+    FileState INT DEFAULT 0,            -- 录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除
+
+    FOREIGN KEY (ItemID) REFERENCES tACACompareItems(ItemID)
+        ON DELETE CASCADE
+);
+
+-- 表注释
+COMMENT ON TABLE tACARecordFile IS 'ACA录音文件记录表';
+-- 字段注释
+COMMENT ON COLUMN tACARecordFile.PKID IS '主键ID';
+COMMENT ON COLUMN tACARecordFile.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACARecordFile.ItemName IS '对比项名称';
+COMMENT ON COLUMN tACARecordFile.ItemRoadNum IS '通道编号';
+COMMENT ON COLUMN tACARecordFile.ItemRoadName IS '通道名称';
+COMMENT ON COLUMN tACARecordFile.SoundCardNum IS '声卡编号';
+COMMENT ON COLUMN tACARecordFile.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACARecordFile.FileStartTime IS '录音开始时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACARecordFile.FileEndTime IS '录音结束时间 (格式: YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACARecordFile.FileDuration IS '录音文件持续时间(秒数)';
+COMMENT ON COLUMN tACARecordFile.FilePath IS '录音文件路径';
+COMMENT ON COLUMN tACARecordFile.FileState IS '录音文件状态,0-未知状态,1-正在录音,2-录音完成,3-文件已删除';
+-- 创建索引
+CREATE INDEX idx_tACARecordFile_ItemID ON tACARecordFile (ItemID);
+CREATE INDEX idx_tACARecordFile_ItemRoadNum ON tACARecordFile (ItemRoadNum);
+CREATE INDEX idx_tACARecordFile_SoundCardNum ON tACARecordFile (SoundCardNum);
+CREATE INDEX idx_tACARecordFile_SoundCardRoadNum ON tACARecordFile (SoundCardRoadNum);
+CREATE INDEX idx_tACARecordFile_FileStartTime ON tACARecordFile (FileStartTime);
+CREATE INDEX idx_tACARecordFile_FileEndTime ON tACARecordFile (FileEndTime);
+CREATE INDEX idx_tACARecordFile_FileDuration ON tACARecordFile (FileDuration);
+
+

+ 2 - 2
Server/ACAServer.cpp

@@ -7,7 +7,7 @@
 #include "SystemConfig.h"
 #include "ThreadPool.h"
 #include "ThreadManager.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 #include "RtpServer.h"
 #include "LHLogInit.h"
 
@@ -163,7 +163,7 @@ bool ACAServer::startService()
     /* 开启录音通道检查线程 */
     CPPTP.add_task(&ACAServer::thread_deleteRecordThread, this);
     /* 开启处理报警信息的线程 */
-    CPPTP.add_task(&ThreadAlarmManager::thread_task, &AlarmManager);
+    CPPTP.add_task(&ThreadWriteDBManager::thread_task, &WriteDB);
     /* 开启RTP监听服务线程 */
     CPPTP.add_task(&ACAServer::thread_RTPServer, this);
 

+ 3 - 3
Server/DataStruct/CalculateAudio.cpp

@@ -502,7 +502,7 @@ bool CaculateDBData::calculateSilent(const StVolumeParam& param, int& startPos,
     }
     if (ringQueue.QueueSize() < (silentDuration + m_offset) || silentDuration <= 0)
     {
-        SPDLOG_DEBUG("队列中数据暂不满足静音持续时间检测 {}秒 的要求,当前队列大小为{}秒", silentDuration + m_offset, ringQueue.QueueSize());
+        // SPDLOG_DEBUG("队列中数据暂不满足静音持续时间检测 {}秒 的要求,当前队列大小为{}秒", silentDuration + m_offset, ringQueue.QueueSize());
         return false;
     }
     // if (silentDuration >= avgDBSeconds)
@@ -573,7 +573,7 @@ bool CaculateDBData::calculateOverload(const StVolumeParam& param, int& startPos
 	/* 判断队列中数据数量是否满足计算需要的数目 */
 	if(ringQueue.QueueSize() < calculateDuration || calculateDuration <= 0)
 	{
-		SPDLOG_DEBUG("队列中数据暂不满足过载持续时间检测 {}秒 的要求,当前队列大小为 {}秒", calculateDuration, ringQueue.QueueSize());
+		// SPDLOG_DEBUG("队列中数据暂不满足过载持续时间检测 {}秒 的要求,当前队列大小为 {}秒", calculateDuration, ringQueue.QueueSize());
 		return false;
 	}
 	// if (calculateDuration >= avgDBSeconds)
@@ -658,7 +658,7 @@ bool CaculateDBData::calculatePhase(const StVolumeParam& param, int& startPos, i
 	/* 判断队列中数据数量是否满足计算需要的数目 */
 	if(ringQueue.QueueSize() < calculateDuration || calculateDuration <= 0)
 	{
-		SPDLOG_DEBUG("队列中数据暂不满足反相持续时间检测 {}秒 的要求,当前队列大小为 {}秒", calculateDuration, ringQueue.QueueSize());
+		// SPDLOG_DEBUG("队列中数据暂不满足反相持续时间检测 {}秒 的要求,当前队列大小为 {}秒", calculateDuration, ringQueue.QueueSize());
 		return false;
 	}
 	// if (calculateDuration >= avgDBSeconds)

+ 17 - 14
Server/GlobalInfo/GlobalInfo.h

@@ -63,6 +63,7 @@ public:
     QString webApiAppType() const {return m_webAPIAppType;}
     void setWebAPIInfo(const QString& url, const QString& id);
 
+
 public:
     /* 音频相关数据 */
     int32_t sampleRate() const {return m_sampleRate;}          /* 获取采样率 */
@@ -79,12 +80,14 @@ public:
 
     /* 设置根目录 */
     void setRootPath(const QString& path) { m_rootPath = path; }
+    /* 获取根目录 */
+    const QString& rootPath() const { return m_rootPath; }
     /* wav小文件路径 */
-    QString wavPath() const {return m_wavPath;}
+    const QString& wavPath() const {return m_wavPath;}
     /* 记录的长文件路径 */
-    QString longWavPath() const {return m_longWavPath;}
+    const QString& longWavPath() const {return m_longWavPath;}
     /* 报警文件路径 */
-    QString alarmWavPath() const {return m_alarmWavPath;}
+    const QString& alarmWavPath() const {return m_alarmWavPath;}
 
 
     /* 获取音频不对称百分比 */
@@ -139,6 +142,17 @@ private:
     QString m_pubTopicCompareItem = "LH_ACAServer/CompareItems";    /* 对比项发布主题 */
     QString m_pubTopicServerInfo = "LH_ACAServer/ServerInfo";       /* 服务信息发布主题 */
 
+    /* 相关的文件夹 */
+    const QString m_dirWav = "WavTemp";         /* 一致性对比的wav文件存储目录 */
+    const QString m_dirLongWav = "RecordWav";   /* 长文件存储目录 */
+    const QString m_dirAlarm = "AlarmWav";      /* 报警文件存储目录 */
+    const QString m_dirConfig = "config";       /* 配置文件存储目录 */
+
+    QString m_rootPath;                         /* 根目录 */
+    QString m_wavPath;                          /* wav文件存储路径 */
+    QString m_longWavPath;                      /* 长文件存储路径 */
+    QString m_alarmWavPath;                     /* 报警文件存储路径 */
+
     /******************** 音频基础数据 *********************/
     /* 环形队列中每个文件的大小,也是生成的wav文件的大小
        这个大小和录音时长相对应,计算方式如下
@@ -154,17 +168,6 @@ private:
     int32_t m_queueElementCount = 180;          /* 默认缓冲区的大小,也就是音频处理线程的环形队列的大小,单位是秒 */
     int32_t m_wavFileDuration = 60;             /* 一个wav小文件有多少秒的数据 */
 
-    /* 相关的文件夹 */
-    const QString m_dirWav = "WavTemp";         /* 一致性对比的wav文件存储目录 */
-    const QString m_dirLongWav = "RecordWav";   /* 长文件存储目录 */
-    const QString m_dirAlarm = "AlarmWav";      /* 报警文件存储目录 */
-    const QString m_dirConfig = "config";       /* 配置文件存储目录 */
-
-    QString m_rootPath;                         /* 根目录 */
-    QString m_wavPath;                          /* wav文件存储路径 */
-    QString m_longWavPath;                      /* 长文件存储路径 */
-    QString m_alarmWavPath;                     /* 报警文件存储路径 */
-
     /* 比对计算相关参数 */
     int m_pcmErrorPercent = 10;                 /* PCM数据不对称少于多少百分比,就判断为噪音,0表示不判断 */
     int m_pcmLessPercent = 0;                   /* PCM数据少于多少百分比,就判断为噪音,0表示不用这个算法判断噪音 */

+ 20 - 15
Server/ThreadCalculate/CalculateDBThread.cpp

@@ -4,7 +4,7 @@
 
 #include "ThreadManager.h"
 #include "GlobalInfo.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 
 
 CalculateDBThread::CalculateDBThread(CalculateThreadInfo_t& threadInfo)
@@ -100,7 +100,7 @@ void CalculateDBThread::task()
     {
         std::this_thread::sleep_for(std::chrono::milliseconds(10));
 
-        std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
+        // std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
         /* --------------------------------------------------------------------------------
          * 更新最新数据
          * --------------------------------------------------------------------------------*/
@@ -119,8 +119,8 @@ void CalculateDBThread::task()
         
         calcuDBData();
 
-        std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
-        std::chrono::microseconds duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
+        // std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
+        // std::chrono::microseconds duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime);
         // SPDLOG_LOGGER_TRACE(m_logger, "{} 计算静音、过载和反相结束, 线程耗时: {}us", m_logBase, duration.count());
     }
     /* 停止所有的报警 */
@@ -292,7 +292,9 @@ void CalculateDBThread::processSilence()
         {
             /* 开启静音报警 */
             m_alarmSilence.CompareItemID = m_threadInfo.compareItemInfo.nID;
-            m_alarmSilence.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
+            m_alarmSilence.strCompareItemName = m_threadInfo.compareItemInfo.strName;
+            m_alarmSilence.RoadInfo = m_roadInfo; // 设置通道信息
+            
             if(m_alarmSilence.CompareItemID == 1)
             {
                 m_alarmSilence.RoadType = ERoadType::RoadType_Main;
@@ -301,8 +303,6 @@ void CalculateDBThread::processSilence()
             }
 
             m_alarmSilence.isAlarm = true;
-            m_alarmSilence.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-            m_alarmSilence.RoadInfo = m_roadInfo; // 设置通道信息
             m_alarmSilence.AlarmType = EAlarmType::EAT_Silent; // 静音报警
             /* 计算开始时间,往前推判断静音需要的时间 */
             QDateTime startTime;
@@ -356,7 +356,7 @@ void CalculateDBThread::processSilence()
             }
 
             /* 将报警信息发送给写入报警信息的线程 */
-            AlarmManager.addAlarmInfo(m_alarmSilence);
+            WriteDB.addAlarmInfo(m_alarmSilence);
 
             /* 打印日志 */
             SPDLOG_LOGGER_INFO(m_logger, "{} 静音报警结束,开始时间:{},结束时间:{}",
@@ -381,7 +381,9 @@ void CalculateDBThread::processOverload()
         {
             /* 开启过载报警 */
             m_alarmOverload.CompareItemID = m_threadInfo.compareItemInfo.nID;
-            m_alarmOverload.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
+            m_alarmOverload.strCompareItemName = m_threadInfo.compareItemInfo.strName;
+            m_alarmOverload.RoadInfo = m_roadInfo; // 设置通道信息
+
             if(m_alarmOverload.CompareItemID == 1)
             {
                 m_alarmOverload.RoadType = ERoadType::RoadType_Main;
@@ -390,8 +392,6 @@ void CalculateDBThread::processOverload()
             }
 
             m_alarmOverload.isAlarm = true;
-            m_alarmOverload.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-            m_alarmOverload.RoadInfo = m_roadInfo; // 设置通道信息
             m_alarmOverload.AlarmType = EAlarmType::EAT_Overload; // 过载报警
             /* 计算开始时间,往前推设置的过载时长 */
             QDateTime startTime;
@@ -413,6 +413,10 @@ void CalculateDBThread::processOverload()
                 /* 开启录制报警音频失败 */
                 SPDLOG_LOGGER_WARN(m_logger, "{} 开启录制过载报警音频失败", m_logBase);
             }
+            SPDLOG_LOGGER_TRACE(m_logger, "{} 开启过载报警,通道信息:{}:{},开始时间:{},结束时间:{}",
+                m_logBase, m_threadInfo.compareItemInfo.nID, m_roadInfo.nCompareRoadNum,
+                m_alarmOverload.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
+                m_alarmOverload.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
 
         }else 
         {
@@ -446,7 +450,7 @@ void CalculateDBThread::processOverload()
             }
 
             /* 将报警信息发送给写入报警信息的线程 */
-            AlarmManager.addAlarmInfo(m_alarmOverload);
+            WriteDB.addAlarmInfo(m_alarmOverload);
 
 
             /* 打印日志 */
@@ -472,7 +476,9 @@ void CalculateDBThread::processPhase()
         {
             /* 开启反相报警 */
             m_alarmPhase.CompareItemID = m_threadInfo.compareItemInfo.nID;
-            m_alarmPhase.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
+            m_alarmPhase.strCompareItemName = m_threadInfo.compareItemInfo.strName;
+            m_alarmPhase.RoadInfo = m_roadInfo; // 设置通道信息
+
             if(m_alarmPhase.CompareItemID == 1)
             {
                 m_alarmPhase.RoadType = ERoadType::RoadType_Main;
@@ -481,7 +487,6 @@ void CalculateDBThread::processPhase()
             }
             
             m_alarmPhase.isAlarm = true;
-            m_alarmPhase.RoadInfo = m_roadInfo; // 设置通道信息
             m_alarmPhase.AlarmType = EAlarmType::EAT_Reversed; // 反相报警
             /* 计算开始时间,往前推设置的反相时长 */
             QDateTime startTime;
@@ -536,7 +541,7 @@ void CalculateDBThread::processPhase()
             }
 
             /* 将报警信息发送给写入报警信息的线程 */
-            AlarmManager.addAlarmInfo(m_alarmPhase);
+            WriteDB.addAlarmInfo(m_alarmPhase);
 
             /* 打印日志 */
             SPDLOG_LOGGER_INFO(m_logger, "{} 反相报警结束,开始时间:{},结束时间:{}",

+ 5 - 5
Server/ThreadCalculate/CompareDoubleThread.cpp__

@@ -7,7 +7,7 @@
 #include "ThreadManager.h"
 #include "ConsistencyCompareThread.h"
 #include "CreateRecordFileThread.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 
 
 CompareDoubleThread::CompareDoubleThread(CalculateThreadInfo_t& compareItemInfo)
@@ -712,8 +712,8 @@ void CompareDoubleThread::saveAlarmInfo()
             m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
 
             /* 将报警信息写入数据库 */
-            AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
-            AlarmManager.addAlarmInfo(m_alarmConsistencySub);
+            WriteDB.addAlarmInfo(m_alarmConsistencyMain);
+            WriteDB.addAlarmInfo(m_alarmConsistencySub);
             
             SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
             /* 清除报警信息 */
@@ -770,8 +770,8 @@ void CompareDoubleThread::endAlarm()
         m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
         m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
         /* 将报警信息写入数据库 */
-        AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
-        AlarmManager.addAlarmInfo(m_alarmConsistencySub);
+        WriteDB.addAlarmInfo(m_alarmConsistencyMain);
+        WriteDB.addAlarmInfo(m_alarmConsistencySub);
         
         SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
         /* 清除报警信息 */

+ 3 - 1
Server/ThreadCalculate/CompareItemThread.cpp

@@ -11,7 +11,7 @@
 #include "ConsistencyCompareThread.h"
 #include "ThreadPool.h"
 #include "commonDefine.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 #include "spdlog.h"
 #include <QDateTime>
 
@@ -953,7 +953,9 @@ void CompareItemThread::startOrStopRecord(bool isStart)
         }
         OneCompareItemRoadInfo_t itemRoadInfo;
         itemRoadInfo.nCompareItemID = m_threadInfo.compareItemInfo.nID;
+        itemRoadInfo.strCompareItemName = m_threadInfo.compareItemInfo.strName;
         itemRoadInfo.nCompareRoadNum = pair.first;
+        itemRoadInfo.strCompareRoadName = m_threadInfo.compareItemInfo.mapRoad[pair.first].strCompareRoadName;
         itemRoadInfo.nSoundCardNum = m_threadInfo.compareItemInfo.mapRoad[pair.first].scRoadInfo.nSoundCardNum;
         itemRoadInfo.nSoundCardRoadNum = m_threadInfo.compareItemInfo.mapRoad[pair.first].scRoadInfo.roadInfo.nRoadNum;
         if(isStart)

+ 15 - 9
Server/ThreadCalculate/ConsistencyCompareThread.cpp

@@ -4,7 +4,7 @@
 #include "SystemConfig.h"
 #include "ThreadManager.h"
 #include "CreateRecordFileThread.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 
 #include "CreateWAVThread.h"
 #include "LHCompareAPI.h"
@@ -110,8 +110,11 @@ void ConsistencyCompareThread::task()
     SPDLOG_LOGGER_INFO(m_logger, " ★ {} 一致性对比线程(调用动态库)开始运行  ", m_logBase);
     
     // std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now();
+#if(CONSISTENCY_DEBUG)
     int nCompareCount = 0; // 计算次数
     bool isConsistency = true;
+#endif 
+
     while(m_isRunning)
     {
         std::this_thread::sleep_for(std::chrono::milliseconds(100));
@@ -145,6 +148,7 @@ void ConsistencyCompareThread::task()
             continue;
         }
 
+    #if(CONSISTENCY_DEBUG)
         /* 模拟不一致报警,启动检测五次开始报警,报警5次取消报警,间隔5次继续报警 */
         if(isConsistency)
         {
@@ -154,7 +158,7 @@ void ConsistencyCompareThread::task()
                 m_isConsistency = false;
                 m_isConsistencyWarning = true;
                 nCompareCount = 0;
-            }
+      }
         }else {
             if(nCompareCount > 3)
             {
@@ -165,6 +169,7 @@ void ConsistencyCompareThread::task()
             }
         }
         nCompareCount++;
+    #endif
 
         /* 保存结果 */
         saveAlarmInfo();
@@ -355,7 +360,7 @@ void ConsistencyCompareThread::saveAlarmInfo()
             m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
 
             /* 将报警信息写入数据库 */
-            AlarmManager.addAlarmInfo(m_alarmConsistencyMain, m_alarmConsistencySub);
+            WriteDB.addAlarmInfo(m_alarmConsistencyMain, m_alarmConsistencySub);
 
             
             SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束,结束时间: {}", m_logBase, 
@@ -374,12 +379,13 @@ void ConsistencyCompareThread::saveAlarmInfo()
             m_alarmConsistencySub.isAlarm = true;
             m_alarmConsistencyMain.CompareItemID = m_threadInfo.compareItemInfo.nID;
             m_alarmConsistencySub.CompareItemID = m_threadInfo.compareItemInfo.nID;
-            m_alarmConsistencyMain.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-            m_alarmConsistencySub.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-            m_alarmConsistencyMain.RoadType = ERoadType::RoadType_Main;
-            m_alarmConsistencySub.RoadType = ERoadType::RoadType_SpaceReceive;
+            m_alarmConsistencyMain.strCompareItemName = m_threadInfo.compareItemInfo.strName;
+            m_alarmConsistencySub.strCompareItemName = m_threadInfo.compareItemInfo.strName;
             m_alarmConsistencyMain.RoadInfo = m_itemRoadInfo1;
             m_alarmConsistencySub.RoadInfo = m_itemRoadInfo2;
+            
+            m_alarmConsistencyMain.RoadType = ERoadType::RoadType_Main;
+            m_alarmConsistencySub.RoadType = ERoadType::RoadType_SpaceReceive;
 
             m_alarmConsistencyMain.AlarmType = EAlarmType::EAR_Consistency;
             m_alarmConsistencySub.AlarmType = EAlarmType::EAR_Consistency;
@@ -418,8 +424,8 @@ void ConsistencyCompareThread::endAlarm()
         m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
         m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
         /* 将报警信息写入数据库 */
-        AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
-        AlarmManager.addAlarmInfo(m_alarmConsistencySub);
+        WriteDB.addAlarmInfo(m_alarmConsistencyMain);
+        WriteDB.addAlarmInfo(m_alarmConsistencySub);
         
         SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
         /* 清除报警信息 */

+ 3 - 0
Server/ThreadCalculate/ConsistencyCompareThread.h

@@ -8,6 +8,9 @@
 #include "ConsistencyResult.h"
 
 
+#define CONSISTENCY_DEBUG false
+
+
 class CreateWAVThread;
 class CreateRecordFileThread;
 

+ 8 - 8
Server/ThreadCalculate/NoiseDetectThread.cpp

@@ -4,7 +4,7 @@
 
 #include "CreateWAVThread.h"
 #include "CreateRecordFileThread.h"
-#include "ThreadAlarmManager.h"
+#include "ThreadWriteDBManager.h"
 #include "ThreadManager.h"
 #include "commonDefine.h"
 #include "GlobalInfo.h"
@@ -365,7 +365,7 @@ bool NoiseDetectThread::detectNoise()
 //                         m_pThreadCreateAlarm->stopRecordAlarmFile(alarmInfo);
 //                     }
 //                     /* 写入数据库,并清空时间 */
-//                     AlarmManager.addAlarmInfo(alarmInfo);
+//                     WriteDB.addAlarmInfo(alarmInfo);
 //                     alarmInfo.StartTime = QDateTime();
 //                     alarmInfo.EndTime = QDateTime();               
 //                 }
@@ -424,7 +424,7 @@ void NoiseDetectThread::saveResultOnlyOneItem()
             {
                 m_currentAlarmInfo.isAlarm = true; // 设置为报警状态
                 m_currentAlarmInfo.CompareItemID = m_threadInfo.compareItemInfo.nID;
-                m_currentAlarmInfo.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
+                m_currentAlarmInfo.strCompareItemName = m_threadInfo.compareItemInfo.strName;
                 m_currentAlarmInfo.RoadInfo = m_threadInfo.compareItemInfo.mapRoad.first();
                 m_currentAlarmInfo.AlarmType = EAlarmType::EAT_Noise;
                 /* 向前推算噪音开始时间,开始时间需要向前推 n次噪音检测的时间 x 单次噪音检测需要的时间,单位秒 */
@@ -432,7 +432,7 @@ void NoiseDetectThread::saveResultOnlyOneItem()
                 QDateTime startTime = m_leftRightData.startTime;
                 startTime = startTime.addSecs(-nNoiseDetectTime);
                 m_currentAlarmInfo.StartTime = startTime;
-                SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 开始噪音报警, 报警开始时间: {}", m_logBase, m_currentAlarmInfo.strCompareItemName, 
+                SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 开始噪音报警, 报警开始时间: {}", m_logBase, m_currentAlarmInfo.strCompareItemName.toStdString(), 
                                                 m_currentAlarmInfo.RoadInfo.strCompareRoadName.toStdString(), 
                                                 startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
                 /* 这里可以添加通知录制报警文件的线程开始录音 */
@@ -459,7 +459,7 @@ void NoiseDetectThread::saveResultOnlyOneItem()
                 m_currentAlarmInfo.isAlarm = false;
                 /* 设置结束时间 */
                 m_currentAlarmInfo.EndTime = m_leftRightData.endTime;
-                SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 结束噪音报警", m_logBase, m_currentAlarmInfo.strCompareItemName, 
+                SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 结束噪音报警", m_logBase, m_currentAlarmInfo.strCompareItemName.toStdString(), 
                                                 m_currentAlarmInfo.RoadInfo.strCompareRoadName.toStdString());
                 /* 这里可以添加通知录制报警文件的线程停止录音 */
                 if(m_pThreadCreateAlarm != nullptr)
@@ -467,7 +467,7 @@ void NoiseDetectThread::saveResultOnlyOneItem()
                     m_pThreadCreateAlarm->stopRecordAlarmFile(m_currentAlarmInfo);
                 }
                 /* 写入数据库,并清空时间 */
-                AlarmManager.addAlarmInfo(m_currentAlarmInfo);
+                WriteDB.addAlarmInfo(m_currentAlarmInfo);
                 m_currentAlarmInfo = AlarmInfo_t(); // 清空当前报警信息         
             }
             
@@ -486,7 +486,7 @@ void NoiseDetectThread::endAlarm()
         m_currentAlarmInfo.isAlarm = false;
         /* 设置结束时间 */
         m_currentAlarmInfo.EndTime = m_leftRightData.endTime;
-        SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 结束噪音报警", m_logBase, m_currentAlarmInfo.strCompareItemName, 
+        SPDLOG_LOGGER_WARN(m_logger, "{} 对比项-{} {} 结束噪音报警", m_logBase, m_currentAlarmInfo.strCompareItemName.toStdString(), 
                                         m_currentAlarmInfo.RoadInfo.strCompareRoadName.toStdString());
         /* 这里可以添加通知录制报警文件的线程停止录音 */
         if(m_pThreadCreateAlarm != nullptr)
@@ -494,7 +494,7 @@ void NoiseDetectThread::endAlarm()
             m_pThreadCreateAlarm->stopRecordAlarmFile(m_currentAlarmInfo);
         }
         /* 写入数据库,并清空时间 */
-        AlarmManager.addAlarmInfo(m_currentAlarmInfo);
+        WriteDB.addAlarmInfo(m_currentAlarmInfo);
         m_currentAlarmInfo = AlarmInfo_t(); // 清空当前报警信息         
     }
     m_isNoiseWarning.store(false);

+ 0 - 152
Server/ThreadManager/ThreadAlarmManager.cpp

@@ -1,152 +0,0 @@
-#include "ThreadAlarmManager.h"
-
-
-#include "GlobalInfo.h"
-#include "spdlog.h"
-#include <mutex>
-#include <thread>
-
-ThreadAlarmManager::~ThreadAlarmManager()
-{
-
-}
-
-
-
-/* 线程工作函数 */
-void ThreadAlarmManager::thread_task()
-{
-    /* 初始化信息 */
-    if(!initData())
-    {
-        SPDLOG_LOGGER_ERROR(m_logger, "报警信息处理线程初始化数据失败");
-        return;
-    }
-
-    /* 设置标志位 */
-    m_isRunning = true;
-    m_isStop = false;
-    m_threadState = EThreadState::State_Running;
-
-    SPDLOG_LOGGER_INFO(m_logger, "⚡ 报警信息处理线程开始运行");
-
-    /* 运行线程功能 */
-    task();
-
-    /* 清理数据 */
-    clearData();
-    m_threadState = EThreadState::State_Stopped;
-    m_isStop = true;
-    SPDLOG_LOGGER_WARN(m_logger, "⚡ 报警信息处理线程结束运行");
-}
-
-/* 停止线程 */
-void ThreadAlarmManager::thread_stop()
-{
-    m_isRunning = false; // 设置线程停止标志位
-}
-
-void ThreadAlarmManager::thread_stopBlock()
-{
-    thread_stop();
-    while(m_threadState != EThreadState::State_Stopped) // 等待线程停止
-    {
-        std::this_thread::sleep_for(std::chrono::milliseconds(1));
-    }
-}
-
-
-/* 添加报警内容 */
-void ThreadAlarmManager::addAlarmInfo(const AlarmInfo_t& alarmInfo)
-{
-    std::lock_guard<std::mutex> lock(m_mutexListAlarm);
-    m_listAlarm.push_back(alarmInfo);
-}
-
-void ThreadAlarmManager::addAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
-{
-    std::lock_guard<std::mutex> lock(m_mutexListAlarm);
-    m_listAlarm.insert(m_listAlarm.end(), listAlarm.begin(), listAlarm.end());
-}
-
-
-/* 添加一致性报警信息,键为主通道信息,值为次通道信息 */
-void ThreadAlarmManager::addAlarmInfo(const AlarmInfo_t& mainAlarm, const AlarmInfo_t& subAlarm)
-{
-    std::lock_guard<std::mutex> lock(m_mutexListAlarmConsistency);
-    m_listAlarmConsistency.push_back(std::make_pair(mainAlarm, subAlarm));
-}
-
-
-/* 线程工作函数 */
-void ThreadAlarmManager::task()
-{
-    while(m_isRunning.load())
-    {
-        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 每100毫秒执行一次
-
-        {
-            /* 普通的报警数据写入数据库 */
-            std::lock_guard<std::mutex> lock(m_mutexListAlarm);
-            if(!m_listAlarm.empty())
-            {
-                if(!m_fromWebAPI.insertAlarmInfo(m_listAlarm))
-                {
-                    SPDLOG_LOGGER_ERROR(m_logger, "写入报警信息失败");
-                }
-                /* 清空报警列表 */
-                m_listAlarm.clear();
-            }
-        }
-
-        {
-            /* 写入一致性报警信息 */
-            std::lock_guard<std::mutex> lock(m_mutexListAlarmConsistency);
-            if(!m_listAlarmConsistency.empty())
-            {
-                for(const auto& alarmPair : m_listAlarmConsistency)
-                {
-                    if(!m_fromWebAPI.insertConsistencyAlarmInfo(alarmPair.first, alarmPair.second))
-                    {
-                        SPDLOG_LOGGER_ERROR(m_logger, "写入一致性报警信息失败");
-                    }
-                }
-                /* 清空报警信息 */
-                m_listAlarmConsistency.clear();
-            }
-        }
-
-    }
-}
-
-/* 初始化数据 */
-bool ThreadAlarmManager::initData()
-{
-    if(m_logger == nullptr)
-    {
-        m_logger = spdlog::get("Alarm");
-        if(m_logger == nullptr)
-        {
-            fmt::print("Alarm is nullptr");
-            return false; // 日志记录器获取失败
-        }
-    }
-
-    /* 登陆WebAPI */
-    if(!m_fromWebAPI.initWebApi(GInfo.webAPIUrl(), GInfo.webAPIID(), GInfo.webApiAppType()))
-    {
-        SPDLOG_LOGGER_ERROR(m_logger, "报警信息处理线程登录WebAPI失败");
-        return false;
-    }
-    SPDLOG_LOGGER_INFO(m_logger, "报警信息处理线程登录WebAPI成功");
-
-
-    return true;
-}
-
-/* 清理数据 */
-void ThreadAlarmManager::clearData()
-{
-
-}
-

+ 268 - 0
Server/ThreadManager/ThreadWriteDBManager.cpp

@@ -0,0 +1,268 @@
+#include "ThreadWriteDBManager.h"
+
+
+#include "GlobalInfo.h"
+#include "spdlog.h"
+#include "GlobalInfo.h"
+
+#include <mutex>
+#include <thread>
+
+ThreadWriteDBManager::~ThreadWriteDBManager()
+{
+
+}
+
+
+
+/* 线程工作函数 */
+void ThreadWriteDBManager::thread_task()
+{
+    /* 初始化信息 */
+    if(!initData())
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "写数据库线程初始化数据失败");
+        return;
+    }
+
+    /* 设置标志位 */
+    m_isRunning = true;
+    m_isStop = false;
+    m_threadState = EThreadState::State_Running;
+
+    SPDLOG_LOGGER_INFO(m_logger, "✉ 写数据库线程开始运行");
+
+    /* 运行线程功能 */
+    task();
+
+    /* 清理数据 */
+    clearData();
+    m_threadState = EThreadState::State_Stopped;
+    m_isStop = true;
+    SPDLOG_LOGGER_WARN(m_logger, "✉ 写数据库线程结束运行");
+}
+
+/* 停止线程 */
+void ThreadWriteDBManager::thread_stop()
+{
+    m_isRunning = false; // 设置线程停止标志位
+}
+
+void ThreadWriteDBManager::thread_stopBlock()
+{
+    thread_stop();
+    while(m_threadState != EThreadState::State_Stopped) // 等待线程停止
+    {
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
+}
+
+
+/* 添加报警内容 */
+void ThreadWriteDBManager::addAlarmInfo(const AlarmInfo_t& alarmInfo)
+{
+    std::lock_guard<std::mutex> lock(m_mutexListAlarm);
+    m_listAlarm.push_back(alarmInfo);
+}
+
+void ThreadWriteDBManager::addAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
+{
+    std::lock_guard<std::mutex> lock(m_mutexListAlarm);
+    m_listAlarm.insert(m_listAlarm.end(), listAlarm.begin(), listAlarm.end());
+}
+
+
+/* 添加一致性报警信息,键为主通道信息,值为次通道信息 */
+void ThreadWriteDBManager::addAlarmInfo(const AlarmInfo_t& mainAlarm, const AlarmInfo_t& subAlarm)
+{
+    std::lock_guard<std::mutex> lock(m_mutexListAlarmConsistency);
+    m_listAlarmConsistency.push_back(std::make_pair(mainAlarm, subAlarm));
+}
+
+/* 录音文件写入数据库,isNewFile = true 是插入数据库,= false是更新数据库 */
+void ThreadWriteDBManager::addRecordFileInfo(std::list<RecordFileInfo_t>& listRecordFile, bool isNewFile)
+{
+    std::lock_guard<std::mutex> lock(m_mutexListRecordFile);
+    m_listRecordFile.insert(m_listRecordFile.end(), listRecordFile.begin(), listRecordFile.end());
+    m_isRecordFileInsert.store(isNewFile);
+}
+
+
+/* 线程工作函数 */
+void ThreadWriteDBManager::task()
+{
+    while(m_isRunning.load())
+    {
+        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 每100毫秒执行一次
+
+        /* 写入普通报警文件 */
+        alarmInfoToDB();
+        
+        /* 写入一致性报警文件 */
+        consistencyAlarmInfoToDB();
+
+        /* 写录音文件信息到数据库 */
+        recordFileInfoToDB();
+    }
+}
+
+/* 初始化数据 */
+bool ThreadWriteDBManager::initData()
+{
+    if(m_logger == nullptr)
+    {
+        m_logger = spdlog::get("WriteDB");
+        if(m_logger == nullptr)
+        {
+            fmt::print("Alarm is nullptr");
+            return false; // 日志记录器获取失败
+        }
+    }
+
+    /* 登陆WebAPI */
+    if(!m_fromWebAPI.initWebApi(GInfo.webAPIUrl(), GInfo.webAPIID(), GInfo.webApiAppType()))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "报警信息处理线程登录WebAPI失败");
+        return false;
+    }
+    SPDLOG_LOGGER_INFO(m_logger, "报警信息处理线程登录WebAPI成功");
+
+    /* 获取文件存储的根目录 */
+    m_strRootPath = GInfo.rootPath();
+    if(m_strRootPath.endsWith('/'))
+    {
+        m_strRootPath.chop(1);
+    }
+
+    return true;
+}
+
+/* 清理数据 */
+void ThreadWriteDBManager::clearData()
+{
+
+}
+
+/* 普通报警写入数据库 */
+void ThreadWriteDBManager::alarmInfoToDB()
+{
+    /* 普通的报警数据写入数据库 */
+    std::list<AlarmInfo_t> listAlarm;
+    {
+        std::lock_guard<std::mutex> lock(m_mutexListAlarm);
+        if(m_listAlarm.empty())
+        {
+            return; // 没有报警信息
+        }
+        listAlarm = std::move(m_listAlarm); // 移动报警信息列表
+        m_listAlarm.clear(); // 清空报警列表
+    }
+
+    /* 处理报警路径 */
+    for(auto& alarm : listAlarm)
+    {
+        processFilePath(alarm.strAlarmFilePath);
+    }
+
+    if(!m_fromWebAPI.insertAlarmInfo(listAlarm))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "写入报警信息失败");
+    }
+    /* 清空报警列表 */
+    listAlarm.clear();
+}
+
+/* 一致性报警写入数据库 */
+void ThreadWriteDBManager::consistencyAlarmInfoToDB()
+{
+    /* 写入一致性报警信息 */
+    std::list<std::pair<AlarmInfo_t, AlarmInfo_t>> listAlarmConsistency;
+    {
+        std::lock_guard<std::mutex> lock(m_mutexListAlarmConsistency);
+        if(m_listAlarmConsistency.empty())
+        {
+            return; // 没有一致性报警信息
+        }
+        listAlarmConsistency = std::move(m_listAlarmConsistency); // 移动一致性报警信息列表
+        m_listAlarmConsistency.clear(); // 清空一致性报警列表
+    }
+
+    /* 处理报警路径 */
+    for(auto it = listAlarmConsistency.begin(); it != listAlarmConsistency.end(); ++it)
+    {
+        processFilePath(it->first.strAlarmFilePath);
+        processFilePath(it->second.strAlarmFilePath);
+    }
+
+    for(const auto& alarmPair : listAlarmConsistency)
+    {
+        if(!m_fromWebAPI.insertConsistencyAlarmInfo(alarmPair.first, alarmPair.second))
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "写入一致性报警信息失败");
+        }
+    }
+    /* 清空报警信息 */
+    listAlarmConsistency.clear();
+}
+
+
+
+
+
+/* 录音文件写数据库 */
+void ThreadWriteDBManager::recordFileInfoToDB()
+{
+    std::list<RecordFileInfo_t> listRecordFile;
+    {
+        std::lock_guard<std::mutex> lock(m_mutexListRecordFile);
+        if(m_listRecordFile.empty())
+        {
+            return; // 没有录音文件信息
+        }
+        listRecordFile = std::move(m_listRecordFile); // 移动录音文件信息列表
+        m_listRecordFile.clear();
+    }
+    
+    /* 处理录音文件路径 */
+    for(auto& recordFile : listRecordFile)
+    {
+        processFilePath(recordFile.FilePath);
+    }
+
+    if(m_isRecordFileInsert.load())
+    {
+        if(!m_fromWebAPI.insertRecordFileInfo(listRecordFile))
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "写入录音文件信息失败");
+        }
+    } else 
+    {
+        if(!m_fromWebAPI.updateRecordFileInfo(listRecordFile))
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "更新录音文件信息失败");
+        }
+    }
+}
+
+
+/* 处理报警路径,去掉前面的本地路径,只保留服务自己创建的文件夹及之后的路径 */
+bool ThreadWriteDBManager::processFilePath(QString& strFilePath)
+{
+    if(strFilePath.isEmpty())
+    {
+        return false;
+    }
+
+    /* 去掉前面的目录,只留下报警文件夹及之后的路径 */
+    if(strFilePath.startsWith(m_strRootPath))
+    {
+        strFilePath = strFilePath.mid(m_strRootPath.length());
+        if(!strFilePath.startsWith('/'))
+        {
+            strFilePath = '/' + strFilePath;
+        }
+    }
+
+    return true;
+}
+

+ 36 - 14
Server/ThreadManager/ThreadAlarmManager.h → Server/ThreadManager/ThreadWriteDBManager.h

@@ -1,8 +1,8 @@
-#ifndef __THREADALARMMANAGER_H__
-#define __THREADALARMMANAGER_H__
+#ifndef __THREADWRITEDBMANAGER_H__
+#define __THREADWRITEDBMANAGER_H__
 
 /**
- * @file ThreadAlarmManager.h
+ * @file ThreadWriteDBManager.h
  * @author your name (you@domain.com)
  * @brief 
  * @version 0.1
@@ -25,27 +25,28 @@
 
 
 /**
-    处理报警信息,所有的报警信息都由这个线程写入数据库
+    写数据库线程,服务写入数据库都由这里写入
     
     1、报警信息列表分为两种,一种是静音、过载、反相、噪音等单个录音通道的报警信息,一种是一致性报警需要
         两个通道的关联的报警信息,这两种分别写入数据库,不相关联。
+    2、录音文件也会从这里写数据库
  */
 
 
 
-#define AlarmManager ThreadAlarmManager::instance()
+#define WriteDB ThreadWriteDBManager::instance()
 
-class ThreadAlarmManager
+class ThreadWriteDBManager
 {
     
-    ThreadAlarmManager() = default;
-    ThreadAlarmManager(const ThreadAlarmManager&) = delete;
-    ThreadAlarmManager& operator=(const ThreadAlarmManager&) = delete;
+    ThreadWriteDBManager() = default;
+    ThreadWriteDBManager(const ThreadWriteDBManager&) = delete;
+    ThreadWriteDBManager& operator=(const ThreadWriteDBManager&) = delete;
 public:
-    ~ThreadAlarmManager();
-    static ThreadAlarmManager& instance()
+    ~ThreadWriteDBManager();
+    static ThreadWriteDBManager& instance()
     {
-        static ThreadAlarmManager instance;
+        static ThreadWriteDBManager instance;
         return instance;
     }
 
@@ -65,6 +66,9 @@ public:
     /* 添加一致性报警信息,键为主通道信息,值为次通道信息 */
     void addAlarmInfo(const AlarmInfo_t& mainAlarm, const AlarmInfo_t& subAlarm);
     
+    /* 录音文件写入数据库,isNewFile = true 是插入数据库,= false是更新数据库 */
+    void addRecordFileInfo(std::list<RecordFileInfo_t>& listRecordFile, bool isNewFile);
+    
 
 private:
     /* 线程工作函数 */
@@ -74,6 +78,16 @@ private:
     /* 清理数据 */
     void clearData();
 
+    /* 普通报警写入数据库 */
+    void alarmInfoToDB();
+    /* 一致性报警写入数据库 */
+    void consistencyAlarmInfoToDB();
+
+    /* 录音文件写数据库 */
+    void recordFileInfoToDB();
+
+    /* 处理文件路径,去掉前面的本地路径,只保留服务自己创建的文件夹及之后的路径 */
+    inline bool processFilePath(QString& strFilePath);
 
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
@@ -81,9 +95,11 @@ private:
     std::atomic_bool m_isRunning = false;           /* 线程运行标志位 */
     std::atomic_bool m_isStop = false;              /* 线程停止标志位 */
     EThreadState m_threadState = EThreadState::State_None; /* 线程状态 */
-
     FromWebAPI m_fromWebAPI;
 
+    QString m_strRootPath;                          /* 本地存储的根目录,不带有服务创建的文件夹 */
+
+    /* ---------------------------- 报警信息 ---------------------------- */
     /* 存储一般的报警信息 */
     std::mutex m_mutexListAlarm;                    /* 报警信息列表的互斥锁 */
     std::list<AlarmInfo_t> m_listAlarm;             /* 报警信息列表 */
@@ -92,8 +108,14 @@ private:
     std::mutex m_mutexListAlarmConsistency;         /* 一致性报警信息列表的互斥锁 */
     /* 一致性报警信息列表,键是主通道信息,值是次通道信息 */
     std::list<std::pair<AlarmInfo_t, AlarmInfo_t>> m_listAlarmConsistency;
+
+    /* ---------------------------- 报警信息 ---------------------------- */
+    /* 存储录音文件信息 */
+    std::mutex m_mutexListRecordFile;               /* 录音文件信息列表的互斥锁 */
+    std::list<RecordFileInfo_t> m_listRecordFile;
+    std::atomic_bool m_isRecordFileInsert = false;  /* 录音文件信息是否是插入数据库 */
 };
 
 
 
-#endif // __THREADALARMMANAGER_H__
+#endif // __THREADWRITEDBMANAGER_H__

+ 47 - 13
Server/ThreadRecord/CreateRecordFileThread.cpp

@@ -2,10 +2,13 @@
 
 #include "AudioData.h"
 #include "GlobalInfo.h"
-#include "spdlog.h"
+#include "spdlog/spdlog.h"
+#include "ThreadWriteDBManager.h"
+
+
 #include <cstring>
 #include <mutex>
-#include <qt5/QtCore/qchar.h>
+#include <QString>
 
 
 
@@ -148,8 +151,9 @@ bool CreateRecordFileThread::startRecordAlarmFile(const AlarmInfo_t& alarmInfo)
                         alarmInfo.AlarmType, alarmInfo.StartTime};
     if(m_mapAlarmFile.find(key) != m_mapAlarmFile.end())
     {
-        SPDLOG_LOGGER_WARN(m_logger, "{} 通道:{}, {}, 报警类型: {}, 已经在报警录制队列中,无法重复添加", m_logBase, 
-                                        alarmInfo.CompareItemID, alarmInfo.strCompareItemName, static_cast<int>(alarmInfo.AlarmType));
+        SPDLOG_LOGGER_WARN(m_logger, "{} 对比项ID:{},{}, 通道:{}, 报警类型: {}, 已经在报警录制队列中,无法重复添加", m_logBase, 
+                                        alarmInfo.CompareItemID, alarmInfo.strCompareItemName.toStdString(), alarmInfo.RoadInfo.nCompareRoadNum,
+                                        static_cast<int>(alarmInfo.AlarmType));
         return true;
     }
 
@@ -159,7 +163,7 @@ bool CreateRecordFileThread::startRecordAlarmFile(const AlarmInfo_t& alarmInfo)
     value.startTime = alarmInfo.StartTime;
     value.endTime = alarmInfo.EndTime;
     value.numConpareItemID = alarmInfo.CompareItemID;
-    value.strCompareItemName = QString::fromStdString(alarmInfo.strCompareItemName);
+    value.strCompareItemName = alarmInfo.strCompareItemName;
     value.itemRoadInfo = alarmInfo.RoadInfo;
 
     m_mapAlarmFile.insert({key, value});
@@ -183,7 +187,7 @@ bool CreateRecordFileThread::stopRecordAlarmFile(AlarmInfo_t& alarmInfo)
             value.endTime = alarmInfo.EndTime; // 设置结束时间
             value.state = eRecordState::eAlarm_Stopped; // 设置为停止状态
             value.fileNameEnd = generateAlarmFileName(value, false); // 生成结束文件名
-            alarmInfo.strAlarmFilePath = value.fileNameEnd.toStdString(); // 返回文件路径
+            alarmInfo.strAlarmFilePath = value.fileNameEnd; // 返回文件路径
             alarmInfo.AlarmStartPos = value.alarmStartPos; // 返回开始位置
             SPDLOG_LOGGER_INFO(m_logger, "{} 停止录制报警文件: {}, 开始位置: {} 秒", 
                 m_logBase, value.fileNameEnd.toStdString(), value.alarmStartPos);
@@ -223,13 +227,7 @@ void CreateRecordFileThread::task()
         /*--------------------------------------------------------------
         * 写入长记录文件
         *--------------------------------------------------------------*/
-        /* 判断是否需要录音 */
-        std::lock_guard<std::mutex> lock(m_mutexCompareItemRoadInfo);
-        if(m_isRequireRecord.load() == false)
-        {
-            /* 没有对比项信息,不进行录音 */
-            continue;
-        }
+        
         writeLongRecordFile();
         
     }
@@ -276,6 +274,14 @@ void CreateRecordFileThread::clearData()
 /* 写入长记录文件 */
 bool CreateRecordFileThread::writeLongRecordFile()
 {
+    /* 判断是否需要录音 */
+    std::lock_guard<std::mutex> lock(m_mutexCompareItemRoadInfo);
+    if(m_isRequireRecord.load() == false)
+    {
+        /* 没有对比项信息,不进行录音 */
+        return true;
+    }
+
     /* 判断缓存是否达到1分钟数据临界值 */
     {
         std::lock_guard<std::mutex> lock(m_mutexBuffer);
@@ -385,6 +391,9 @@ bool CreateRecordFileThread::writeLongRecordFile()
         m_openFileErrorSize = 0;                // 重置错误次数
     }
 
+    /* 更新文件信息到数据库 */
+    updateRecordFileInfoToDB(isNewFile);
+
     return true;
 }
 
@@ -525,6 +534,31 @@ bool CreateRecordFileThread::isOneHourPassed()
     return isPassed;
 }
 
+/* 更新文件信息到数据库 */
+void CreateRecordFileThread::updateRecordFileInfoToDB(bool isNewFile)
+{
+    std::list<RecordFileInfo_t> listRecordFileInfo;
+    for(const auto& it : m_listCompareItemRoadInfo)
+    {
+        RecordFileInfo_t recordFileInfo;
+        recordFileInfo.ItemID = it.nCompareItemID;
+        recordFileInfo.ItemName = it.strCompareItemName;
+        recordFileInfo.ItemRoadNum = it.nCompareRoadNum;
+        recordFileInfo.ItemRoadName = it.strCompareRoadName;
+        recordFileInfo.SoundCardNum = it.nSoundCardNum;
+        recordFileInfo.SoundCardRoadNum = it.nSoundCardRoadNum;
+
+        recordFileInfo.FileStartTime = m_writtenStartTime;
+        recordFileInfo.FileEndTime = m_writtenNowTime;
+        recordFileInfo.FilePath = m_wavFileName;
+        recordFileInfo.FileDuration = m_writtenStartTime.secsTo(m_writtenNowTime);
+        
+        listRecordFileInfo.push_back(recordFileInfo);
+    }
+
+    WriteDB.addRecordFileInfo(listRecordFileInfo, isNewFile);
+}
+
 
 /* 生成报警文件名 */
 QString CreateRecordFileThread::generateAlarmFileName(const AlarmValue_t& value, bool isNewFile)

+ 4 - 2
Server/ThreadRecord/CreateRecordFileThread.h

@@ -11,7 +11,7 @@
 #include <mutex>
 #include <QFile>
 #include <QDir>
-#include <qt5/QtCore/qchar.h>
+
 
 
 /**
@@ -151,6 +151,8 @@ private:
     inline QString generateFileName(const QDateTime& startTime, const QDateTime& endTime) const;
     /* 判断是否过了整点 */
     inline bool isOneHourPassed();
+    /* 更新文件信息到数据库 */
+    void updateRecordFileInfoToDB(bool isNewFile);
 
     /*===============================================================================*/
     /* 写入报警文件 */
@@ -183,7 +185,7 @@ private:
 
     QDir m_todayDir;                        /* 今日目录 */
     QDate m_todayDateRecord;                /* 今日日期,记录长文件用 */
-    QString m_wavFileName;                  /* wav文件对象 */
+    QString m_wavFileName;                  /* 当前录音的wav文件名 */
     int m_openFileErrorSize = 0;            /* 打开文件错误次数 */
     WavHeader m_wavHeader;                  /* 当前wav文件头信息 */
     int64_t m_writtenSize = 0;              /* 已经写入的数据大小 */

+ 4 - 4
Server/ThreadRecord/CreateWAVThread.cpp

@@ -290,7 +290,7 @@ bool CreateWAVThread::createWAVFile(int secondCount)
     tmpHeader.calculateDerivedFields();
     wavFile.write(reinterpret_cast<const char*>(&tmpHeader), sizeof(WavHeader));
 
-    SPDLOG_LOGGER_DEBUG(m_logger, "{} 开始写入音频数据,当前队列大小: {}", m_logBase, m_queueWavSrcData.QueueSize());
+    // SPDLOG_LOGGER_DEBUG(m_logger, "{} 开始写入音频数据,当前队列大小: {}", m_logBase, m_queueWavSrcData.QueueSize());
     /* 写入音频数据 */
     for(int i = 0; i < secondCount; ++i)
     {
@@ -328,9 +328,9 @@ bool CreateWAVThread::createWAVFile(int secondCount)
     m_queueWavFileName->mutex.unlock();
 
     // SPDLOG_LOGGER_DEBUG(m_logger, "{} 数据写入完成,当前队列大小: {}", m_logBase, m_queueWavSrcData.QueueSize());
-    SPDLOG_LOGGER_DEBUG(m_logger, "{} 生成WAV文件成功: {}, 开始时间: {}, 结束时间: {}", 
-        m_logBase, wavFilePath.fileName, wavFilePath.startDateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
-        wavFilePath.endDateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+    // SPDLOG_LOGGER_DEBUG(m_logger, "{} 生成WAV文件成功: {}, 开始时间: {}, 结束时间: {}", 
+    //     m_logBase, wavFilePath.fileName, wavFilePath.startDateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+    //     wavFilePath.endDateTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
 
     return true;
 }

+ 1 - 0
Server/ThreadRecord/RecordThread.h

@@ -13,6 +13,7 @@
 #include "spdlog/spdlog.h"
 
 
+/* 设置为true,使用本地文件 */
 #define RECORD_READFILE true
 
 

+ 1 - 1
Server/common/LHLog/LHLogInit.cpp

@@ -91,7 +91,7 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
         /* 创建一个对比项管理线程的logger */
         auto logger_compareitem = std::make_shared<spdlog::logger>("CompareItemManager",begin(sinks),end(sinks));
         /* 创建一个处理日志的线程logger */
-        auto logger_threadAlarm = std::make_shared<spdlog::logger>("Alarm",begin(sinks),end(sinks));
+        auto logger_threadAlarm = std::make_shared<spdlog::logger>("WriteDB",begin(sinks),end(sinks));
 
 
         /* 注册到注册表 */

+ 3 - 0
SettingLibrary/CMakeLists.txt

@@ -47,6 +47,7 @@ file(GLOB LOCAL_SRC
     
     ${LHQLog_SOURCE_DIRS}/*.cpp
     ${LHHTTPAPI_SOURCE_DIRS}/*.cpp
+    ${SM_SOURCE_DIR}/*.cpp
 )
 
 
@@ -112,6 +113,7 @@ target_include_directories(${libName} PRIVATE
     ${LHQLog_INCLUDE_DIRS}
     ${LHHTTPAPI_INCLUDE_DIRS}
     ${qmqtt_INCLUDE_DIR}
+    ${SM_INCLUDE_DIR}
 )
 
 
@@ -125,5 +127,6 @@ target_link_libraries(${libName} PRIVATE
 target_link_libraries(${libName} PRIVATE
     ${spdlog_LIBRARY}
     ${qmqtt_LIBRARY}
+    ${SM_LIB_LIBRARY}
 )
 

+ 8 - 0
SettingLibrary/Modules/Database/databasewidget.cpp

@@ -42,6 +42,9 @@ DatabaseWidget::DatabaseWidget(QWidget *parent) :
 
     ui->lineEdit_ftpPath->setPlaceholderText("请输入,FTP文件路径");
 
+    /* 设置密码行隐藏 */
+    ui->lineEdit_ftpPasswd->setEchoMode(QLineEdit::Password);
+
     /* 隐藏客户端通讯端口 */
     ui->label_6->hide();
     ui->lineEdit_clientPort->hide();
@@ -72,6 +75,8 @@ bool DatabaseWidget::saveParams()
     m_databaseConfig.nListenPort = ui->lineEdit_listenPort->text().toInt();
     m_databaseConfig.strRecordFilePath = ui->lineEdit_recordFilePath->text();
     m_databaseConfig.strFtpPath = ui->lineEdit_ftpPath->text();
+    m_databaseConfig.strFtpUser = ui->lineEdit_ftpUser->text();
+    m_databaseConfig.strFtpPassword = ui->lineEdit_ftpPasswd->text();
     
     /* 和旧数据对比 */
     const DatabaseConfig_t& oldConfig = SysConfig.getDatabaseConfig();
@@ -113,5 +118,8 @@ void DatabaseWidget::do_pBtn_restore_clicked()
     ui->lineEdit_clientPort->setText(QString::number(m_databaseConfig.nClientPort));
     ui->lineEdit_listenPort->setText(QString::number(m_databaseConfig.nListenPort));
     ui->lineEdit_recordFilePath->setText(m_databaseConfig.strRecordFilePath);
+    ui->lineEdit_ftpPath->setText(m_databaseConfig.strFtpPath);
+    ui->lineEdit_ftpUser->setText(m_databaseConfig.strFtpUser);
+    ui->lineEdit_ftpPasswd->setText(m_databaseConfig.strFtpPassword);
 }
 

+ 106 - 54
SettingLibrary/Modules/Database/databasewidget.ui

@@ -62,48 +62,78 @@
       <property name="verticalSpacing">
        <number>16</number>
       </property>
-      <item row="3" column="0">
-       <widget class="QLabel" name="label_6">
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_4">
         <property name="text">
-         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;客户端通讯端口:</string>
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;录音文件保留:</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
-       <widget class="QLineEdit" name="lineEdit_recordFileRetain">
+      <item row="5" column="0">
+       <widget class="QLabel" name="label_7">
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;录音文件目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="9" column="0">
+       <widget class="QPushButton" name="pBtn_restore">
         <property name="minimumSize">
          <size>
-          <width>172</width>
+          <width>102</width>
           <height>32</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
-          <width>232</width>
+          <width>102</width>
           <height>32</height>
          </size>
         </property>
+        <property name="text">
+         <string>恢复配置项</string>
+        </property>
        </widget>
       </item>
-      <item row="7" column="0">
-       <widget class="QPushButton" name="pBtn_restore">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;录音日志保留:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLineEdit" name="lineEdit_recordLogRetain">
         <property name="minimumSize">
          <size>
-          <width>102</width>
+          <width>172</width>
           <height>32</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
-          <width>102</width>
+          <width>232</width>
           <height>32</height>
          </size>
         </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="label_5">
         <property name="text">
-         <string>恢复配置项</string>
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;RTP监听&lt;/span&gt;端口:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
        </widget>
       </item>
@@ -123,8 +153,18 @@
         </property>
        </widget>
       </item>
-      <item row="5" column="1">
-       <widget class="QLineEdit" name="lineEdit_recordFilePath">
+      <item row="6" column="0">
+       <widget class="QLabel" name="label_8">
+        <property name="text">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP文件&lt;/span&gt;目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="7" column="1">
+       <widget class="QLineEdit" name="lineEdit_ftpUser">
         <property name="minimumSize">
          <size>
           <width>172</width>
@@ -139,13 +179,19 @@
         </property>
        </widget>
       </item>
-      <item row="0" column="0">
-       <widget class="QLabel" name="label_2">
-        <property name="text">
-         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;录音日志保留:</string>
+      <item row="3" column="1">
+       <widget class="QLineEdit" name="lineEdit_clientPort">
+        <property name="minimumSize">
+         <size>
+          <width>172</width>
+          <height>32</height>
+         </size>
         </property>
-        <property name="alignment">
-         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        <property name="maximumSize">
+         <size>
+          <width>232</width>
+          <height>32</height>
+         </size>
         </property>
        </widget>
       </item>
@@ -159,7 +205,17 @@
         </property>
        </widget>
       </item>
-      <item row="9" column="0" colspan="3">
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_6">
+        <property name="text">
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;客户端通讯端口:</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="11" column="0" colspan="3">
        <spacer name="verticalSpacer">
         <property name="orientation">
          <enum>Qt::Vertical</enum>
@@ -172,18 +228,15 @@
         </property>
        </spacer>
       </item>
-      <item row="2" column="0">
-       <widget class="QLabel" name="label_4">
+      <item row="10" column="0" colspan="3">
+       <widget class="QLabel" name="label_tip">
         <property name="text">
-         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;录音文件保留:</string>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+         <string>可恢复为编辑时的初始字段信息</string>
         </property>
        </widget>
       </item>
-      <item row="3" column="1">
-       <widget class="QLineEdit" name="lineEdit_clientPort">
+      <item row="1" column="1">
+       <widget class="QLineEdit" name="lineEdit_operatorLogRetain">
         <property name="minimumSize">
          <size>
           <width>172</width>
@@ -198,8 +251,8 @@
         </property>
        </widget>
       </item>
-      <item row="1" column="1">
-       <widget class="QLineEdit" name="lineEdit_operatorLogRetain">
+      <item row="5" column="1">
+       <widget class="QLineEdit" name="lineEdit_recordFilePath">
         <property name="minimumSize">
          <size>
           <width>172</width>
@@ -214,28 +267,34 @@
         </property>
        </widget>
       </item>
-      <item row="5" column="0">
-       <widget class="QLabel" name="label_7">
-        <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;录音文件目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <item row="6" column="1">
+       <widget class="QLineEdit" name="lineEdit_ftpPath">
+        <property name="minimumSize">
+         <size>
+          <width>172</width>
+          <height>32</height>
+         </size>
         </property>
-        <property name="alignment">
-         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        <property name="maximumSize">
+         <size>
+          <width>232</width>
+          <height>32</height>
+         </size>
         </property>
        </widget>
       </item>
-      <item row="4" column="0">
-       <widget class="QLabel" name="label_5">
+      <item row="7" column="0">
+       <widget class="QLabel" name="label_9">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;RTP监听&lt;/span&gt;端口:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP用户名&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
        </widget>
       </item>
-      <item row="0" column="1">
-       <widget class="QLineEdit" name="lineEdit_recordLogRetain">
+      <item row="2" column="1">
+       <widget class="QLineEdit" name="lineEdit_recordFileRetain">
         <property name="minimumSize">
          <size>
           <width>172</width>
@@ -250,25 +309,18 @@
         </property>
        </widget>
       </item>
-      <item row="8" column="0" colspan="3">
-       <widget class="QLabel" name="label_tip">
-        <property name="text">
-         <string>可恢复为编辑时的初始字段信息</string>
-        </property>
-       </widget>
-      </item>
-      <item row="6" column="0">
-       <widget class="QLabel" name="label_8">
+      <item row="8" column="0">
+       <widget class="QLabel" name="label_10">
         <property name="text">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP文件&lt;/span&gt;目录:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#d21f21;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot; color:#000000;&quot;&gt;FTP用户密码&lt;/span&gt;:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
         </property>
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
        </widget>
       </item>
-      <item row="6" column="1">
-       <widget class="QLineEdit" name="lineEdit_ftpPath">
+      <item row="8" column="1">
+       <widget class="QLineEdit" name="lineEdit_ftpPasswd">
         <property name="minimumSize">
          <size>
           <width>172</width>

BIN
ThreeLib/libsignalcompare-v1.1.so


BIN
ThreeLib/libsignalcompare_bck.so


+ 4 - 0
common/DataManager/SystemConfig.cpp

@@ -256,6 +256,8 @@ bool SystemConfigInfo::getDatabaseConfigFromJson(const std::string& jsonStr)
         m_databaseConfig.nListenPort = jsonConfig["ListenPort"].is_null() ? 0 : jsonConfig["ListenPort"].get<int>();
         m_databaseConfig.strRecordFilePath = jsonConfig["RecordFilePath"].is_null() ? "" : QString::fromStdString(jsonConfig["RecordFilePath"].get<std::string>());
         m_databaseConfig.strFtpPath = jsonConfig["FtpPath"].is_null() ? "" : QString::fromStdString(jsonConfig["FtpPath"].get<std::string>());
+        m_databaseConfig.strFtpUser = jsonConfig["FtpUser"].is_null() ? "" : QString::fromStdString(jsonConfig["FtpUser"].get<std::string>());
+        m_databaseConfig.strFtpPassword = jsonConfig["FtpPassword"].is_null() ? "" : QString::fromStdString(jsonConfig["FtpPassword"].get<std::string>());
         
     }nJsonCatch
 
@@ -273,6 +275,8 @@ bool SystemConfigInfo::setDatabaseConfigToJson(const DatabaseConfig_t& databaseC
         jsonConfig["ListenPort"] = databaseConfig.nListenPort;
         jsonConfig["RecordFilePath"] = databaseConfig.strRecordFilePath.toStdString();
         jsonConfig["FtpPath"] = databaseConfig.strFtpPath.toStdString();
+        jsonConfig["FtpUser"] = databaseConfig.strFtpUser.toStdString();
+        jsonConfig["FtpPassword"] = databaseConfig.strFtpPassword.toStdString();
 
         strJson = jsonConfig.dump();
     }nJsonCatch

+ 3 - 1
common/DataManager/SystemConfigStruct.cpp

@@ -112,7 +112,9 @@ bool DatabaseConfig_t::operator==(const DatabaseConfig_t &other) const
         nClientPort == other.nClientPort &&
         nListenPort == other.nListenPort &&
         strRecordFilePath == other.strRecordFilePath &&
-        strFtpPath == other.strFtpPath
+        strFtpPath == other.strFtpPath &&
+        strFtpUser == other.strFtpUser &&
+        strFtpPassword == other.strFtpPassword
     )
     {
         return true;

+ 2 - 0
common/DataManager/SystemConfigStruct.h

@@ -117,6 +117,8 @@ struct DatabaseConfig_t
     int nListenPort = 0;            /* 监听端口 */
     QString strRecordFilePath;      /* 录音文件路径 */
     QString strFtpPath;             /* FTP报警文件路径 */
+    QString strFtpUser;             /* FTP用户名 */
+    QString strFtpPassword;         /* FTP密码 */
 
     bool operator==(const DatabaseConfig_t &other) const;
 };

+ 28 - 1
common/GlobalInfo/GlobalVariable.cpp

@@ -71,6 +71,8 @@ OneCompareItemRoadInfo_t& OneCompareItemRoadInfo_t::operator=(const OneCompareIt
     nCompareRoadNum = other.nCompareRoadNum;
     nSoundCardNum = other.nSoundCardNum;
     nSoundCardRoadNum = other.nSoundCardRoadNum;
+    strCompareItemName = other.strCompareItemName;
+    strCompareRoadName = other.strCompareRoadName;
     return *this;
 }
 
@@ -79,7 +81,10 @@ bool OneCompareItemRoadInfo_t::operator==(const OneCompareItemRoadInfo_t &other)
     return (nCompareItemID == other.nCompareItemID &&
             nCompareRoadNum == other.nCompareRoadNum &&
             nSoundCardNum == other.nSoundCardNum &&
-            nSoundCardRoadNum == other.nSoundCardRoadNum);
+            nSoundCardRoadNum == other.nSoundCardRoadNum &&
+            strCompareItemName == other.strCompareItemName &&
+            strCompareRoadName == other.strCompareRoadName
+            );
 }
 
 
@@ -327,5 +332,27 @@ bool AlarmInfo_t::operator==(const AlarmInfo_t& other) const
 }
 
 
+/* =========================================================================================
+ * 录音文件结构体
+ * =========================================================================================*/
+RecordFileInfo_t& RecordFileInfo_t::operator=(const RecordFileInfo_t& obj)
+{
+    if (this == &obj)
+    {
+        return *this; // 防止自赋值
+    }
+    ItemID = obj.ItemID;
+    ItemName = obj.ItemName;
+    ItemRoadNum = obj.ItemRoadNum;
+    ItemRoadName = obj.ItemRoadName;
+    SoundCardNum = obj.SoundCardNum;
+    SoundCardRoadNum = obj.SoundCardRoadNum;
+    FileStartTime = obj.FileStartTime;
+    FileEndTime = obj.FileEndTime;
+    FileDuration = obj.FileDuration;
+    FilePath = obj.FilePath;
+
+    return *this;
+}
 
 

+ 27 - 2
common/GlobalInfo/GlobalVariable.h

@@ -187,6 +187,8 @@ struct OneCompareItemRoadInfo_t
     int nCompareRoadNum = -1;               /* 对比项通道编号 */
     int nSoundCardNum = -1;                 /* 声卡编号 */
     int nSoundCardRoadNum = -1;             /* 声卡通道编号 */
+    QString strCompareItemName;             /* 对比项名称 */
+    QString strCompareRoadName;             /* 对比项通道名称 */
 
     OneCompareItemRoadInfo_t() = default;
     OneCompareItemRoadInfo_t(const OneCompareItemRoadInfo_t &other);
@@ -367,7 +369,7 @@ struct AlarmInfo_t
 {
     bool isAlarm = false;           /* 是否报警 */
     int CompareItemID = 0;          /* 对比项ID */
-    std::string strCompareItemName; /* 对比项名称 */
+    QString strCompareItemName;     /* 对比项名称 */
 
     CompareItemRoadInfo_t RoadInfo; /* 录音通道信息 */
     ERoadType RoadType;             /* 录音通道类型 */
@@ -381,7 +383,7 @@ struct AlarmInfo_t
     // std::string strAlarmEndTime;    /* 报警结束时间 */
     // std::string strAlarmExistTime;  /* 报警持续时间 */
 
-    std::string strAlarmFilePath;   /* 报警文件路径 */
+    QString strAlarmFilePath;       /* 报警文件路径 */
     int AlarmStartPos = 0;          /* 报警开始位置 */
     QDateTime AlarmFileStartTime;   /* 录音文件开始时间 */
 
@@ -395,6 +397,29 @@ struct AlarmInfo_t
 };
 
 
+/* =========================================================================================
+ * 录音文件结构体
+ * =========================================================================================*/
+struct RecordFileInfo_t
+{
+    int ItemID = -1;                /* 对比项ID */
+    QString ItemName;               /* 对比项名称 */
+    int ItemRoadNum = -1;           /* 对比项通道编号 */
+    QString ItemRoadName;           /* 对比项通道名称 */
+    int SoundCardNum = -1;          /* 声卡编号 */
+    int SoundCardRoadNum = -1;      /* 声卡通道编号 */
+
+    QDateTime FileStartTime;        /* 文件开始时间 */
+    QDateTime FileEndTime;          /* 文件结束时间 */
+    int FileDuration = 0;           /* 文件时长,单位秒 */
+    QString FilePath;               /* 文件路径 */
+
+    RecordFileInfo_t() = default;
+    RecordFileInfo_t(const RecordFileInfo_t& obj) { *this = obj; }
+    RecordFileInfo_t& operator=(const RecordFileInfo_t& obj);
+};
+
+
 
 
 

+ 93 - 6
common/Network/FromWebAPI.cpp

@@ -740,7 +740,7 @@ bool FromWebAPI::insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
             json1["Key"] = Key++;
             nJson jsonAlarm;
             jsonAlarm["itemID"] = it.CompareItemID;
-            jsonAlarm["itemName"] = it.strCompareItemName;
+            jsonAlarm["itemName"] = it.strCompareItemName.toStdString();
             jsonAlarm["alarmType"] = static_cast<int>(it.AlarmType);
             jsonAlarm["soundCardNum"] = it.RoadInfo.nCompareRoadNum;
             jsonAlarm["soundCardName"] = it.RoadInfo.strCompareRoadName.toStdString();
@@ -751,7 +751,7 @@ bool FromWebAPI::insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
             jsonAlarm["alarmStartTime"] = it.StartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
             jsonAlarm["alarmEndTime"] = it.EndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
             jsonAlarm["alarmDuration"] = it.StartTime.secsTo(it.EndTime);
-            jsonAlarm["alarmFilePath"] = it.strAlarmFilePath;
+            jsonAlarm["alarmFilePath"] = it.strAlarmFilePath.toStdString();
             jsonAlarm["fileAlarmStartPos"] = it.AlarmStartPos;
 
             json1["paramList"] = jsonAlarm;
@@ -782,7 +782,7 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         json0["opName"] = "ACAS_InsertTwoAlarmInfo";
         nJson json1;
         json1["itemID1"] = mainAlarm.CompareItemID;
-        json1["itemName1"] = mainAlarm.strCompareItemName;
+        json1["itemName1"] = mainAlarm.strCompareItemName.toStdString();
         json1["alarmType1"] = static_cast<int>(mainAlarm.AlarmType);
         json1["soundCardNum1"] = mainAlarm.RoadInfo.nCompareRoadNum;
         json1["soundCardName1"] = mainAlarm.RoadInfo.strCompareRoadName.toStdString();
@@ -793,11 +793,11 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         json1["alarmStartTime1"] = mainAlarm.StartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
         json1["alarmEndTime1"] = mainAlarm.EndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
         json1["alarmDuration1"] = mainAlarm.StartTime.secsTo(mainAlarm.EndTime);
-        json1["alarmFilePath1"] = mainAlarm.strAlarmFilePath;
+        json1["alarmFilePath1"] = mainAlarm.strAlarmFilePath.toStdString();
         json1["fileAlarmStartPos1"] = mainAlarm.AlarmStartPos;
 
         json1["itemID2"] = subAlarm.CompareItemID;
-        json1["itemName2"] = subAlarm.strCompareItemName;
+        json1["itemName2"] = subAlarm.strCompareItemName.toStdString();
         json1["alarmType2"] = static_cast<int>(subAlarm.AlarmType);
         json1["soundCardNum2"] = subAlarm.RoadInfo.nCompareRoadNum;
         json1["soundCardName2"] = subAlarm.RoadInfo.strCompareRoadName.toStdString();
@@ -808,7 +808,7 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
         json1["alarmStartTime2"] = subAlarm.StartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
         json1["alarmEndTime2"] = subAlarm.EndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
         json1["alarmDuration2"] = subAlarm.StartTime.secsTo(subAlarm.EndTime);
-        json1["alarmFilePath2"] = subAlarm.strAlarmFilePath;
+        json1["alarmFilePath2"] = subAlarm.strAlarmFilePath.toStdString();
         json1["fileAlarmStartPos2"] = subAlarm.AlarmStartPos;
 
         json0["paramList"] = json1;
@@ -827,3 +827,90 @@ bool FromWebAPI::insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const
 }
 
 
+/* 插入录音文件信息 */
+bool FromWebAPI::insertRecordFileInfo(const std::list<RecordFileInfo_t>& listRecordFile)
+{
+    try
+    {
+        int Key = 1;
+        nJson jsonArray = nJson::array();
+        for(auto it : listRecordFile)
+        {
+            nJson json1;
+            json1["opName"] = "ACAS_InsertRecordFileInfo";
+            json1["Key"] = Key++;
+            nJson jsonRecord;
+            jsonRecord["itemID"] = it.ItemID;
+            jsonRecord["itemName"] = it.ItemName.toStdString();
+            jsonRecord["itemRoadNum"] = it.ItemRoadNum;
+            jsonRecord["itemRoadName"] = it.ItemRoadName.toStdString();
+            jsonRecord["soundCardNum"] = it.SoundCardNum;
+            jsonRecord["soundCardRoadNum"] = it.SoundCardRoadNum;
+
+            jsonRecord["fileStartTime"] = it.FileStartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
+            jsonRecord["fileEndTime"] = it.FileEndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
+            jsonRecord["fileDuration"] = it.FileStartTime.secsTo(it.FileEndTime);
+            jsonRecord["filePath"] = it.FilePath.toStdString();
+
+            json1["paramList"] = jsonRecord;
+            
+            jsonArray.push_back(json1);
+        }
+
+        // SPDLOG_LOGGER_DEBUG(m_logger, "写入录音文件信息: {}", jsonArray.dump(4));
+        QString strSend = QString::fromStdString(jsonArray.dump());
+        QString strRet;
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "写入录音文件数据失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+    }nJsonCatch
+
+
+    return true;
+}
+
+/* 更新录音文件信息,更新结束时间和文件名,1分中心写入一次文件,也就更新一次 */
+bool FromWebAPI::updateRecordFileInfo(const std::list<RecordFileInfo_t>& listRecordFile)
+{
+    try
+    {
+        int Key = 1;
+        nJson jsonArray = nJson::array();
+        for(auto it : listRecordFile)
+        {
+            nJson json1;
+            json1["opName"] = "ACAS_UpdateRecordFileEndTime";
+            json1["Key"] = Key++;
+            nJson jsonRecord;
+            jsonRecord["itemID"] = it.ItemID;
+            jsonRecord["itemRoadNum"] = it.ItemRoadNum;
+            jsonRecord["soundCardNum"] = it.SoundCardNum;
+            jsonRecord["soundCardRoadNum"] = it.SoundCardRoadNum;
+
+            jsonRecord["fileStartTime"] = it.FileStartTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
+            jsonRecord["fileEndTime"] = it.FileEndTime.toString("yyyy-MM-dd HH:mm:ss").toStdString();
+            jsonRecord["fileDuration"] = it.FileStartTime.secsTo(it.FileEndTime);
+            jsonRecord["filePath"] = it.FilePath.toStdString();
+
+            json1["paramList"] = jsonRecord;
+            
+            jsonArray.push_back(json1);
+        }
+        QString strSend = QString::fromStdString(jsonArray.dump());
+        QString strRet;
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strSend, strRet);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "更新录音文件数据失败: {}, {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+    }nJsonCatch
+
+    return true;
+}
+
+
+

+ 7 - 0
common/Network/FromWebAPI.h

@@ -56,6 +56,13 @@ public:
     /* 写入一致性报警信息,先写入主通道报警,获取返回的PKID,再写入次通道数据 */
     bool insertConsistencyAlarmInfo(const AlarmInfo_t& mainAlarm, const AlarmInfo_t& subAlarm);
 
+    /* ================================================================================== */
+    /* 插入录音文件信息 */
+    bool insertRecordFileInfo(const std::list<RecordFileInfo_t>& listRecordFile);
+    /* 更新录音文件信息 */
+    bool updateRecordFileInfo(const std::list<RecordFileInfo_t>& listRecordFile);
+
+
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;