Browse Source

V0.2.8
1、修改了报警信息的处理方式

Apple 1 week ago
parent
commit
c4a1f1158b

+ 9 - 0
SQL/ACAServer.sql

@@ -62,4 +62,13 @@ FROM tACAAlarmLog
 SELECT *
 FROM tACAAlarmFile;
 
+#插入报警信息
+INSERT INTO tACAAlarmInfo (
+    ItemID, ItemName, AlarmType, SoundCardNum, SoundCardName, SoundCardRoadNum, CompareRoadNum, CompareRoadName, CompareRoadType, 
+    AlarmStartTime, AlarmEndTime, AlarmDuration, AlarmFilePath, FileAlarmStartPos )
+VALUES (
+    @itemID, @itemName, @alarmType, @soundCardNum, @soundCardName, @soundCardRoadNum, @compareRoadNum, @compareRoadName, @compareRoadType, 
+    @alarmStartTime, @alarmEndTime, @alarmDuration, @alarmFilePath, @fileAlarmStartPos );
+
+
 

+ 29 - 1
SQL/ACASetting.sqlbook

@@ -142,6 +142,7 @@ COMMENT ON COLUMN tACADetectPeriod.ApplyNoise IS '是否应用噪音检测';
 -- 创建索引
 CREATE INDEX idx_tACADetectPeriod_ItemID ON tACADetectPeriod (ItemID);
 -- SQLBook: Code
+-- Active: 1752920752747@@192.1.2.61@5236@EQM_CESHI
 #创建报警记录表
 CREATE TABLE tACAAlarmInfo
 (
@@ -159,5 +160,32 @@ CREATE TABLE tACAAlarmInfo
     AlarmEndTime VARCHAR(32), -- 报警结束时间 (格式:YYYY-MM-DD HH:MM:SS)
     AlarmDuration INT, -- 报警持续时间(秒数)
     AlarmFilePath VARCHAR(256), -- 报警录音文件路径
-    
+    FileAlarmStartPos int -- 在报警录音文件中报警开始的时间
 )
+
+-- 表注释
+COMMENT ON TABLE tACAAlarmInfo IS 'ACA报警记录表';
+-- 字段注释
+COMMENT ON COLUMN tACAAlarmInfo.PKID IS '主键ID';
+COMMENT ON COLUMN tACAAlarmInfo.ItemID IS '对比项ID';
+COMMENT ON COLUMN tACAAlarmInfo.ItemName IS '对比项名称';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmType IS '报警类型,1-静音,2-过载,3-反相,4-噪音';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardNum IS '声卡编号(在系统中的编号)';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardName IS '声卡名称';
+COMMENT ON COLUMN tACAAlarmInfo.SoundCardRoadNum IS '声卡通道编号';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadNum IS '对比通道编号';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadName IS '对比通道名称';
+COMMENT ON COLUMN tACAAlarmInfo.CompareRoadType IS '通道类型:1、主输出,2、空收,3、主输出空收';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmStartTime IS '报警开始时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmEndTime IS '报警结束时间 (格式:YYYY-MM-DD HH:MM:SS)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmDuration IS '报警持续时间(秒数)';
+COMMENT ON COLUMN tACAAlarmInfo.AlarmFilePath IS '报警录音文件路径';
+COMMENT ON COLUMN tACAAlarmInfo.FileAlarmStartPos IS '在报警录音文件中报警开始的时间';
+-- 创建索引
+CREATE INDEX idx_tACAAlarmInfo_ItemID ON tACAAlarmInfo (ItemID);
+CREATE INDEX idx_tACAAlarmInfo_AlarmType ON tACAAlarmInfo (AlarmType);
+CREATE INDEX idx_tACAAlarmInfo_SoundCardNum ON tACAAlarmInfo (SoundCardNum);
+CREATE INDEX idx_tACAAlarmInfo_SoundCardRoadNum ON tACAAlarmInfo (SoundCardRoadNum);
+CREATE INDEX idx_tACAAlarmInfo_CompareRoadNum ON tACAAlarmInfo (CompareRoadNum);
+CREATE INDEX idx_tACAAlarmInfo_AlarmStartTime ON tACAAlarmInfo (AlarmStartTime);
+CREATE INDEX idx_tACAAlarmInfo_AlarmEndTime ON tACAAlarmInfo (AlarmEndTime);

+ 0 - 35
Server/DataStruct/AlarmInfo.cpp

@@ -1,35 +0,0 @@
-#include "AlarmInfo.h"
-
-
-AlarmInfo_t& AlarmInfo_t::operator=(const AlarmInfo_t& obj)
-{
-    if (this == &obj)
-    {
-        return *this; // 防止自赋值
-    }
-    isAlarm = obj.isAlarm;
-    CompareItemID = obj.CompareItemID;
-    strCompareItemName = obj.strCompareItemName;
-    RoadInfo = obj.RoadInfo;
-    RoadType = obj.RoadType;
-    AlarmType = obj.AlarmType;
-    StartTime = obj.StartTime;
-    EndTime = obj.EndTime;
-    strAlarmFilePath = obj.strAlarmFilePath;
-    AlarmStartPos = obj.AlarmStartPos;
-    AlarmFileStartTime = obj.AlarmFileStartTime;
-    return *this;
-}
-
-
-/* 比较是否相等,主要是比较是否报警、通道ID,报警类型,报警时间 */
-bool AlarmInfo_t::operator==(const AlarmInfo_t& other) const
-{
-    return (isAlarm == other.isAlarm) &&
-           (RoadInfo == other.RoadInfo) &&
-           (AlarmType == other.AlarmType) &&
-           (StartTime == other.StartTime) &&
-           (EndTime == other.EndTime);
-}
-
-

+ 0 - 74
Server/DataStruct/AlarmInfo.h

@@ -1,74 +0,0 @@
-#ifndef _ALARMINFO_H_
-#define _ALARMINFO_H_
-
-#include <QDateTime>
-#include <string>
-
-#include "GlobalVariable.h"
-
-/**
- * @brief 录音通道类型
- * 
- */
-enum class ERoadType
-{
-    RoadType_Main = 0,      /* 主输出 */
-    RoadType_SpaceReceive,  /* 空间接收 */
-    RoadType_SpaceSend,     /* 空间发送 */
-};
-
-/**
- * @brief 报警类型
- * 
- */
-enum class EAlarmType
-{
-    EAT_None = 0,           /* 无报警 */
-    EAT_Silent,             /* 静音报警 */
-    EAT_Overload,           /* 过载报警 */
-    EAT_Reversed,           /* 反相报警 */
-    EAR_Consistency,        /* 一致性报警 */
-    EAT_Noise,              /* 噪音报警 */
-    EAT_Unknown,            /* 未知报警 */
-};
-
-
-/**
- * @brief 报警结构体
- * 
- */
-struct AlarmInfo_t
-{
-    bool isAlarm = false;           /* 是否报警 */
-    int CompareItemID = 0;          /* 对比项ID */
-    std::string strCompareItemName; /* 对比项名称 */
-
-    CompareItemRoadInfo_t RoadInfo; /* 录音通道信息 */
-    ERoadType RoadType;             /* 录音通道类型 */
-
-    EAlarmType AlarmType = EAlarmType::EAT_None; /* 报警类型 */
-
-    QDateTime StartTime;            /* 报警开始时间 */
-    QDateTime EndTime;              /* 报警结束时间 */
-
-    // std::string strAlarmStartTime;  /* 报警发生时间 */
-    // std::string strAlarmEndTime;    /* 报警结束时间 */
-    // std::string strAlarmExistTime;  /* 报警持续时间 */
-
-    std::string strAlarmFilePath;   /* 报警文件路径 */
-    int AlarmStartPos = 0;          /* 报警开始位置 */
-    QDateTime AlarmFileStartTime;   /* 录音文件开始时间 */
-
-    AlarmInfo_t() = default;
-    AlarmInfo_t(const AlarmInfo_t& obj) { *this = obj; }
-    AlarmInfo_t& operator=(const AlarmInfo_t& obj);
-
-    /* 比较是否相等,主要是比较是否报警、通道ID,报警类型,报警时间 */
-    bool operator==(const AlarmInfo_t& other) const;
-
-};
-
-
-
-
-#endif // _ALARMINFO_H_

+ 0 - 33
Server/GlobalInfo/GlobalVariable.cpp__

@@ -1,33 +0,0 @@
-#include "GlobalVariable.h"
-
-#include "spdlog/spdlog.h"
-
-#include <QFile>
-
-
-
-
-
-/* =========================================================================================
- * 计算线程信息结构体
- * =========================================================================================*/
-CalculateThreadInfo_t::CalculateThreadInfo_t(const CalculateThreadInfo_t& info)
-{
-    *this = info; // 使用赋值运算符进行深拷贝
-}
-
-CalculateThreadInfo_t& CalculateThreadInfo_t::operator=(const CalculateThreadInfo_t& info)
-{
-    if(&info == this)
-    {
-        return *this; // 防止自赋值
-    }
-    CompareItemID = info.CompareItemID;
-    strCompareItemName = info.strCompareItemName;
-    vecRoad = info.vecRoad;
-    threadState = info.threadState;
-    threadType = info.threadType;
-    pThread = info.pThread;
-
-    return *this;
-}

+ 0 - 193
Server/GlobalInfo/GlobalVariable.h__

@@ -1,193 +0,0 @@
-#ifndef _GLOBALVARIABLE_H_
-#define _GLOBALVARIABLE_H_
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-class QString;
-
-
-
-
-/* =========================================================================================
- * 枚举
- * =========================================================================================*/
-/**
- * @brief 录音通道枚举
- * 
- */
-enum class ERoadID
-{
-    RoadID_None = 0,      /* 无通道 */
-    RoadID_1 = 1,         /* 通道1 */
-    RoadID_2,             /* 通道2 */
-    RoadID_3,             /* 通道3 */
-    RoadID_4,             /* 通道4 */
-    RoadID_5,             /* 通道5 */
-    RoadID_6,             /* 通道6 */
-    RoadID_7,             /* 通道7 */
-    RoadID_8,             /* 通道8 */
-    RoadID_9,             /* 通道9 */
-    RoadID_10,            /* 通道10 */
-    RoadID_11,            /* 通道11 */
-    RoadID_12,            /* 通道12 */
-    RoadID_13,            /* 通道13 */
-    RoadID_14,            /* 通道14 */
-    RoadID_15,            /* 通道15 */
-    RoadID_16,            /* 通道16 */
-    RoadID_17,            /* 通道17 */
-    RoadID_18,            /* 通道18 */
-    RoadID_19,            /* 通道19 */
-    RoadID_20,            /* 通道20 */
-    RoadID_21,            /* 通道21 */
-    RoadID_22,            /* 通道22 */
-    RoadID_23,            /* 通道23 */
-    RoadID_24,            /* 通道24 */
-    RoadID_25,            /* 通道25 */
-    RoadID_26,            /* 通道26 */
-    RoadID_27,            /* 通道27 */
-    RoadID_28,            /* 通道28 */
-    RoadID_29,            /* 通道29 */
-    RoadID_30,            /* 通道30 */
-    RoadID_31,            /* 通道31 */
-    RoadID_32,            /* 通道32 */
-    RoadID_33,            /* 通道33 */
-    RoadID_34,            /* 通道34 */
-    RoadID_35,            /* 通道35 */
-    RoadID_36,            /* 通道36 */
-    RoadID_37,            /* 通道37 */
-    RoadID_38,            /* 通道38 */
-    RoadID_39,            /* 通道39 */
-    RoadID_40,            /* 通道40 */
-    RoadID_41,            /* 通道41 */
-    RoadID_42,            /* 通道42 */
-    RoadID_43,            /* 通道43 */
-    RoadID_44,            /* 通道44 */
-    RoadID_45,            /* 通道45 */
-    RoadID_46,            /* 通道46 */
-    RoadID_47,            /* 通道47 */
-    RoadID_48,            /* 通道48 */
-    RoadID_49,            /* 通道49 */
-    RoadID_50,            /* 通道50 */
-    RoadID_51,            /* 通道51 */
-    RoadID_52,            /* 通道52 */
-    RoadID_53,            /* 通道53 */
-    RoadID_54,            /* 通道54 */
-    RoadID_55,            /* 通道55 */
-    RoadID_56,            /* 通道56 */
-    RoadID_57,            /* 通道57 */
-    RoadID_58,            /* 通道58 */
-    RoadID_59,            /* 通道59 */
-    RoadID_60,            /* 通道60 */
-    RoadID_61,            /* 通道61 */
-    RoadID_62,            /* 通道62 */
-    RoadID_63,            /* 通道63 */
-    RoadID_64,            /* 通道64 */
-    RoadID_MAX = RoadID_64, /* 最大通道数 */
-};
-
-
-
-
-
-
-/* =========================================================================================
- * 线程信息相关枚举和结构体
- * =========================================================================================*/
-
- /**
- * @brief 线程状态枚举
- * 
- */
-enum class EThreadState
-{
-    State_None = 0,         /* 无状态 */
-    State_Inited,           /* 已初始化 */
-    State_Running,          /* 运行中 */
-    State_Stopped,          /* 已停止 */
-    State_Error             /* 错误状态 */
-};
-
-/**
- * @brief 线程类型枚举
- * 
- */
-enum class EThreadType
-{
-    Type_None = 0,              /* 无类型 */
-    Type_RecordSrc,             /* 录音源线程 */
-    Type_AssignSrcData,         /* 分派数据线程 */
-    Type_CreateWAV,             /* 生成WAV文件线程 */
-    Type_CalculateDBAndPhase,   /* 计算音量和反相线程 */
-    // Type_CreateNoise,           /* 生成噪音数据线程 */
-    Type_CreateLongWAV,         /* 生成长文件线程 */
-    Type_RtpSend,               /* RTP发送线程 */
-    Type_ConsistencyCheck,      /* 一致性检查线程 */
-    Type_CheckDBAndPhase        /* 检查音量和反相线程 */
-};
-
-/**
- * @brief 录音通道信息
- * 
- */
-struct RoadNumberInfo_t
-{
-    ERoadID roadID;                             /* 录音通道编号 */
-    std::string strRoadName;                    /* 录音通道名称 */
-    int roadNum;                                /* 录音通道编号,在对比项里的编号 */
-
-    RoadNumberInfo_t() = default;
-    RoadNumberInfo_t(const RoadNumberInfo_t& info)
-        : roadID(info.roadID), strRoadName(info.strRoadName), roadNum(info.roadNum) {}
-    RoadNumberInfo_t& operator=(const RoadNumberInfo_t& info)
-    {
-        if (this == &info) return *this; // 防止自赋值
-        roadID = info.roadID;
-        strRoadName = info.strRoadName;
-        roadNum = info.roadNum;
-        return *this;
-    }
-};
-
-class BaseRecordThread; /* 录音线程基类 */
-/**
- * @brief 录音线程信息结构体
- */
-struct RecordThreadInfo_t
-{
-    RoadNumberInfo_t RoadInfo;                  /* 录音通道信息 */
-    EThreadType threadType;                     /* 线程类型 */
-    EThreadState threadState;                   /* 线程状态 */
-    // BaseRecordThread* pThread = nullptr;        /* 线程对象 */
-};
-
-
-
-
-class BaseCalculateThread;
-/**
- * @brief 计算线程信息结构体
- * 
- */
-struct CalculateThreadInfo_t
-{
-    int CompareItemID;                              /* 对比项ID */
-    std::string strCompareItemName;                 /* 对比项名称 */
-    std::vector<RoadNumberInfo_t> vecRoad;          /* 其他对比项录音通道编号列表 */
-
-    EThreadType threadType;                         /* 线程类型 */
-    EThreadState threadState;                       /* 线程状态 */
-    BaseCalculateThread* pThread = nullptr;         /* 计算线程对象 */
-
-    CalculateThreadInfo_t() = default;
-    CalculateThreadInfo_t(const CalculateThreadInfo_t& info);
-    CalculateThreadInfo_t& operator=(const CalculateThreadInfo_t& info);
-    
-
-};
-
-
-
-
-#endif // _GLOBALVARIABLE_H_

+ 113 - 26
Server/ThreadCalculate/CalculateDBThread.cpp

@@ -1,4 +1,5 @@
 #include "CalculateDBThread.h"
+#include "GlobalVariable.h"
 #include "spdlog.h"
 
 #include "ThreadManager.h"
@@ -23,8 +24,13 @@ OneRoadVolume_t CalculateDBThread::getVolumeInfo()
     return m_roadVolumeInfo;
 }
 
-/* 获取最新的结果
- * 结果包括:静音、过载、反相和音量包信息
+/**
+ * @brief   获取最新的结果
+ *          结果包括:静音、过载、反相和音量包信息
+ * 
+ * @param volumeInfo 
+ * @return true 结果更新成功
+ * @return false 没有更新结果,可能是没有,也可能传入的已经是最新的结果了
  */
 bool CalculateDBThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
 {
@@ -52,17 +58,44 @@ bool CalculateDBThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
 }
 
 /* 获取报警数据 */
-const AlarmInfo_t& CalculateDBThread::getAlarm(EAlarmType alarmType)
+AlarmInfo_t CalculateDBThread::getAlarm(EAlarmType alarmType)
 {
     std::lock_guard<std::mutex> lock(m_mutexVolumeInfo);
     switch(alarmType)
     {
         case EAlarmType::EAT_Silent:
-            return m_alarmLastSilence;
+            {
+                if(m_alarmSilence.AlarmType != EAlarmType::EAT_None && m_alarmLastSilence.isAlarm == false)
+                {
+                    /* 报警结束了,返回报警信息,并清空 */
+                    AlarmInfo_t alarmInfo = m_alarmLastSilence;
+                    m_alarmLastSilence = AlarmInfo_t(); // 清空报警信息
+                    return alarmInfo;
+                }
+                return m_alarmSilence;
+            }
         case EAlarmType::EAT_Overload:
-            return m_alarmLastOverload;
+            {
+                if(m_alarmOverload.AlarmType != EAlarmType::EAT_None && m_alarmLastOverload.isAlarm == false)
+                {
+                    /* 报警结束了,返回报警信息,并清空 */
+                    AlarmInfo_t alarmInfo = m_alarmLastOverload;
+                    m_alarmLastOverload = AlarmInfo_t(); // 清空报警信息
+                    return alarmInfo;
+                }
+                return m_alarmOverload;
+            }
         case EAlarmType::EAT_Reversed:
-            return m_alarmLastPhase;
+            {
+                if(m_alarmPhase.AlarmType != EAlarmType::EAT_None && m_alarmLastPhase.isAlarm == false)
+                {
+                    /* 报警结束了,返回报警信息,并清空 */
+                    AlarmInfo_t alarmInfo = m_alarmLastPhase;
+                    m_alarmLastPhase = AlarmInfo_t(); // 清空报警信息
+                    return alarmInfo;
+                }
+                return m_alarmPhase;
+            }
         default:
             SPDLOG_LOGGER_ERROR(m_logger, "{} 获取报警数据失败,未知报警类型: {}", m_logBase, static_cast<int>(alarmType));
             return m_alarmNull; // 返回一个空的报警信息
@@ -276,18 +309,36 @@ void CalculateDBThread::processSilence()
             {
                 m_alarmSilence.EndTime = m_currSecondData.endTime.addSecs(- m_volumeParam.GetSilentDuration());
             }
-            m_alarmSilence.strAlarmFilePath = generateAlarmFilePath(m_alarmSilence); // 生成报警文件路径
             /* 保存报警信息 */
-            m_alarmLastSilence = m_alarmSilence;
-            m_alarmSilence = AlarmInfo_t(); // 清空报警信息
+            // m_alarmLastSilence = m_alarmSilence;
+            // m_alarmSilence = AlarmInfo_t(); // 清空报警信息,报警信息在对比项获取到结果后再清空
             /* 将报警信息给截取报警文件的线程 */
 
             /* 打印日志 */
-            SPDLOG_LOGGER_INFO(m_logger, "{} 静音报警结束,开始时间:{},结束时间:{},文件路径:{}",
+            SPDLOG_LOGGER_INFO(m_logger, "{} 静音报警结束,开始时间:{},结束时间:{}",
                 m_logBase, 
-                m_alarmLastSilence.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmLastSilence.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmLastSilence.strAlarmFilePath);
+                m_alarmSilence.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
+                m_alarmSilence.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+        }
+    }
+
+    /* 更新结果,实时更新 */
+    if(m_alarmSilence.AlarmType != EAlarmType::EAT_None)
+    {
+        /* 有报警类型,进一步判断是否有报警 */
+        if(m_alarmSilence.isAlarm)
+        {
+            /* 有报警,更新报警信息,判断一下上次的报警是否被取走 */
+            if(m_alarmLastSilence.AlarmType == EAlarmType::EAT_None || m_alarmLastSilence.isAlarm == true)
+            {
+                /* 报警结束信息被取走了,清空了结果,或者正在报警中,更新信息 */
+                m_alarmLastSilence = m_alarmSilence;
+            }
+        }else 
+        {
+            /* 有报警类型无报警,说明是报警结束了 */
+            m_alarmLastSilence = m_alarmSilence;
+            m_alarmSilence = AlarmInfo_t(); // 清空报警信息
         }
     }
 }
@@ -340,18 +391,36 @@ void CalculateDBThread::processOverload()
             {
                 m_alarmOverload.EndTime = m_currSecondData.endTime.addSecs(- m_volumeParam.GetOverloadDuration());
             }
-            m_alarmOverload.strAlarmFilePath = generateAlarmFilePath(m_alarmOverload); // 生成报警文件路径
             /* 保存报警信息 */
-            m_alarmLastOverload = m_alarmOverload;
-            m_alarmOverload = AlarmInfo_t(); // 清空报警信息
+            // m_alarmLastOverload = m_alarmOverload;
+            // m_alarmOverload = AlarmInfo_t(); // 清空报警信息
             /* 将报警信息给截取报警文件的线程 */
 
             /* 打印日志 */
-            SPDLOG_LOGGER_INFO(m_logger, "{} 过载报警结束,开始时间:{},结束时间:{},文件路径:{}",
+            SPDLOG_LOGGER_INFO(m_logger, "{} 过载报警结束,开始时间:{},结束时间:{}",
                 m_logBase, 
-                m_alarmLastOverload.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmLastOverload.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmLastOverload.strAlarmFilePath);
+                m_alarmOverload.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
+                m_alarmOverload.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+        }
+    }
+
+    /* 更新结果,实时更新 */
+    if(m_alarmOverload.AlarmType != EAlarmType::EAT_None)
+    {
+        /* 有报警类型,进一步判断是否有报警 */
+        if(m_alarmOverload.isAlarm)
+        {
+            /* 有报警,更新报警信息,判断一下上次的报警是否被取走 */
+            if(m_alarmLastOverload.AlarmType == EAlarmType::EAT_None || m_alarmLastOverload.isAlarm == true)
+            {
+                /* 报警结束信息被取走了,或者正在报警中,更新信息 */
+                m_alarmLastOverload = m_alarmOverload;
+            }
+        }else 
+        {
+            /* 有报警类型无报警,说明是报警结束了 */
+            m_alarmLastOverload = m_alarmOverload;
+            m_alarmOverload = AlarmInfo_t(); // 清空报警信息
         }
     }
     
@@ -405,17 +474,35 @@ void CalculateDBThread::processPhase()
             {
                 m_alarmPhase.EndTime = m_currSecondData.endTime.addSecs(- m_volumeParam.GetPhaseDuration());
             }
-            m_alarmPhase.strAlarmFilePath = generateAlarmFilePath(m_alarmPhase); // 生成报警文件路径
             /* 保存报警信息 */
-            m_alarmLastPhase = m_alarmPhase;
-            m_alarmPhase = AlarmInfo_t(); // 清空报警信息
+            // m_alarmLastPhase = m_alarmPhase;
+            // m_alarmPhase = AlarmInfo_t(); // 清空报警信息
             /* 将报警信息给截取报警文件的线程 */
             /* 打印日志 */
-            SPDLOG_LOGGER_INFO(m_logger, "{} 反相报警结束,开始时间:{},结束时间:{},文件路径:{}",
+            SPDLOG_LOGGER_INFO(m_logger, "{} 反相报警结束,开始时间:{},结束时间:{}",
                 m_logBase, 
                 m_alarmPhase.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmPhase.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
-                m_alarmPhase.strAlarmFilePath);
+                m_alarmPhase.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+        }
+    }
+
+    /* 更新结果,实时更新 */
+    if(m_alarmPhase.AlarmType != EAlarmType::EAT_None)
+    {
+        /* 有报警类型,进一步判断是否有报警 */
+        if(m_alarmPhase.isAlarm)
+        {
+            /* 有报警,更新报警信息,判断一下上次的报警是否被取走 */
+            if(m_alarmLastPhase.AlarmType == EAlarmType::EAT_None || m_alarmLastPhase.isAlarm == true)
+            {
+                /* 报警结束信息被取走了,或者正在报警中,更新信息 */
+                m_alarmLastPhase = m_alarmPhase;
+            }
+        }else 
+        {
+            /* 有报警类型无报警,说明是报警结束了 */
+            m_alarmLastPhase = m_alarmPhase;
+            m_alarmPhase = AlarmInfo_t(); // 清空报警信息
         }
     }
 }

+ 6 - 6
Server/ThreadCalculate/CalculateDBThread.h

@@ -6,15 +6,13 @@
 #include "CreateDBThread.h"
 #include "SendStruct.h"
 #include "CalculateAudio.h"
-#include "AlarmInfo.h"
 #include "CompareResult.h"
 
 
 /**
  *  这个线程类进行静音、过载和反相等报警的计算,这个线程和对比项相关,需要对比项中的参数,由对比项线程创建
  *      1、计算静音、过载和反相
- *      2、将报警结果得出的报警信息发送给写数据库线程,写入到数据库中
- *      3、将报警结果发送给截取报警文件的线程,截取出报警时间段的音频文件
+ *      2、保存报警结果得出的报警信息,外部获取是实时的报警状态,通过一个中介报警信息解决了报警时间粘连的问题
  *  线程输出结果
  *      1、静音报警信息
  *      2、过载报警信息
@@ -33,10 +31,10 @@ public:
 
     /* 获取结果,这个线程计算出静音、过载、反相和音量包信息 */
     OneRoadVolume_t getVolumeInfo();
-    /* 获取最新的结果 */
+    /* 获取最新音量值计算的结果 */
     bool getlastVolumeInfo(OneRoadVolume_t& volumeInfo);
-    /* 获取报警数据 */
-    const AlarmInfo_t& getAlarm(EAlarmType alarmType);
+    /* 获取最新的结果,实时结果 */
+    AlarmInfo_t getAlarm(EAlarmType alarmType);
 
 protected:
     /* 线程功能函数 */
@@ -94,6 +92,8 @@ private:
     AlarmInfo_t m_alarmOverload;                            /* 过载报警信息 */
     AlarmInfo_t m_alarmPhase;                               /* 反相报警信息 */
 
+    /* 这里的报警信息作为返回给对比项线程的中介,防止刚结束报警,结果还未取出,又来了一个报警,
+     * 报警时间粘连的问题 */
     AlarmInfo_t m_alarmLastSilence;                         /* 上一次静音报警信息 */
     AlarmInfo_t m_alarmLastOverload;                        /* 上一次过载报警信息 */
     AlarmInfo_t m_alarmLastPhase;                           /* 上一次反相报警信息 */

+ 1 - 1
Server/ThreadCalculate/CompareDoubleThread.cpp

@@ -44,7 +44,7 @@ OneRoadVolume_t CompareDoubleThread::getVolumeInfo()
  * @return true 
  * @return false 
  */
-bool CompareDoubleThread::getlastVolumeInfo(OneRoadVolume_t& volumeInfo)
+bool CompareDoubleThread::getlastResult(OneRoadVolume_t& volumeInfo)
 {
     std::lock_guard<std::mutex> lock(m_mutexVolumeInfo);
     volumeInfo.isConsistency = m_roadResult.isConsistency;

+ 1 - 1
Server/ThreadCalculate/CompareDoubleThread.h

@@ -54,7 +54,7 @@ public:
     /* 获取计算结果 */
     OneRoadVolume_t getVolumeInfo();
     /* 获取最新的计算结果 */
-    bool getlastVolumeInfo(OneRoadVolume_t& volumeInfo);
+    bool getlastResult(OneRoadVolume_t& volumeInfo);
 
 protected:
     /* 线程功能函数 */

+ 26 - 12
Server/ThreadCalculate/CompareItemThread.cpp

@@ -155,7 +155,7 @@ void CompareItemThread::task()
         /* -------------------------------------------------------------------------------------
          * 处理数据,将报警信息给写报警数据的线程
          * ------------------------------------------------------------------------------------- */
-        processAlarmData();
+        // processAlarmData();
 
         /* -------------------------------------------------------------------------------------
          * 将音量包数据发送到MQTT中
@@ -192,9 +192,10 @@ void CompareItemThread::timerTask()
         return;
     }
     /* -------------------------------------------------------------------------------------
-     * 处理数据,将报警信息给写报警数据的线程
+     * 处理数据,将报警信息给写报警数据的线程,直接由各个计算线程直接写入
      * ------------------------------------------------------------------------------------- */
-    processAlarmData();
+    // processAlarmData();
+    
     /* -------------------------------------------------------------------------------------
      * 将音量包数据发送到MQTT中
      * ------------------------------------------------------------------------------------- */
@@ -492,7 +493,7 @@ bool CompareItemThread::updateResultData()
             SPDLOG_LOGGER_ERROR(m_logger, "{} 音量计算线程失效", m_logBase);
             continue;
         }
-        /* 获取最新的音量数据 */
+        /* 获取最新的音量数据,包括静音、过载、反向等报警信息 */
         if(!pThread->getlastVolumeInfo(m_compareResult.mapRoadVolumes[pair.first]))
         {
             continue; // 没有获取到最新数据,继续等待
@@ -516,7 +517,7 @@ bool CompareItemThread::updateResultData()
 
 
     /* -------------------------------------------------------------------------------------
-     * 获取噪音计算的结果
+     * 获取噪音计算的结果(从噪音对比线程中获取)
      * ------------------------------------------------------------------------------------- */
     for(auto& pair : m_mapNoiseDetectThreads)
     {
@@ -543,7 +544,7 @@ bool CompareItemThread::updateResultData()
         }
         /* 获取最新的一致性结果 */
         OneRoadVolume_t roadVolume;
-        if(pThread->getlastVolumeInfo(roadVolume))
+        if(pThread->getlastResult(roadVolume))
         {
             m_compareResult.mapRoadVolumes[pair.first].isConsistency = roadVolume.isConsistency;
             m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = roadVolume.isNotConsistencyWarning;
@@ -555,10 +556,18 @@ bool CompareItemThread::updateResultData()
 
 
 
-/* 处理报警数据,主要是和之前的数据尽情对比,是否是一样的 */
+/**
+    处理报警数据,现在的报警信息都是实时的,不再是报警结束后得到的数据了
+    处理逻辑:
+        1、如果是开始报警了,将报警信息发送给录制报警文件的线程,开始录音
+        2、如果是结束报警了,将报警结束信息再次通知录制报警文件的线程,结束录音
+           然后将报警信息发送给写入数据库的线程,写入到数据库中
+        3、静音、过载、反相报警信息直接从计算音量的线程中获取,一致性报警从对比项线程中获取,
+            噪音报警从噪音检测线程中获取
+ */
 void CompareItemThread::processAlarmData()
 {
-    m_listAlarm.clear();
+    m_listWriteAlarm.clear();
     /* 处理静音报警数据 */
     for(auto& pair : m_mapAlarmSilence)
     {
@@ -572,7 +581,7 @@ void CompareItemThread::processAlarmData()
             }else {
                 nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
                 nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-                m_listAlarm.push_back(nowAlarm);
+                m_listWriteAlarm.push_back(nowAlarm);
                 m_mapAlarmSilenceLast[pair.first] = nowAlarm;
             }
         }
@@ -591,7 +600,7 @@ void CompareItemThread::processAlarmData()
             }else {
                 nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
                 nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-                m_listAlarm.push_back(nowAlarm);
+                m_listWriteAlarm.push_back(nowAlarm);
                 m_mapAlarmOverloadLast[pair.first] = nowAlarm;
             }
         }
@@ -610,14 +619,19 @@ void CompareItemThread::processAlarmData()
             }else {
                 nowAlarm.CompareItemID = m_threadInfo.compareItemInfo.nID;
                 nowAlarm.strCompareItemName = m_threadInfo.compareItemInfo.strName.toStdString();
-                m_listAlarm.push_back(nowAlarm);
+                m_listWriteAlarm.push_back(nowAlarm);
                 m_mapAlarmPhaseLast[pair.first] = nowAlarm;
             }
         }
     }
+
+    /* 处理一致性报警信息 */
+
+    /* 处理噪音报警信息 */
+
     
     /* 将报警列表写入到处理报警数据的线程中 */
-    AlarmManager.addAlarmInfo(m_listAlarm);
+    AlarmManager.addAlarmInfo(m_listWriteAlarm);
 }
 
 /* 发送数据 */

+ 8 - 5
Server/ThreadCalculate/CompareItemThread.h

@@ -8,7 +8,6 @@
 
 #include "BaseCalculateThread.h"
 #include "CompareResult.h"
-#include "AlarmInfo.h"
 #include "FromMQTT.h"
 // #include "mqtt_client_cpp.hpp"
 
@@ -22,8 +21,11 @@ class CompareDoubleThread;
     对比项功能线程
         功能:
             1、对比两个录音通道的数据,通道1是主通道,和其他通道挨个对比
-            2、这里处理各个通道的报警信息,写入数据库
-            3、从这里开启各个比对线程,获取比对结果信息,并组合
+            2、从这里开启各个比对线程,获取比对结果信息,获取噪音检测结果,获取计算出的音量包信息,
+               组合成一个对比项的结果,发送到MQTT中
+            3、静音、过载、反相的报警信息从计算音量的线程中计算得出,并直接写入数据库,不再经过这里
+               一致性报警信息从两两对比线程中计算得出,直接写入数据库
+               噪音报警信息从噪音检测线程中计算得出,直接写入数据库
             4、这里创建的线程包含:两两对比线程、音量检测线程,这两个都和对比项相关联
             5、噪音检测线程从线程管理器中获取的,这里不负责创建和销毁
         其他说明:
@@ -103,7 +105,8 @@ private:
 
     /* 计算音量信息的线程指针,第一个是主通道线程,int是对比项中的通道号 */
     std::map<int, CalculateDBThread*> m_mapCalculateDBThreads;
-    std::map<int, bool> m_mapCDBUpdated;             /* 音量包更新标志位 */
+    /* 音量包更新标志位 */
+    std::map<int, bool> m_mapCDBUpdated;
     /* 计算噪音的线程指针 */
     std::map<int, NoiseDetectThread*> m_mapNoiseDetectThreads;
     /* 对比项信息线程,这个线程在这里创建,不会和其他对比项复用,int是第二路对比通道的编号 */
@@ -123,7 +126,7 @@ private:
     std::map<int, AlarmInfo_t> m_mapAlarmPhaseLast;         /* 上一次反相报警信息 */
 
     /* 要写入到数据库的报警信息 */
-    std::list<AlarmInfo_t> m_listAlarm;;
+    std::list<AlarmInfo_t> m_listWriteAlarm;;
 };
 
 

+ 6 - 0
Server/ThreadManager/ThreadAlarmManager.cpp

@@ -85,8 +85,14 @@ void ThreadAlarmManager::task()
                 continue; // 如果没有报警信息,继续循环
             }
 
+            /* 处理报警信息,拼接报警文件字符串,拼接出报警文件 */
 
 
+            /* 写入数据库 */
+            if(!m_fromWebAPI.insertAlarmInfo(m_listAlarm))
+            {
+                SPDLOG_LOGGER_ERROR(m_logger, "写入报警信息失败");
+            }
         }
 
     }

+ 0 - 1
Server/ThreadManager/ThreadAlarmManager.h

@@ -14,7 +14,6 @@
  */
 
  #include "FromWebAPI.h"
-#include "AlarmInfo.h"
 #include "GlobalVariable.h"
 #include "spdlog/spdlog.h"
 

+ 19 - 0
Server/ThreadRecord/CreateLongFileThread.cpp

@@ -67,6 +67,25 @@ bool CreateLongFileThread::setData(const AudioSrcData& srcData)
     return true;
 }
 
+
+/* 开启录制 */
+bool CreateLongFileThread::startRecordAlarmFile(const AlarmInfo_t& alarmInfo)
+{
+
+    return true;
+}
+
+/* 停止录制 */
+bool CreateLongFileThread::stopRecordAlarmFile(AlarmInfo_t& alarmInfo)
+{
+
+    return true;
+}
+
+
+
+
+
 /**
  * @brief   生成长文件的线程函数,文件生成逻辑如下
  *          1、这里有一个缓冲区,存储音频数据,缓冲区大小是2分钟的数据

+ 25 - 4
Server/ThreadRecord/CreateLongFileThread.h

@@ -3,17 +3,28 @@
 
 #include "BaseRecordThread.h"
 #include "AudioData.h"
+#include "GlobalVariable.h"
 
 #include <mutex>
 #include <QFile>
 #include <QDir>
+#include <qt5/QtCore/qchar.h>
 
 
 /**
- * @brief 这个线程类记录一个长的录音文件,1小时一个文件
- *        1、如果是刚开始录音,到下一个整点记录一个文件,后续都是满1小时一个文件
- *        2、数据先放到缓冲区中,满1分钟写一次文件
- * 
+    这个线程类记录一个长的录音文件,1小时一个文件
+    功能1:记录一个长的录音文件,1小时一个文件
+        1、如果是刚开始录音,到下一个整点记录一个文件,后续都是满1小时一个文件
+        2、数据先放到缓冲区中,满1分钟写一次文件
+    
+    功能2:
+        1、录制报警文件
+        2、由其他线程传来报警参数,开启录制,报警结束后,结束录制
+        3、由于静音、过载、反相、一致性报警、噪音报警条件是和对比项相关联的,因此这里可能回同时存在多个录音,
+           根据对比项ID和对比项通道以及报警类型来区分
+        4、报警文件的命名规则:Alarm_CompareItemID_RoadNum_AlarmType_yyyyMMdd_hhmmss-yyyyMMdd_hhmmss.wav
+           例如:Alarm_1_1_Silent_20250101_120000-20250101_120100.wav
+
  */
 class CreateLongFileThread : public BaseRecordThread
 {
@@ -25,6 +36,11 @@ public:
     /* 设置数据 */
     bool setData(const AudioSrcData& srcData) override;
 
+    /* 开启录制 */
+    bool startRecordAlarmFile(const AlarmInfo_t& alarmInfo);
+    /* 停止录制,alarmInfo既是传入参数,也是传出参数,传出文件路径和开始位置 */
+    bool stopRecordAlarmFile(AlarmInfo_t& alarmInfo);
+
 private:
     /* 执行任务函数 */
     void task() override;
@@ -62,6 +78,11 @@ private:
     int64_t m_writtenSize = 0;      /* 已经写入的数据大小 */
     QDateTime m_writtenStartTime;   /* 已经写入数据的开始时间点 */
     QDateTime m_writtenNowTime;     /* 已经写入数据的最后时间点 */
+
+
+    /*===============================================================================*/
+    /* 报警文件相关 */
+    std::map<AlarmInfo_t, bool> m_mapAlarmFileName; /* 报警文件名,key是报警信息,value是文件名 */
 };
 
 

+ 40 - 0
common/GlobalInfo/GlobalVariable.cpp

@@ -262,3 +262,43 @@ CalculateThreadInfo_t& CalculateThreadInfo_t::operator=(const CalculateThreadInf
 }
 
 
+
+/* =========================================================================================
+ * 报警信息结构体
+ * =========================================================================================*/
+
+
+AlarmInfo_t& AlarmInfo_t::operator=(const AlarmInfo_t& obj)
+{
+    if (this == &obj)
+    {
+        return *this; // 防止自赋值
+    }
+    isAlarm = obj.isAlarm;
+    CompareItemID = obj.CompareItemID;
+    strCompareItemName = obj.strCompareItemName;
+    RoadInfo = obj.RoadInfo;
+    RoadType = obj.RoadType;
+    AlarmType = obj.AlarmType;
+    StartTime = obj.StartTime;
+    EndTime = obj.EndTime;
+    strAlarmFilePath = obj.strAlarmFilePath;
+    AlarmStartPos = obj.AlarmStartPos;
+    AlarmFileStartTime = obj.AlarmFileStartTime;
+    return *this;
+}
+
+
+/* 比较是否相等,主要是比较是否报警、通道ID,报警类型,报警时间 */
+bool AlarmInfo_t::operator==(const AlarmInfo_t& other) const
+{
+    return (isAlarm == other.isAlarm) &&
+           (RoadInfo == other.RoadInfo) &&
+           (AlarmType == other.AlarmType) &&
+           (StartTime == other.StartTime) &&
+           (EndTime == other.EndTime);
+}
+
+
+
+

+ 69 - 1
common/GlobalInfo/GlobalVariable.h

@@ -32,6 +32,34 @@ Q_DECLARE_METATYPE(eWeekType)
 extern const QMap<eWeekType, QString> MapWeekTypeToString;
 
 
+/**
+ * @brief 录音通道类型
+ * 
+ */
+enum class ERoadType
+{
+    RoadType_Main = 0,      /* 主输出 */
+    RoadType_SpaceReceive,  /* 空间接收 */
+    RoadType_SpaceSend,     /* 空间发送 */
+};
+
+/**
+ * @brief 报警类型
+ * 
+ */
+enum class EAlarmType
+{
+    EAT_None = 0,           /* 无报警 */
+    EAT_Silent,             /* 静音报警 */
+    EAT_Overload,           /* 过载报警 */
+    EAT_Reversed,           /* 反相报警 */
+    EAR_Consistency,        /* 一致性报警 */
+    EAT_Noise,              /* 噪音报警 */
+    EAT_Unknown,            /* 未知报警 */
+};
+
+
+
 /**
  * @brief 一条计划
  * 
@@ -269,7 +297,9 @@ struct RecordThreadInfo_t
 };
 
 
-
+/* =========================================================================================
+ * 报警信息结构体
+ * =========================================================================================*/
 
 class BaseCalculateThread;
 /**
@@ -294,5 +324,43 @@ struct CalculateThreadInfo_t
 
 
 
+/**
+ * @brief 报警结构体
+ * 
+ */
+struct AlarmInfo_t
+{
+    bool isAlarm = false;           /* 是否报警 */
+    int CompareItemID = 0;          /* 对比项ID */
+    std::string strCompareItemName; /* 对比项名称 */
+
+    CompareItemRoadInfo_t RoadInfo; /* 录音通道信息 */
+    ERoadType RoadType;             /* 录音通道类型 */
+
+    EAlarmType AlarmType = EAlarmType::EAT_None; /* 报警类型 */
+
+    QDateTime StartTime;            /* 报警开始时间 */
+    QDateTime EndTime;              /* 报警结束时间 */
+
+    // std::string strAlarmStartTime;  /* 报警发生时间 */
+    // std::string strAlarmEndTime;    /* 报警结束时间 */
+    // std::string strAlarmExistTime;  /* 报警持续时间 */
+
+    std::string strAlarmFilePath;   /* 报警文件路径 */
+    int AlarmStartPos = 0;          /* 报警开始位置 */
+    QDateTime AlarmFileStartTime;   /* 录音文件开始时间 */
+
+    AlarmInfo_t() = default;
+    AlarmInfo_t(const AlarmInfo_t& obj) { *this = obj; }
+    AlarmInfo_t& operator=(const AlarmInfo_t& obj);
+
+    /* 比较是否相等,主要是比较是否报警、通道ID,报警类型,报警时间 */
+    bool operator==(const AlarmInfo_t& other) const;
+
+};
+
+
+
+
 
 #endif // __GLOBAL_VARIABLE_H__

+ 46 - 0
common/Network/FromWebAPI.cpp

@@ -718,3 +718,49 @@ bool FromWebAPI::deleteDetectPeriodConfig(const QList<int>& listIDs)
 }
 
 
+/* 写入报警信息 */
+bool FromWebAPI::insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm)
+{
+    try
+    {
+        int Key = 1;
+        nJson jsonArray = nJson::array();
+        for(auto it : listAlarm)
+        {
+            nJson json1;
+            json1["opName"] = "ACAS_InsertAlarmInfo";
+            json1["Key"] = Key++;
+            nJson jsonAlarm;
+            jsonAlarm["itemID"] = it.CompareItemID;
+            jsonAlarm["itemName"] = it.strCompareItemName;
+            jsonAlarm["alarmType"] = static_cast<int>(it.AlarmType);
+            jsonAlarm["soundCardNum"] = it.RoadInfo.nCompareRoadNum;
+            jsonAlarm["soundCardName"] = it.RoadInfo.strCompareRoadName.toStdString();
+            jsonAlarm["soundCardRoadNum"] = it.RoadInfo.scRoadInfo.roadInfo.nRoadNum;
+            jsonAlarm["compareRoadNum"] = it.RoadInfo.nCompareRoadNum;
+            jsonAlarm["compareRoadName"] = it.RoadInfo.strCompareRoadName.toStdString();
+            jsonAlarm["compareRoadType"] = static_cast<int>(it.RoadType);
+            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["fileAlarmStartPos"] = it.AlarmStartPos;
+
+            json1["paramList"] = jsonAlarm;
+            
+            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 - 1
common/Network/FromWebAPI.h

@@ -4,9 +4,12 @@
 #include "spdlog/spdlog.h"
 #include "WebAPIBase.h"
 #include "GlobalVariable.h"
+
+
 #include <string>
 
 
+
 class FromWebAPI : public WebAPIBase
 {
 
@@ -46,7 +49,10 @@ public:
     bool insertDetectPeriodConfig(const QMap<int, DetectPeriodConfig_t>& mapDetectConfig);
     /* 删除某些对比项的检测时段 */
     bool deleteDetectPeriodConfig(const QList<int>& listIDs);
-    
+
+    /* ================================================================================== */
+    /* 写入报警信息 */
+    bool insertAlarmInfo(const std::list<AlarmInfo_t>& listAlarm);
 
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;