Parcourir la source

V0.3.1
1、修改了报警文件的输出位置和输出文件名格式

Apple il y a 1 semaine
Parent
commit
c31e9a1ad1

+ 159 - 116
Server/ThreadRecord/CreateLongFileThread.cpp

@@ -1,5 +1,6 @@
 #include "CreateLongFileThread.h"
 
+#include "AudioData.h"
 #include "GlobalInfo.h"
 #include "spdlog.h"
 #include <cstring>
@@ -35,7 +36,16 @@ bool CreateLongFileThread::setData(const AudioSrcData& srcData)
         return false;
     }
 
+    /* ------------------------------------------------------------------------------- */
+    /* 先写入记录报警文件的环形缓冲区 */
+    auto oldData = m_ringQueue.push_pop(new AudioSrcData(srcData));
+    if(oldData != nullptr)
+    {
+        delete oldData;
+        oldData = nullptr;
+    }
     
+    /* ------------------------------------------------------------------------------- */
     /* 锁定缓冲区 */
     std::lock_guard<std::mutex> lock(m_mutexBuffer);
     /* 如果缓冲区没有分配内存,先分配 */
@@ -111,118 +121,18 @@ void CreateLongFileThread::task()
 
     while(m_isRunning)
     {
-        /* 线程休眠1秒 */
-        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
-        
-        /* 判断缓存是否达到1分钟数据临界值 */
-        {
-            std::lock_guard<std::mutex> lock(m_mutexBuffer);
-            if(m_bufferData.dataSize < m_writeCriticalSize)
-            {
-                continue; // 缓存数据不足,继续等待
-            }
-            /* 数据足够了将缓冲区数据拷贝出来 */
-            memcpy(m_srcData.pData, m_bufferData.pData, m_bufferData.dataSize);
-            m_srcData.dataSize = m_bufferData.dataSize;
-            m_srcData.startTime = m_bufferData.startTime;
-            m_srcData.endTime = m_bufferData.endTime;
-            /* 清空缓冲区数据 */
-            m_bufferData.clear();
-        }
-        // SPDLOG_LOGGER_DEBUG(m_logger, "{} 设置数据,dataSize: {}, startTime: {}, endTime: {}",
-        // m_logBase, m_srcData.dataSize, m_srcData.startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), m_srcData.endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+        /* 线程休眠100ms */
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
 
         /*--------------------------------------------------------------
-         * 打开文件。写入的时候判断是否到达了整点,如果到达了整点,则关闭文件
-         * 重新创建一个新的文件
-         *--------------------------------------------------------------*/
-        bool isNewFile = false;
-        if(m_writtenSize == 0)
-        {
-            /* 如果没有写入过数据,则是新文件 */
-            isNewFile = true;
-            m_writtenStartTime = m_srcData.startTime; // 记录开始时间
-            m_writtenNowTime = m_writtenStartTime; // 记录当前时间
-        }
-        /* 设置今日目录 */
-        if(!setTodayPath(isNewFile))
-        {
-            continue;
-        }
+        * 写入报警文件
+        *--------------------------------------------------------------*/
+
         
-        /* 打开文件 */
-        QFile wavFile;
-        if(!openFile(wavFile, isNewFile))
-        {
-            if(m_openFileErrorSize >= 3)
-            {
-                SPDLOG_LOGGER_ERROR(m_logger, "{} 打开文件失败次数过多,重新开始记录", m_logBase);
-                m_writtenSize = 0;
-                m_writtenStartTime = QDateTime::currentDateTime(); // 重新开始时间
-                m_writtenNowTime = m_writtenStartTime; // 重新开始时间
-                m_wavFileName.clear(); // 清空文件名
-                m_srcData.clear(); // 清空缓冲区数据
-                m_openFileErrorSize = 0; // 重置错误次数
-                continue; // 重新开始记录
-            }
-        }
-        /*--------------------------------------------------------------
-         * 将数据写入文件,并记录其携带的时间和写入的数据大小
-         *--------------------------------------------------------------*/
-        int64_t wSize = 0;
-        {
-            std::lock_guard<std::mutex> lock(m_mutexBuffer);
-            wSize = wavFile.write(m_srcData.pData, m_srcData.dataSize);
-            /* 更新结束时间 */
-            m_writtenNowTime = m_srcData.endTime;
-            /* 清空缓冲区 */
-            m_srcData.clear();
-        }
-        if(wSize < 0)
-        {
-            SPDLOG_LOGGER_ERROR(m_logger, "{} 写入WAV文件失败: {}", m_logBase, wavFile.errorString().toStdString());
-            SPDLOG_LOGGER_WARN(m_logger, "文件路径:{}", m_wavFileName.toStdString());
-            wavFile.close();
-            continue;
-        } else {
-            SPDLOG_LOGGER_TRACE(m_logger, "{} 写入WAV文件成功: {}, 大小: {} 字节", m_logBase, m_wavFileName.toStdString(), wSize);
-        }
-        wavFile.close();
-        // SPDLOG_LOGGER_DEBUG(m_logger, "{} 写入WAV文件完成: {}, 大小: {} 字节", 
-        //     m_logBase, m_wavFileName.toStdString(), wSize);
-    
         /*--------------------------------------------------------------
-         * 对该文件进行其他操作,判断是否已经过了一个整点,修改其文件名称
-         * 现在这里的时间是这一分钟的开始时间,现在需要根据开始时间求出已写入
-         * 数据大小对应的结束时间
-         *--------------------------------------------------------------*/
-        m_writtenSize += wSize;
-        
-        /* 修改文件名称 */
-        QString newFileName = generateFileName(m_writtenStartTime, m_writtenNowTime);
-        if(modifyFileName(m_wavFileName, newFileName))
-        {
-            m_wavFileName = newFileName;
-        }
-        
-        /* 判断是否过了整点 */
-        if(isOneHourPassed())
-        {
-            /* 修改文件头中记录的数据大小 */
-            m_wavHeader.setDataSize(m_writtenSize);
-            m_wavHeader.calculateDerivedFields();
-            modifyWavFileHeader(m_wavFileName, m_wavHeader);
-
-            SPDLOG_LOGGER_INFO(m_logger, "{} 结束记录一个文件: {}, 已写入大小: {} 字节", 
-                m_logBase, m_wavFileName.toStdString(), m_writtenSize);
-
-            /* 重置已写入大小 */
-            m_writtenSize = 0;
-            m_writtenStartTime = QDateTime();       // 重新开始时间
-            m_writtenNowTime = m_writtenStartTime;  // 重新开始时间
-            m_wavFileName.clear();                  // 清空文件名
-            m_openFileErrorSize = 0;                // 重置错误次数
-        }
+        * 写入长记录文件
+        *--------------------------------------------------------------*/
+        writeLongRecordFile();
         
     }
     SPDLOG_LOGGER_WARN(m_logger, "➢ {} 记录长文件线程结束运行", m_logBase);
@@ -251,6 +161,9 @@ bool CreateLongFileThread::initData()
     m_bufferData.allocateMemory(m_writeCriticalSize * 3);
     m_srcData.allocateMemory(m_writeCriticalSize * 3);
 
+    /* 设置环形队列大小 */
+    m_ringQueue.setQueueCapacity(GInfo.queueElementCount());
+
     return true;
 }
 
@@ -261,6 +174,119 @@ void CreateLongFileThread::clearData()
     m_bufferData.clear();
 }
 
+/* 写入长记录文件 */
+bool CreateLongFileThread::writeLongRecordFile()
+{
+    /* 判断缓存是否达到1分钟数据临界值 */
+    {
+        std::lock_guard<std::mutex> lock(m_mutexBuffer);
+        if(m_bufferData.dataSize < m_writeCriticalSize)
+        {
+            return true; // 缓存数据不足,继续等待
+        }
+        /* 数据足够了将缓冲区数据拷贝出来 */
+        memcpy(m_srcData.pData, m_bufferData.pData, m_bufferData.dataSize);
+        m_srcData.dataSize = m_bufferData.dataSize;
+        m_srcData.startTime = m_bufferData.startTime;
+        m_srcData.endTime = m_bufferData.endTime;
+        /* 清空缓冲区数据 */
+        m_bufferData.clear();
+    }
+    // SPDLOG_LOGGER_DEBUG(m_logger, "{} 设置数据,dataSize: {}, startTime: {}, endTime: {}",
+    // m_logBase, m_srcData.dataSize, m_srcData.startTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), m_srcData.endTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+    /*--------------------------------------------------------------
+     * 打开文件。写入的时候判断是否到达了整点,如果到达了整点,则关闭文件
+     * 重新创建一个新的文件
+     *--------------------------------------------------------------*/
+    bool isNewFile = false;
+    if(m_writtenSize == 0)
+    {
+        /* 如果没有写入过数据,则是新文件 */
+        isNewFile = true;
+        m_writtenStartTime = m_srcData.startTime; // 记录开始时间
+        m_writtenNowTime = m_writtenStartTime; // 记录当前时间
+    }
+    /* 设置今日目录 */
+    if(!setTodayPath(isNewFile))
+    {
+        return false;
+    }
+    
+    /* 打开文件 */
+    QFile wavFile;
+    if(!openFile(wavFile, isNewFile))
+    {
+        if(m_openFileErrorSize >= 3)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "{} 打开文件失败次数过多,重新开始记录", m_logBase);
+            m_writtenSize = 0;
+            m_writtenStartTime = QDateTime::currentDateTime(); // 重新开始时间
+            m_writtenNowTime = m_writtenStartTime; // 重新开始时间
+            m_wavFileName.clear(); // 清空文件名
+            m_srcData.clear(); // 清空缓冲区数据
+            m_openFileErrorSize = 0; // 重置错误次数
+            return false; // 重新开始记录
+        }
+    }
+    /*--------------------------------------------------------------
+     * 将数据写入文件,并记录其携带的时间和写入的数据大小
+     *--------------------------------------------------------------*/
+    int64_t wSize = 0;
+    {
+        std::lock_guard<std::mutex> lock(m_mutexBuffer);
+        wSize = wavFile.write(m_srcData.pData, m_srcData.dataSize);
+        /* 更新结束时间 */
+        m_writtenNowTime = m_srcData.endTime;
+        /* 清空缓冲区 */
+        m_srcData.clear();
+    }
+    if(wSize < 0)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{} 写入WAV文件失败: {}", m_logBase, wavFile.errorString().toStdString());
+        SPDLOG_LOGGER_WARN(m_logger, "文件路径:{}", m_wavFileName.toStdString());
+        wavFile.close();
+        return false;
+    } else {
+        SPDLOG_LOGGER_TRACE(m_logger, "{} 写入WAV文件成功: {}, 大小: {} 字节", m_logBase, m_wavFileName.toStdString(), wSize);
+    }
+    wavFile.close();
+    // SPDLOG_LOGGER_DEBUG(m_logger, "{} 写入WAV文件完成: {}, 大小: {} 字节", 
+    //     m_logBase, m_wavFileName.toStdString(), wSize);
+
+    /*--------------------------------------------------------------
+     * 对该文件进行其他操作,判断是否已经过了一个整点,修改其文件名称
+     * 现在这里的时间是这一分钟的开始时间,现在需要根据开始时间求出已写入
+     * 数据大小对应的结束时间
+     *--------------------------------------------------------------*/
+    m_writtenSize += wSize;
+    
+    /* 修改文件名称 */
+    QString newFileName = generateFileName(m_writtenStartTime, m_writtenNowTime);
+    if(modifyFileName(m_wavFileName, newFileName))
+    {
+        m_wavFileName = newFileName;
+    }
+    
+    /* 判断是否过了整点 */
+    if(isOneHourPassed())
+    {
+        /* 修改文件头中记录的数据大小 */
+        m_wavHeader.setDataSize(m_writtenSize);
+        m_wavHeader.calculateDerivedFields();
+        modifyWavFileHeader(m_wavFileName, m_wavHeader);
+        SPDLOG_LOGGER_INFO(m_logger, "{} 结束记录一个文件: {}, 已写入大小: {} 字节", 
+            m_logBase, m_wavFileName.toStdString(), m_writtenSize);
+        /* 重置已写入大小 */
+        m_writtenSize = 0;
+        m_writtenStartTime = QDateTime();       // 重新开始时间
+        m_writtenNowTime = m_writtenStartTime;  // 重新开始时间
+        m_wavFileName.clear();                  // 清空文件名
+        m_openFileErrorSize = 0;                // 重置错误次数
+    }
+
+    return true;
+}
+
 /* 设置今日目录 */
 bool CreateLongFileThread::setTodayPath(bool isNewFile)
 {
@@ -401,13 +427,14 @@ bool CreateLongFileThread::isOneHourPassed()
 /* 生成报警文件名 */
 QString CreateLongFileThread::generateAlarmFileName(const AlarmInfo_t& alarmInfo, bool isNewFile)
 {
+    QString retFileName;
     if(isNewFile)
     {
         /* 先检查是否已经过了一天了,设置日期文件夹 */
         setTodayAlarmPath();
 
         /* 检查这个对比项的报警文件夹是否存在 */
-        QString itemDirName = QString::fromStdString(alarmInfo.strCompareItemName);
+        QString itemDirName = QString("CompareItemID_%1").arg(QString::number(alarmInfo.CompareItemID));
         QDir itemDir = m_todayDirAlarm;
         itemDir.cd(itemDirName);
         if(!itemDir.exists())
@@ -420,18 +447,34 @@ QString CreateLongFileThread::generateAlarmFileName(const AlarmInfo_t& alarmInfo
                 SPDLOG_LOGGER_INFO(m_logger, "{} 创建报警文件夹成功: {}", m_logBase, itemDirName.toStdString());
             }
         }
-        /* 生成文件名, 格式: Alarm_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav */
-        QString fileName = QString("Alarm_%1_%2_%3-%4.wav")
-            .arg(alarmInfo.RoadInfo.nCompareRoadNum)
+        /* 生成文件名, 格式: Alarm_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav
+           这里创建的录音文件只有开始日期,没有结束日期,等报警结束之后才会有结束日期 */
+        QString fileName = QString("Alarm_%1_%2_%3-.wav")
+            .arg(QString::number(alarmInfo.RoadInfo.nCompareRoadNum))
             .arg(getAlarmTypeString(alarmInfo.AlarmType))
-            .arg(alarmInfo.StartTime.toString("yyyyMMdd_hhmmss"))
-            .arg(alarmInfo.EndTime.toString("yyyyMMdd_hhmmss"));
+            .arg(alarmInfo.StartTime.toString("yyyyMMdd_hhmmss"));
+        
+        /* 拼接文件夹路径 */
+        retFileName = itemDir.filePath(fileName);
     }else 
     {
-    
+        /* 已有的文件,是报警结束的文件名 */
+        retFileName = QString::fromStdString(alarmInfo.strAlarmFilePath);
+        /* 这里的文件名格式是:Alarm_CompareItemID_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav,
+           这里带上结束时间 */
+        QString endTimeStr = alarmInfo.EndTime.toString("yyyyMMdd_hhmmss");
+        /* 替换掉原来的结束时间 */
+        retFileName.replace("-.wav", QString("-%1.wav").arg(endTimeStr));    
     }
 
-    return QString();
+    return retFileName;
+}
+
+
+/* 写入报警文件 */
+void CreateLongFileThread::writeAlarmFile()
+{
+    /* 先判断环形队列中数据是否足够的秒数,不一定是每一秒都会写的 */
 }
 
 

+ 14 - 4
Server/ThreadRecord/CreateLongFileThread.h

@@ -4,6 +4,7 @@
 #include "BaseRecordThread.h"
 #include "AudioData.h"
 #include "GlobalVariable.h"
+#include "RingQueue.hpp"
 
 #include <mutex>
 #include <QFile>
@@ -90,7 +91,7 @@ struct AlarmValue_t
     文件夹路径格式:
         1、长录音文件夹: Application/ACAServerData/Record/yyyy-MM-dd/SoundCardID-RoadNum/Record_yyyy-MM-dd-hh-mm-ss-yyyy-MM-dd-hh-mm-ss.wav
               例如:Application/2025-01-01/SoundCard1-1/Record_2025-01-01-12-00-00-2025-01-01-12-01-00.wav
-        2、报警录音文件夹:Application/ACAServerData/AlarmWav/yyyy-MM-dd/CompareItemID-RoadNum/Alarm_CompareItemID_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav
+        2、报警录音文件夹:Application/ACAServerData/AlarmWav/yyyy-MM-dd/CompareItemName/Alarm_CompareItemID_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav
               例如:Application/2025-01-01/1-1/Alarm_1_1_Silent_20250101_120000-20250101_120100.wav
 
  */
@@ -117,6 +118,9 @@ private:
     /* 清理数据 */
     void clearData() override;
 
+    /*===============================================================================*/
+    /* 写入长记录文件 */
+    bool writeLongRecordFile();
     /* 设置今日目录 */
     inline bool setTodayPath(bool isNewFile);
     /* 打开文件 */
@@ -128,6 +132,9 @@ private:
     /* 判断是否过了整点 */
     inline bool isOneHourPassed();
 
+    /*===============================================================================*/
+    /* 写入报警文件 */
+    void writeAlarmFile();
     /* 生成报警文件名 */
     inline QString generateAlarmFileName(const AlarmInfo_t& alarmInfo, bool isNewFile);
     /* 设置今日报警文件夹 */
@@ -161,9 +168,12 @@ private:
     /* 报警文件名,key是报警信息,value是文件信息 */
     std::map<AlarmKey_t, AlarmValue_t> m_mapAlarmFile;
 
-    QDir m_yesterdayDir;            /* 昨日目录,用来给还未录制完成的报警文件使用的 */
-    QDir m_todayDirAlarm;           /* 今日报警目录,这个目录只到日期,里面的子文件夹是对比项相关的 */
-    QDate m_todayDateAlarm;         /* 今日日期,记录报警文件用 */
+    QDir m_yesterdayDir;                    /* 昨日目录,用来给还未录制完成的报警文件使用的 */
+    QDir m_todayDirAlarm;                   /* 今日报警目录,这个目录只到日期,里面的子文件夹是对比项相关的 */
+    QDate m_todayDateAlarm;                 /* 今日日期,记录报警文件用 */
+
+    RingQueue<AudioSrcData*> m_ringQueue;   /* 环形队列,存储几分钟的数据,用来写入报警文件 */
+    QDateTime m_alarmWrittenTime;       /* 报警文件中环形队列已写入文件的时间 */
 };