浏览代码

V0.5.3
1、应用了一些设置动态库的参数
2、修改了一致性比对的检测方法,直接调用动态库检测,其他都不需要了

Apple 5 小时之前
父节点
当前提交
720565a634

+ 18 - 0
Server/ACAServer.cpp

@@ -9,6 +9,8 @@
 #include "ThreadManager.h"
 #include "ThreadAlarmManager.h"
 #include "RtpServer.h"
+#include "LHLogInit.h"
+
 
 #include <QFile>
 #include <QString>
@@ -117,6 +119,18 @@ bool ACAServer::initGlobalInfo()
     /* 初始化全局数据信息 */
     GInfo.initGlobalInfo();
 
+    /*------------------------------------------------------------------------------------*/
+    /* 应用一些配置选项 */
+#if defined(C_RELEASE)
+    bool isDebug = SysConfig.getBaseConfigSrc().isEnableDebugLog;
+    if(isDebug)
+    {
+        changeLogLevel(ELogLevel::Log_Debug);
+    } else {
+        changeLogLevel(ELogLevel::Log_Info);
+    }
+#endif
+
     /*------------------------------------------------------------------------------------*/
     /* 发送服务信息到MQTT中,设置为保留信息 */
     sendServerInfoToMQTT();
@@ -208,6 +222,10 @@ bool ACAServer::sendServerInfoToMQTT()
     nJson serverInfo;
     serverInfo["server_ip"] = SysConfig.getBaseConfigSrc().strServerIP.toStdString();
     serverInfo["server_rtp_port"] = SysConfig.getDatabaseConfig().nListenPort;
+    /* 录音相关的参数 */
+    serverInfo["sample_rate"] = GInfo.sampleRate();
+    serverInfo["channel_count"] = GInfo.numChannels();
+    serverInfo["bit_depth"] = GInfo.bitsPerSample();
 
     QByteArray payload = QString::fromStdString(serverInfo.dump()).toUtf8();
 

+ 0 - 35
Server/DataStruct/ChannelParam.cpp

@@ -75,40 +75,5 @@ int StVolumeParam::GetPhaseNum() const
 
 
 
-/* --------------------------------------------------------------------------------
- * 一致性检测参数 StConsistencyParam
- * -------------------------------------------------------------------------------- */
-StConsistencyParam::StConsistencyParam()
-{
-    Init();
-}
-
-StConsistencyParam::StConsistencyParam(const StConsistencyParam& obj)
-{
-    *this = obj;
-}
-
-StConsistencyParam& StConsistencyParam::operator=(const StConsistencyParam& obj)
-{
-    m_bConsistencySwitch = obj.m_bConsistencySwitch;
-
-    m_iConsistencyThreshold = obj.m_iConsistencyThreshold;
-    m_iConsistencyThresholdNum = obj.m_iConsistencyThresholdNum;
-    m_iConsistencyThresholdNot = obj.m_iConsistencyThresholdNot;
-    m_iConsistencyThresholdNotNum = obj.m_iConsistencyThresholdNotNum;
-	m_nConsistencyThresholdWarningNum = obj.m_nConsistencyThresholdWarningNum;
-    return *this;
-}
-
-void StConsistencyParam::Init()
-{
-    m_bConsistencySwitch = false;
-
-    m_iConsistencyThreshold = 0;
-    m_iConsistencyThresholdNum = 0;
-    m_iConsistencyThresholdNot = 0;
-    m_iConsistencyThresholdNotNum = 0;
-	m_nConsistencyThresholdWarningNum = 0;
-}
 
 

+ 0 - 49
Server/DataStruct/ChannelParam.h

@@ -125,55 +125,6 @@ private:
 };
 
 
-/**
- * @brief 一致性检测参数
- * 
- */
-struct StConsistencyParam
-{
-    StConsistencyParam();
-    StConsistencyParam(const StConsistencyParam& obj);
-    StConsistencyParam& operator=(const StConsistencyParam& obj);
-
-    void Init();
-
-    // ********* 一致性 ********* [[
-    void SetConsistencySwitch(bool b) { m_bConsistencySwitch = b; }
-    bool GetConsistencySwitch() { return m_bConsistencySwitch; }
-
-    int GetConsistencyThreshold() const { return m_iConsistencyThreshold; }
-    void SetConsistencyThreshold(int ival) { m_iConsistencyThreshold = ival; }
-
-    int GetConsistencyThresholdNum() const { return m_iConsistencyThresholdNum; }
-    void SetConsistencyThresholdNum(int ival) { m_iConsistencyThresholdNum = ival; }
-
-    int GetConsistencyThresholdNot() const { return m_iConsistencyThresholdNot; }
-    void SetConsistencyThresholdNot(int ival) { m_iConsistencyThresholdNot = ival; }
-
-    int GetConsistencyThresholdNotNum() const { return m_iConsistencyThresholdNotNum; }    
-	// 不一致的判定更严谨,全部为不一致时,才判定为不一致
-    int GetConsistencyThresholdNotNumEx() const { return m_iConsistencyThresholdNotNum * 2; }
-
-    void SetConsistencyThresholdNotNum(int ival) { m_iConsistencyThresholdNotNum = ival; }
-
-	int GetConsistencyThresholdWarningNum() const { return m_nConsistencyThresholdWarningNum; }
-	void SetConsistencyThresholdWarningNum(int ival) { m_nConsistencyThresholdWarningNum = ival; }
-
-private:
-    // 一致性监测开关
-    bool m_bConsistencySwitch;
-    // 一致性阀值
-    // 持续时间内,如果有m_iConsistencyThresholdNum相似度个比阀值大,就表示一致性
-    int	m_iConsistencyThreshold;
-    int	m_iConsistencyThresholdNum;
-	// 一致性阀值预警次数: 多少个不一致时,开启不一致预警
-	int m_nConsistencyThresholdWarningNum;
-    // 不一致性阀值
-    // 持续时间内,如果有m_iConsistencyThresholdNotNum相似度个比阀值小,就表示不一致性
-    int	m_iConsistencyThresholdNot;
-    int	m_iConsistencyThresholdNotNum;
-};
-
 
 
 

+ 318 - 138
Server/DataStruct/ConsistencyResult.cpp

@@ -2,17 +2,61 @@
 #include "GlobalInfo.h"
 #include "spdlog/spdlog.h"
 
-// ************************** StConsistencyResult ************************** 【【
-StConsistencyResult::StConsistencyResult()	
+
+
+
+
+/* --------------------------------------------------------------------------------
+ * 一致性检测参数 StConsistencyParam
+ * -------------------------------------------------------------------------------- */
+StConsistencyParam::StConsistencyParam()
 {
-	Init();
+    Init();
 }
-StConsistencyResult::StConsistencyResult(StConsistencyParam &param)
+
+StConsistencyParam::StConsistencyParam(const StConsistencyParam& obj)
 {
-	Init();
-    m_stConsistencyParam = param;
+    *this = obj;
+}
+
+StConsistencyParam& StConsistencyParam::operator=(const StConsistencyParam& obj)
+{
+    m_bConsistencySwitch = obj.m_bConsistencySwitch;
+
+    m_iConsistencyThreshold = obj.m_iConsistencyThreshold;
+    m_iConsistencyThresholdNum = obj.m_iConsistencyThresholdNum;
+    m_iConsistencyThresholdNot = obj.m_iConsistencyThresholdNot;
+    m_iConsistencyThresholdNotNum = obj.m_iConsistencyThresholdNotNum;
+	m_nConsistencyThresholdWarningNum = obj.m_nConsistencyThresholdWarningNum;
+    return *this;
 }
 
+void StConsistencyParam::Init()
+{
+    m_bConsistencySwitch = false;
+
+    m_iConsistencyThreshold = 0;
+    m_iConsistencyThresholdNum = 0;
+    m_iConsistencyThresholdNot = 0;
+    m_iConsistencyThresholdNotNum = 0;
+	m_nConsistencyThresholdWarningNum = 0;
+}
+
+
+
+/* --------------------------------------------------------------------------------
+ * 一致性检测参数 StConsistencyResult
+ * -------------------------------------------------------------------------------- */
+StConsistencyResult::StConsistencyResult()	
+{
+	// Init();
+}
+// StConsistencyResult::StConsistencyResult(StConsistencyParam &param)
+// {
+// 	// Init();
+//     // m_stConsistencyParam = param;
+// }
+
 StConsistencyResult::~StConsistencyResult()
 {
 
@@ -25,18 +69,18 @@ StConsistencyResult::StConsistencyResult(const StConsistencyResult& obj)
 
 StConsistencyResult& StConsistencyResult::operator=(const StConsistencyResult &obj)
 {
-	m_bIsNoiseOfCur = obj.m_bIsNoiseOfCur;
-	m_stNoiseConsistencyParam = obj.m_stNoiseConsistencyParam;
+	// m_bIsNoiseOfCur = obj.m_bIsNoiseOfCur;
+	// m_stNoiseConsistencyParam = obj.m_stNoiseConsistencyParam;
 
-	// m_nRetPythonCompareFile = obj.m_nRetPythonCompareFile;
-    m_stConsistencyParam = obj.m_stConsistencyParam;
+	// // m_nRetPythonCompareFile = obj.m_nRetPythonCompareFile;
+    // m_stConsistencyParam = obj.m_stConsistencyParam;
 
-	iCurPos = obj.iCurPos;
-	for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
-	{
-		aryOfDelN[i] = obj.aryOfDelN[i];
-		aryOfSimilarity[i] = obj.aryOfSimilarity[i];
-	}
+	// iCurPos = obj.iCurPos;
+	// for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
+	// {
+	// 	aryOfDelN[i] = obj.aryOfDelN[i];
+	// 	aryOfSimilarity[i] = obj.aryOfSimilarity[i];
+	// }
 
 	for(int i = 0; i < 10; ++i)
 	{
@@ -45,38 +89,38 @@ StConsistencyResult& StConsistencyResult::operator=(const StConsistencyResult &o
 	return *this;
 }
 
-void StConsistencyResult::Init()
-{
-	m_bIsNoiseOfCur = false;
-	InitAICompareFile();
-	// m_nRetPythonCompareFile = ERCF_3_CompareFile_Unkonw;
-	iCurPos = 0;
-	for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
-	{
-		aryOfDelN[i] = 0;
-		aryOfSimilarity[i] = 0.0;
-	}
-}
+// void StConsistencyResult::Init()
+// {
+// 	m_bIsNoiseOfCur = false;
+// 	InitAICompareFile();
+// 	// m_nRetPythonCompareFile = ERCF_3_CompareFile_Unkonw;
+// 	iCurPos = 0;
+// 	for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
+// 	{
+// 		aryOfDelN[i] = 0;
+// 		aryOfSimilarity[i] = 0.0;
+// 	}
+// }
 
 void StConsistencyResult::InitAICompareFile()
 {
-	m_tLastAITime = QDateTime::currentDateTime();
-	m_nLastRetAICompareFile = ERCF_3_CompareFile_Unkonw;
+	// m_tLastAITime = QDateTime::currentDateTime();
+	// m_nLastRetAICompareFile = ERCF_3_CompareFile_Unkonw;
 	for(int i = 0; i < 10; ++i)
 	{
 		aryOfAICompareFile[i] = -1.0;
 	}
 }
 
-int StConsistencyResult::GetLastRetAICompareFile()
-{
-	auto span = m_tLastAITime.secsTo(QDateTime::currentDateTime());
-	if (span < GInfo.compareTimeSpan())
-	{
-		return m_nLastRetAICompareFile;
-	}
-	return ERCF_3_CompareFile_Unkonw;
-}
+// int StConsistencyResult::GetLastRetAICompareFile()
+// {
+// 	// auto span = m_tLastAITime.secsTo(QDateTime::currentDateTime());
+// 	// if (span < GInfo.compareTimeSpan())
+// 	// {
+// 	// 	return m_nLastRetAICompareFile;
+// 	// }
+// 	return ERCF_3_CompareFile_Unkonw;
+// }
 
 int StConsistencyResult::AddRetAICompareFile(float fVal)
 {
@@ -86,15 +130,15 @@ int StConsistencyResult::AddRetAICompareFile(float fVal)
 	}
 	aryOfAICompareFile[0] = fVal;
 
-	m_tLastAITime = QDateTime::currentDateTime();
-	if (fVal > 0.99)
-	{
-		m_nLastRetAICompareFile = ERCF_1_CompareFile_TRUE;
-	}
-	else
-	{
-		m_nLastRetAICompareFile = ERCF_0_CompareFile_FALSE;
-	}
+	// m_tLastAITime = QDateTime::currentDateTime();
+	// if (fVal > 0.99)
+	// {
+	// 	m_nLastRetAICompareFile = ERCF_1_CompareFile_TRUE;
+	// }
+	// else
+	// {
+	// 	m_nLastRetAICompareFile = ERCF_0_CompareFile_FALSE;
+	// }
 	return 10;
 }
 
@@ -108,7 +152,7 @@ bool StConsistencyResult::IsAIConsistency(int nThresholdNum, float dThreshold, s
 	{
 		if (aryOfAICompareFile[i] < -0.9)
 		{
-			strAIValue += ",数据未初始化直接返回-1";
+			strAIValue += "数据未初始化直接返回 -1";
 			return -1;
 		}
 		if (aryOfAICompareFile[i] < dThreshold)
@@ -116,8 +160,7 @@ bool StConsistencyResult::IsAIConsistency(int nThresholdNum, float dThreshold, s
 			bConsistency = false;
 			strAIValue = fmt::format("{},{:.3f}<{:.3f}不能判断为一致", strAIValue, aryOfAICompareFile[i], dThreshold);
 			break;
-		}
-		else
+		} else
 		{
 			strAIValue = fmt::format("{},{:.3f}", strAIValue, aryOfAICompareFile[i]);
 		}
@@ -139,7 +182,7 @@ bool StConsistencyResult::IsAINotConsistency(int nThresholdNum, float dThreshold
 	{
 		if (aryOfAICompareFile[i] < -0.9)
 		{
-			strAIValue = fmt::format("{}, 数据未初始化直接返回-1", strAIValue);
+			strAIValue = fmt::format("数据未初始化直接返回 -1");
 			return -1;
 		}
 
@@ -148,8 +191,7 @@ bool StConsistencyResult::IsAINotConsistency(int nThresholdNum, float dThreshold
 			bNotConsistency = false;
 			strAIValue = fmt::format("{},{:.3f} > {:.3f}不能判断为不一致", strAIValue, aryOfAICompareFile[i], dThreshold);
 			break;
-		}
-		else
+		} else
 		{
 			strAIValue = fmt::format("{}, {:.3f}", strAIValue, aryOfAICompareFile[i]);
 		}
@@ -161,119 +203,257 @@ bool StConsistencyResult::IsAINotConsistency(int nThresholdNum, float dThreshold
 	return bNotConsistency;
 }
 
-std::string StConsistencyResult::OutPutConsistencyInfo(const bool bConsistencyInfo)
-{
-    std::string strInfo;
-    for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
-    {
+// std::string StConsistencyResult::OutPutConsistencyInfo(const bool bConsistencyInfo)
+// {
+//     std::string strInfo;
+//     for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
+//     {
         
-        std::string str = fmt::format("{:.2f}(相似度) {}(采样率偏移量)", aryOfSimilarity[i], aryOfDelN[i]);
-        strInfo += str;
-    }
-
-	StConsistencyParam param = m_stConsistencyParam;
-	if (m_bIsNoiseOfCur)
-	{
-		param = m_stNoiseConsistencyParam;
-	}
-
-	std::string strMsg = fmt::format("{}: {}-{} {}-{}", strInfo,
-		param.GetConsistencyThreshold(),
-		param.GetConsistencyThresholdNum(),
-		param.GetConsistencyThresholdNot(), 
-		param.GetConsistencyThresholdNotNum());
+//         std::string str = fmt::format("{:.2f}(相似度) {}(采样率偏移量)", aryOfSimilarity[i], aryOfDelN[i]);
+//         strInfo += str;
+//     }
+
+// 	StConsistencyParam param = m_stConsistencyParam;
+// 	if (m_bIsNoiseOfCur)
+// 	{
+// 		param = m_stNoiseConsistencyParam;
+// 	}
+
+// 	std::string strMsg = fmt::format("{}: {}-{} {}-{}", strInfo,
+// 		param.GetConsistencyThreshold(),
+// 		param.GetConsistencyThresholdNum(),
+// 		param.GetConsistencyThresholdNot(), 
+// 		param.GetConsistencyThresholdNotNum());
 	
-        SPDLOG_DEBUG("一致性检测结果: {}", strMsg);
-	return strMsg;
+//         SPDLOG_DEBUG("一致性检测结果: {}", strMsg);
+// 	return strMsg;
+// }
+
+// bool StConsistencyResult::IsConsistency() const
+// {
+// 	StConsistencyParam param = m_stConsistencyParam;
+// 	if (m_bIsNoiseOfCur)
+// 	{
+// 		param = m_stNoiseConsistencyParam;
+// 	}
+
+//     if(param.GetConsistencyThreshold() <= GetMaxResult())
+//     {
+//         return true;
+//     }
+
+//     return false;
+// }
+
+// bool StConsistencyResult::IsNotConsistency() const
+// {
+// 	StConsistencyParam param = m_stConsistencyParam;
+// 	if (m_bIsNoiseOfCur)
+// 	{
+// 		param = m_stNoiseConsistencyParam;
+// 	}
+
+//     if(param.GetConsistencyThresholdNot() > GetMaxResult())
+//     {
+//         return true;
+//     }
+
+//     return false;
+// }
+
+// int StConsistencyResult::GetMaxResult() const
+// {
+//     int iRet = 0;
+//     for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
+//     {
+//         int iTmp = aryOfSimilarity[i];
+//         if(iRet <= iTmp)
+//         {
+//             iRet = iTmp;
+//         }
+//     }
+//     return iRet;
+// }
+
+// int StConsistencyResult::AddResult(const float f, const int iDelN)
+// {
+// 	if(iCurPos < RESULT_NUM_OF_ONETIME_COMPARE)
+//     {
+//         return -1;
+//     }
+
+// 	aryOfDelN[iCurPos] = iDelN;
+// 	aryOfSimilarity[iCurPos] = f;
+
+// 	return ++iCurPos;
+// }
+
+// int StConsistencyResult::GetConsistencyThresholdNum() const
+// {
+// 	int iNum = m_stConsistencyParam.GetConsistencyThresholdNum();
+// 	if (iNum < m_stNoiseConsistencyParam.GetConsistencyThresholdNum())
+// 	{
+// 		iNum = m_stNoiseConsistencyParam.GetConsistencyThresholdNum();
+// 	}
+
+// 	return iNum;
+// }
+
+// int StConsistencyResult::GetConsistencyThresholdNotNum() const
+// {
+// 	int iNotNum = m_stConsistencyParam.GetConsistencyThresholdNotNum();
+// 	if (iNotNum < m_stNoiseConsistencyParam.GetConsistencyThresholdNotNum())
+// 	{
+// 		iNotNum = m_stNoiseConsistencyParam.GetConsistencyThresholdNotNum();
+// 	}
+// 	return iNotNum;
+// }
+
+// int StConsistencyResult::GetConsistencyThresholdWarningNum() const
+// {
+// 	int iNum = m_stConsistencyParam.GetConsistencyThresholdWarningNum();
+// 	if (iNum < m_stNoiseConsistencyParam.GetConsistencyThresholdWarningNum())
+// 	{
+// 		iNum = m_stNoiseConsistencyParam.GetConsistencyThresholdWarningNum();
+// 	}
+// 	return iNum;
+// }
+// ************************** stConsistency ************************** 】】
+
+
+/* --------------------------------------------------------------------------------
+ * 一致性检测结果 ConsistencyResult_t
+ * -------------------------------------------------------------------------------- */
+
+ConsistencyResult_t::ConsistencyResult_t()
+{
+	Init();
 }
 
-bool StConsistencyResult::IsConsistency() const
+ConsistencyResult_t::ConsistencyResult_t(const ConsistencyResult_t& obj)
 {
-	StConsistencyParam param = m_stConsistencyParam;
-	if (m_bIsNoiseOfCur)
-	{
-		param = m_stNoiseConsistencyParam;
-	}
 
-    if(param.GetConsistencyThreshold() <= GetMaxResult())
-    {
-        return true;
-    }
-
-    return false;
 }
 
-bool StConsistencyResult::IsNotConsistency() const
+ConsistencyResult_t& ConsistencyResult_t::operator=(const ConsistencyResult_t& obj)
 {
-	StConsistencyParam param = m_stConsistencyParam;
-	if (m_bIsNoiseOfCur)
+	m_fInitThreshold = obj.m_fInitThreshold;
+	m_nCurPos = obj.m_nCurPos;
+	for(int i = 0; i < m_numArryCount; ++i)
 	{
-		param = m_stNoiseConsistencyParam;
+		m_arryResult[i] = obj.m_arryResult[i];
 	}
 
-    if(param.GetConsistencyThresholdNot() > GetMaxResult())
-    {
-        return true;
-    }
-
-    return false;
+	return *this;
 }
 
-int StConsistencyResult::GetMaxResult() const
+void ConsistencyResult_t::Init()
 {
-    int iRet = 0;
-    for(int i = 0; i < RESULT_NUM_OF_ONETIME_COMPARE; ++i)
-    {
-        int iTmp = aryOfSimilarity[i];
-        if(iRet <= iTmp)
-        {
-            iRet = iTmp;
-        }
-    }
-    return iRet;
+	m_fInitThreshold = 0.9;	/* 初始化阈值 */
+	m_nCurPos = 0;
+	for(int i = 0; i < m_numArryCount; ++i)
+	{
+		m_arryResult[i] = -1.0;
+	}
 }
-
-int StConsistencyResult::AddResult(const float f, const int iDelN)
+/* 添加结果 */
+bool ConsistencyResult_t::AddResult(float fVal)
 {
-	if(iCurPos < RESULT_NUM_OF_ONETIME_COMPARE)
-    {
-        return -1;
-    }
-
-	aryOfDelN[iCurPos] = iDelN;
-	aryOfSimilarity[iCurPos] = f;
+	for(int i = 8; i >= 0; --i)
+	{
+		m_arryResult[i + 1] = m_arryResult[i];
+	}
+	m_arryResult[0] = fVal;
 
-	return ++iCurPos;
+	return true;
 }
 
-int StConsistencyResult::GetConsistencyThresholdNum() const
+/* 
+	计算一致性
+	计算要求:需要 nThresholdNum 全部大于一致性阈值 fThreshold 方可判断为一致,否则返回无法判断为一致
+ */
+eConsistencyState ConsistencyResult_t::computeConsistency(int nThresholdNum, float fThreshold, std::string& strInfo)
 {
-	int iNum = m_stConsistencyParam.GetConsistencyThresholdNum();
-	if (iNum < m_stNoiseConsistencyParam.GetConsistencyThresholdNum())
+	strInfo.clear();
+	bool bConsistency = true;
+	if (nThresholdNum < 0)
 	{
-		iNum = m_stNoiseConsistencyParam.GetConsistencyThresholdNum();
+		nThresholdNum = 1;
+		strInfo += "一致性最小检测数目为1 ";
+	}
+	if (nThresholdNum > 10)
+	{
+		nThresholdNum = 10;
+		strInfo += "一致性最大检测数目为10 ";
 	}
 
-	return iNum;
+	for(int i = 0; i < nThresholdNum; ++i)
+	{
+		if (m_arryResult[i] < -0.9)
+		{
+			strInfo += "数据未初始化";
+			return eConsistencyState::eCS_Unknown;
+		}
+		if (m_arryResult[i] < fThreshold)
+		{
+			bConsistency = false;
+			strInfo = fmt::format("{},{:.3f}<{:.3f}不能判断为一致", strInfo, m_arryResult[i], fThreshold);
+			break;
+		} else
+		{
+			strInfo = fmt::format("{},{:.3f}", strInfo, m_arryResult[i]);
+		}
+	}
+	if (bConsistency)
+	{
+		return eConsistencyState::eCS_Consistency;
+	}else {
+		return eConsistencyState::eCS_Unknown;
+	}
 }
 
-int StConsistencyResult::GetConsistencyThresholdNotNum() const
+/* 计算不一致性 */
+eConsistencyState ConsistencyResult_t::computeNotConsistency(int nThresholdNum, float fThreshold, std::string& strInfo)
 {
-	int iNotNum = m_stConsistencyParam.GetConsistencyThresholdNotNum();
-	if (iNotNum < m_stNoiseConsistencyParam.GetConsistencyThresholdNotNum())
+	strInfo.clear();
+	bool bNotConsistency = true;
+	if (nThresholdNum < 0)
 	{
-		iNotNum = m_stNoiseConsistencyParam.GetConsistencyThresholdNotNum();
+		nThresholdNum = 1;
+		strInfo += "一致性最小检测数目为1 ";
+	}
+	if (nThresholdNum > 10)
+	{
+		nThresholdNum = 10;
+		strInfo += "一致性最大检测数目为10 ";
 	}
-	return iNotNum;
-}
 
-int StConsistencyResult::GetConsistencyThresholdWarningNum() const
-{
-	int iNum = m_stConsistencyParam.GetConsistencyThresholdWarningNum();
-	if (iNum < m_stNoiseConsistencyParam.GetConsistencyThresholdWarningNum())
+	for(int i = 0; i < nThresholdNum; ++i)
 	{
-		iNum = m_stNoiseConsistencyParam.GetConsistencyThresholdWarningNum();
+		if (m_arryResult[i] < -0.9)
+		{
+			strInfo = fmt::format("数据未初始化直接返回");
+			return eConsistencyState::eCS_Unknown;
+		}
+
+		if (m_arryResult[i] > fThreshold)
+		{
+			bNotConsistency = false;
+			strInfo = fmt::format("{},{:.3f} > {:.3f}不能判断为不一致", strInfo, m_arryResult[i], fThreshold);
+			break;
+		} else
+		{
+			strInfo = fmt::format("{}, {:.3f}", strInfo, m_arryResult[i]);
+		}
 	}
-	return iNum;
-}
-// ************************** stConsistency ************************** 】】
+	if (bNotConsistency)
+	{
+		strInfo = fmt::format("{}, 判断为不一致", strInfo);
+	}
+	if(bNotConsistency)
+	{
+		return eConsistencyState::eCS_NotConsistency;
+	}else {
+		return eConsistencyState::eCS_Unknown;
+	}
+}

+ 119 - 25
Server/DataStruct/ConsistencyResult.h

@@ -17,34 +17,99 @@ enum ERetPythonCompareFile
 	ERCF_3_CompareFile_Unkonw = 3,	// 对比返回未知,判断不出一致性
 };
 
-// 保存1次一致性比较的结果,大概1秒钟的数据
+
+/* 新版本的一致性状态 */
+enum class eConsistencyState
+{
+	eCS_Unknown = 0,       		// 未知状态
+	eCS_Consistency = 1,    	// 一致性
+	eCS_NotConsistency = 2, 	// 不一致性
+	eCS_ConsistencyWarning, 	// 一致性预警
+};
+
+
+/**
+ * @brief 一致性检测参数
+ * 
+ */
+struct StConsistencyParam
+{
+    StConsistencyParam();
+    StConsistencyParam(const StConsistencyParam& obj);
+    StConsistencyParam& operator=(const StConsistencyParam& obj);
+
+    void Init();
+
+    // ********* 一致性 ********* [[
+    void SetConsistencySwitch(bool b) { m_bConsistencySwitch = b; }
+    bool GetConsistencySwitch() { return m_bConsistencySwitch; }
+
+    int GetConsistencyThreshold() const { return m_iConsistencyThreshold; }
+    void SetConsistencyThreshold(int ival) { m_iConsistencyThreshold = ival; }
+
+    int GetConsistencyThresholdNum() const { return m_iConsistencyThresholdNum; }
+    void SetConsistencyThresholdNum(int ival) { m_iConsistencyThresholdNum = ival; }
+
+    int GetConsistencyThresholdNot() const { return m_iConsistencyThresholdNot; }
+    void SetConsistencyThresholdNot(int ival) { m_iConsistencyThresholdNot = ival; }
+
+    int GetConsistencyThresholdNotNum() const { return m_iConsistencyThresholdNotNum; }    
+	// 不一致的判定更严谨,全部为不一致时,才判定为不一致
+    int GetConsistencyThresholdNotNumEx() const { return m_iConsistencyThresholdNotNum * 2; }
+
+    void SetConsistencyThresholdNotNum(int ival) { m_iConsistencyThresholdNotNum = ival; }
+
+	int GetConsistencyThresholdWarningNum() const { return m_nConsistencyThresholdWarningNum; }
+	void SetConsistencyThresholdWarningNum(int ival) { m_nConsistencyThresholdWarningNum = ival; }
+
+private:
+    // 一致性监测开关
+    bool m_bConsistencySwitch;
+    // 一致性阀值
+    // 持续时间内,如果有m_iConsistencyThresholdNum相似度个比阀值大,就表示一致性
+    int	m_iConsistencyThreshold;
+    int	m_iConsistencyThresholdNum;
+	// 一致性阀值预警次数: 多少个不一致时,开启不一致预警
+	int m_nConsistencyThresholdWarningNum;
+    // 不一致性阀值
+    // 持续时间内,如果有m_iConsistencyThresholdNotNum相似度个比阀值小,就表示不一致性
+    int	m_iConsistencyThresholdNot;
+    int	m_iConsistencyThresholdNotNum;
+};
+
+
+
+/**
+ * @brief 保存n次一致性比较的结果,相似度的值,根据传入的阈值,计算是否是一致的
+ * 
+ */
 struct StConsistencyResult
 {
 	StConsistencyResult();
-	StConsistencyResult(StConsistencyParam &param);
+	// StConsistencyResult(StConsistencyParam &param);
     virtual ~StConsistencyResult();
 	StConsistencyResult(const StConsistencyResult& obj);
 	StConsistencyResult& operator=(const StConsistencyResult& obj);
 
-	void Init();
-    std::string OutPutConsistencyInfo(const bool bConsistencyInfo);
+	// void Init();
+    // std::string OutPutConsistencyInfo(const bool bConsistencyInfo);
 
-	int AddResult(const float f, const int iDelN);
-	int GetCount() const { return iCurPos; }
-    int GetMaxResult() const;
+	// int AddResult(const float f, const int iDelN);
+	// int GetCount() const { return iCurPos; }
+    // int GetMaxResult() const;
 
-	// 这个一致性不能用于判定是否一致性,一致性判定要在CConsistencyList里面判定,计算一致性的个数
-	bool IsConsistency() const;
-    bool IsNotConsistency() const;
+	// // 这个一致性不能用于判定是否一致性,一致性判定要在 CConsistencyList 里面判定,计算一致性的个数
+	// bool IsConsistency() const;
+    // bool IsNotConsistency() const;
 
-	bool m_bIsNoiseOfCur;
-	StConsistencyParam m_stConsistencyParam;
-	StConsistencyParam m_stNoiseConsistencyParam;
-	int GetConsistencyThresholdNum() const;
-	int GetConsistencyThresholdNotNum() const;
-	int GetConsistencyThresholdWarningNum() const;
+	// bool m_bIsNoiseOfCur;
+	// StConsistencyParam m_stConsistencyParam;
+	// StConsistencyParam m_stNoiseConsistencyParam;
+	// int GetConsistencyThresholdNum() const;
+	// int GetConsistencyThresholdNotNum() const;
+	// int GetConsistencyThresholdWarningNum() const;
 
-    int GetDelNAt(const int nIndex = 0) const { return aryOfDelN[nIndex]; }
+    // int GetDelNAt(const int nIndex = 0) const { return aryOfDelN[nIndex]; }
 
 	// Python对比结果
 	// int m_nRetPythonCompareFile;
@@ -56,11 +121,11 @@ struct StConsistencyResult
 	bool IsAIConsistency(int nThresholdNum, float dThreshold, std::string &strAIValue);
 	bool IsAINotConsistency(int nThresholdNum, float dThreshold, std::string &strAIValue);
 
-	int GetLastRetAICompareFile();
+	// int GetLastRetAICompareFile();
 
 private:
-	QDateTime m_tLastAITime;
-	int m_nLastRetAICompareFile;
+	// QDateTime m_tLastAITime;
+	// int m_nLastRetAICompareFile;
 
 	// AI对比结果,范围[0,1]
 	float aryOfAICompareFile[10];
@@ -72,12 +137,41 @@ private:
 	xxx1010001011010101110 
 	xxx的位数就是偏差量了
 	*/
-	int aryOfDelN[RESULT_NUM_OF_ONETIME_COMPARE];
-	// 相似度数组
-	float aryOfSimilarity[RESULT_NUM_OF_ONETIME_COMPARE];
-	// 数组实际保存了多少个数据,当前可以填充数据的位置
-	int iCurPos;
+	// int aryOfDelN[RESULT_NUM_OF_ONETIME_COMPARE];
+	// // 相似度数组
+	// float aryOfSimilarity[RESULT_NUM_OF_ONETIME_COMPARE];
+	// // 数组实际保存了多少个数据,当前可以填充数据的位置
+	// int iCurPos;
+
+};
 
+
+/**
+ * @brief 一致性计算结果,新版本
+ * 
+ */
+struct ConsistencyResult_t
+{
+	ConsistencyResult_t();
+	ConsistencyResult_t(const ConsistencyResult_t& obj);
+	ConsistencyResult_t& operator=(const ConsistencyResult_t& obj);
+
+
+	void Init();
+	/* 添加结果 */
+	bool AddResult(float fVal);
+	/* 计算一致性 */
+	eConsistencyState computeConsistency(int nThresholdNum, float fThreshold, std::string& strInfo);
+	/* 计算不一致性 */
+	eConsistencyState computeNotConsistency(int nThresholdNum, float fThreshold, std::string& strInfo);
+	/* 获取当前已存储的结果个数 */
+	int GetCount() const { return m_nCurPos; }
+
+private:
+	float m_fInitThreshold = 0.9;	/* 初始化阈值 */
+	const int m_numArryCount = 10;
+	float m_arryResult[10];			/* 结果数组 */
+	int m_nCurPos;					/* 当前结果位置 */
 };
 
 

+ 1 - 4
Server/GlobalInfo/GlobalInfo.h

@@ -117,7 +117,7 @@ public:
     int sinEffectiveNum() const {return m_sinEffectiveNum;}
 
     /* 获取杭州台是否按上面的逻辑来 */
-    bool isAINotConsistencyAlone() const {return m_isAINotConsistencyAlone; }
+    // bool isAINotConsistencyAlone() const {return m_isAINotConsistencyAlone; }
     /* 获取是否需要等待静音状态 */
     int nIsSameBothMinDBWaitNum() const {return m_nIsSameBothMinDBWaitNum;}
     /* 获取一致性对比时间间隔 */
@@ -206,9 +206,6 @@ private:
     int32_t m_noiseElementDuration = 1;         /* 噪音检测元素大小,单位:秒 */
 
     /******************** 定制化的配置选项 *********************/
-    /* 杭州台:在其它报警时,不一致不报警且后台不进行不一致比对,在其它报警恢复后,不一致重新计时比对
-	 * 1表示按上面的逻辑来,0表示不按上面的逻辑来 */
-    bool m_isAINotConsistencyAlone = false;
     /* 因为音频播放存在时间偏移,判断两个都是静音,或者判断一个静音一个非静音时,
      * 需要有延时时间(次数),CalcRefreshDataThread线程一秒一次 */
     int m_nIsSameBothMinDBWaitNum = 3;

+ 81 - 69
Server/ThreadCalculate/CompareDoubleThread.cpp

@@ -67,6 +67,15 @@ void CompareDoubleThread::task()
     {
         std::this_thread::sleep_for(std::chrono::milliseconds(20));
 
+        /* 判断是否开启不一致检测 */
+        if(m_isEnableNotConsistencyDetect.load() == false)
+        {
+            /* 不开启不一致检测,直接返回一致性结果 */
+            m_roadResult.isConsistency = true;
+            m_roadResult.isNotConsistencyWarning = false;
+            continue; // 跳过后续的计算
+        }
+
         /* 判断是否在检测时间段内 */
         if(m_isInDetectPeriod.load() == false)
         {
@@ -84,7 +93,7 @@ void CompareDoubleThread::task()
         /* 使用比对动态库比对一致性 */
         m_pConsistencyCompareThread->compareConsistencyData();
 
-        /* 更新数据 */
+        /* 更新数据,更新音量数据和动态库比对的结果 */
         if(!updateData())
         {
             continue; // 数据不足,继续等待
@@ -105,7 +114,7 @@ void CompareDoubleThread::task()
     /* 清理数据 */
     clearData();
     SPDLOG_LOGGER_WARN(m_logger, " ★ {} 计算双通道对比的线程结束 ", m_logBase);
-    m_threadInfo.threadState = EThreadState::State_Stopped; // 更新线程状态
+    m_threadInfo.threadState = EThreadState::State_Stopped;
 }
 
 
@@ -118,6 +127,9 @@ bool CompareDoubleThread::initData()
         SPDLOG_LOGGER_WARN(m_logger, "{} 对比项信息错误,录音通道数量小于2", m_threadInfo.compareItemInfo.strName.toStdString());
         return false;
     }
+    m_isEnableNotConsistencyDetect = true; // 默认开启不一致检测
+
+    /* 获取两个通道的信息 */
     auto it = m_threadInfo.compareItemInfo.mapRoad.begin();
     m_itemRoadInfo1 = it.value();
     m_roadInfo1 = it->scRoadInfo;
@@ -136,7 +148,7 @@ bool CompareDoubleThread::initData()
     m_silentThreshold = GInfo.silentThreshold(); // 获取静音阈值
     m_sinSeconds = GInfo.sinSeconds(); // 获取正弦波计算所需要的时长
 
-    m_isAINotConsistencyAlone = GInfo.isAINotConsistencyAlone(); // 获取杭州台是否按上面的逻辑来
+    // m_isAINotConsistencyAlone = GInfo.isAINotConsistencyAlone(); // 获取杭州台是否按上面的逻辑来
     m_nIsSameBothMinDBWaitNum = GInfo.nIsSameBothMinDBWaitNum(); // 获取是否需要等待静音状态
 
     m_nCompareTimeSpan = GInfo.compareTimeSpan(); // 获取比对时间间隔
@@ -257,7 +269,7 @@ bool CompareDoubleThread::updateData()
     }
 
     /* 获取一致性线程计算的结果 */
-    m_consistencyResult = m_pConsistencyCompareThread->getConsistencyResult();
+    // m_consistencyResult = m_pConsistencyCompareThread->getConsistencyResult();
 
     return true;
 }
@@ -396,88 +408,88 @@ void CompareDoubleThread::calculateOffset(long chn1Offset, long chn2Offset)
 bool CompareDoubleThread::getLatestConsistencyStatus(OneRoadVolume_t& oneRoad)
 {
     // 非对比时间时,默认为一致
-    if (!m_isCompareTime)
-    {
-        initMiniArray();
+    // if (!m_isCompareTime)
+    // {
+    //     initMiniArray();
 
-        // SPDLOG_LOGGER_DEBUG(m_logger, "{}: 非对比时间时,默认为一致", m_chnName);
+    //     // SPDLOG_LOGGER_DEBUG(m_logger, "{}: 非对比时间时,默认为一致", m_chnName);
 
-        oneRoad.isConsistency = true;
-        return true;
-    }
+    //     oneRoad.isConsistency = true;
+    //     return true;
+    // }
 
     /* 使用Python对比的结果,这里没有这个功能 */
     
 
     /* 如果没有开启比较线程,默认为一致 */
-    if (!m_isRunCompareThread)
-    {
-        oneRoad.isConsistency = true;
-        SPDLOG_LOGGER_INFO(m_logger, "{}: 没有开启比较线程,默认为一致", m_chnName);
-        return true;
-    }
+    // if (!m_isRunCompareThread)
+    // {
+    //     oneRoad.isConsistency = true;
+    //     SPDLOG_LOGGER_INFO(m_logger, "{}: 没有开启比较线程,默认为一致", m_chnName);
+    //     return true;
+    // }
 
     /* 不做一致性检测,返回一致性 */
-    if (!m_consistencyParam.GetConsistencySwitch())
-    {
-        SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性检测关闭,不做一致性检测,返回一致性", m_chnName);
+    // if (!m_consistencyParam.GetConsistencySwitch())
+    // {
+    //     SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性检测关闭,不做一致性检测,返回一致性", m_chnName);
 
-        oneRoad.isConsistency = true;
-        return true;
-    }
+    //     oneRoad.isConsistency = true;
+    //     return true;
+    // }
 
     /* 判断是否开启计算这两个通道音量值的线程
      * 如果两个线程都在不在运行,无法判断,则设置成一致,一个在运行一个不在运行,则不一致
      * */
-    if(!m_isRunCalDB1Thread && !m_isRunCalDB2Thread)
-    {
-        oneRoad.isConsistency = true;
-        SPDLOG_LOGGER_INFO(m_logger, "{}: 通道指针为空,默认为一致", m_chnName);
-        return true;
-    }
-    // 一个为空,一个不空判定为不一致
-    if (m_isRunCalDB1Thread != m_isRunCalDB2Thread)
-    {
-        oneRoad.isConsistency = false;
-        SPDLOG_LOGGER_INFO(m_logger, "{}: 一个通道正在运行计算音量的线程,一个通道未在运行,判定为不一致", m_chnName);
-        return false;
-    }
+    // if(!m_isRunCalDB1Thread && !m_isRunCalDB2Thread)
+    // {
+    //     oneRoad.isConsistency = true;
+    //     SPDLOG_LOGGER_INFO(m_logger, "{}: 通道指针为空,默认为一致", m_chnName);
+    //     return true;
+    // }
+    // // 一个为空,一个不空判定为不一致
+    // if (m_isRunCalDB1Thread != m_isRunCalDB2Thread)
+    // {
+    //     oneRoad.isConsistency = false;
+    //     SPDLOG_LOGGER_INFO(m_logger, "{}: 一个通道正在运行计算音量的线程,一个通道未在运行,判定为不一致", m_chnName);
+    //     return false;
+    // }
 
     /* 上一次的一致性标记 */
     m_mutexVolumeInfo.lock();
     const bool lastConsistency = m_roadResult.isConsistency;
     m_mutexVolumeInfo.unlock();
     bool bConsistency = lastConsistency;
-    if (!m_isRunCompareThread)
-    {
-        /* 没有开启比对线程 */
-        bConsistency = false;
-        if(m_recordDev1ID == m_recordDev2ID)
-        {
-            // 同一个通道肯定是一致的
-            bConsistency = true;
-            SPDLOG_LOGGER_INFO(m_logger, "同一个通道肯定是一致的");
-        }
-    }
-    else if(!m_isRunCalDB1Thread && !m_isRunCalDB2Thread)
-    {
-        // 都没有开启,表示两者是静音
-        bConsistency = true;
-        SPDLOG_LOGGER_INFO(m_logger, "都没有开启,表示两者是静音");
-    }
-    else if(m_isRunCalDB1Thread != m_isRunCalDB2Thread)
-    {
-        // 一个开启了,一个没有开启,表示不一致
-        bConsistency = false;
-        SPDLOG_LOGGER_INFO(m_logger, "一个开启了,一个没有开启,表示不一致");
-    }else 
+    // if (!m_isRunCompareThread)
+    // {
+    //     /* 没有开启比对线程 */
+    //     bConsistency = false;
+    //     if(m_recordDev1ID == m_recordDev2ID)
+    //     {
+    //         // 同一个通道肯定是一致的
+    //         bConsistency = true;
+    //         SPDLOG_LOGGER_INFO(m_logger, "同一个通道肯定是一致的");
+    //     }
+    // }
+    // else if(!m_isRunCalDB1Thread && !m_isRunCalDB2Thread)
+    // {
+    //     // 都没有开启,表示两者是静音
+    //     bConsistency = true;
+    //     SPDLOG_LOGGER_INFO(m_logger, "都没有开启,表示两者是静音");
+    // }
+    // else if(m_isRunCalDB1Thread != m_isRunCalDB2Thread)
+    // {
+    //     // 一个开启了,一个没有开启,表示不一致
+    //     bConsistency = false;
+    //     SPDLOG_LOGGER_INFO(m_logger, "一个开启了,一个没有开启,表示不一致");
+    // }else 
     {
         /* 都开启了计算音量的线程 */
         /* 获取上一次的低音量信息 */
         int bBothMinDB = m_bBothMinDB;
 
         addBothMiniDB(bBothMinDB);
-            
+        
         /*************************************************************
         * 金海林加入
         * 时间:  2023年8月30日 16:09:25
@@ -485,13 +497,14 @@ bool CompareDoubleThread::getLatestConsistencyStatus(OneRoadVolume_t& oneRoad)
         if (ESW_ALL_NOT != bBothMinDB)
         *************************************************************/
         /* m_isAINotConsistencyAlone 是外部的配置选项 */
-        if (ESW_ALL_NOT != bBothMinDB && !m_isAINotConsistencyAlone)
+        // if (ESW_ALL_NOT != bBothMinDB && !m_isAINotConsistencyAlone)
+        if(ESW_ALL_NOT != bBothMinDB)
         /**********金海林加入结束*************/
         {
             if (ESW_BothMinDB_TRUE == bBothMinDB)
             {
                 SPDLOG_LOGGER_INFO(m_logger, "{}: 平均音量比较小时,维持当前状态不变!", m_chnName);
-            } 
+            }
             else if (ESW_BothMute_TRUE == bBothMinDB)
             {
                 /*************************************************************
@@ -575,15 +588,14 @@ bool CompareDoubleThread::compareConsistencyBaseOnAI(bool& bConsistency, const b
     * 时间:  2023年8月30日 16:09:25
     * 描述:  杭州台:在其它报警时,不一致不报警且后台不进行不一致比对,在其它报警恢复后,不一致重新计时比对
     *************************************************************/
-    if (m_isHasAlarmExecpt)
-    {
-        bConsistency = true;
-        return false;
-    }
+    // if (m_isHasAlarmExecpt)
+    // {
+    //     bConsistency = true;
+    //     return false;
+    // }
     /**********金海林加入结束*************/
 
-    /* 更新动态库的一致性比对结果 */
-
+    /* 更新动态库的一致性比对结果,计算结果 */
 
     std::string strAIValue, strAIValueNot;
     bool bAICon = m_consistencyResult.IsAIConsistency(GInfo.AICMPThresholdNum(), GInfo.AICMPThreshold(), strAIValue);

+ 16 - 8
Server/ThreadCalculate/CompareDoubleThread.h

@@ -17,7 +17,8 @@ class CreateRecordFileThread;
 
 
 /**
-    功能:再检测一遍一致性和噪音,和动态库检测结果进行对比
+    功能: 不一致检测的运行线程,这个线程会调用 ConsistencyCompareThread 进行一致性检测,
+        不过这里会再检测一遍一致性和噪音,和动态库检测结果进行对比
         对比两个录音通道的数据,通道1是需要所有被对比的主通道,通道2就是其余通道
         对比结果就是对比项中任意一个通道和主通道的对比结果
         1、这里进一步进行噪音和一致性检测,可能是不放心动态库检测的结果
@@ -25,6 +26,9 @@ class CreateRecordFileThread;
         3、一致性检测通过检测是否静音来进行计算的,这里直接获取两个通道的音量值进行对比,
             获取一致性对比结果,再结合动态库检测的一致性进行判断
         4、调用动态库检测的功能没有再开一个线程,直接在这个线程中进行检测
+
+    最新说明:
+        2025-05-05: 这个类暂时废弃了
   
  */
 class CompareDoubleThread : public BaseCalculateThread
@@ -61,6 +65,9 @@ public:
 
     /* 设置是否在检测时间段 */
     void setInDetectPeriod(bool isInDetectPeriod) { m_isInDetectPeriod = isInDetectPeriod; }
+    /* 设置是否开启不一致检测 */
+    void enableNotConsistencyDetect(bool isNotConsistencyDetect) { m_isEnableNotConsistencyDetect.store(isNotConsistencyDetect); }
+    
 
 protected:
     /* 线程功能函数 */
@@ -104,7 +111,7 @@ private:
     CompareItemRoadInfo_t m_itemRoadInfo2;                  /* 对比项通道2信息 */
 
     std::atomic_bool m_isInDetectPeriod = true;             /* 是否在检测时段内 */
-    
+    std::atomic_bool m_isEnableNotConsistencyDetect = false;/* 是否开启不一致检测 */
 
     /* ----------------- 生成音量数据的线程 ------------------ */
     CreateDBThread* m_threadCreateDB1 = nullptr;            /* 生成通道1音量数据的线程 */
@@ -146,10 +153,10 @@ private:
     int m_recordDev2ID = 0;         /* 录音通道2 */
 
     /* 比较相关的标志位 */
-    bool m_isCompareTime = false;       /* 是否比较时间 */
-    bool m_isRunCompareThread = false;  /* 是否开启比较线程 */
-    bool m_isRunCalDB1Thread = false;   /* 是否开启生成音量的线程1 */
-    bool m_isRunCalDB2Thread = false;   /* 是否开启生成音量的线程2 */
+    // bool m_isCompareTime = false;       /* 是否比较时间 */
+    // bool m_isRunCompareThread = false;  /* 是否开启比较线程 */
+    // bool m_isRunCalDB1Thread = false;   /* 是否开启生成音量的线程1 */
+    // bool m_isRunCalDB2Thread = false;   /* 是否开启生成音量的线程2 */
 
     /* 偏移量,通道1和通道2可能会有偏移,如果通道1是发射出去,通道2是结束过来,之间可能会有
      * 几秒钟的偏移,这个偏移量是手动设置的
@@ -176,14 +183,15 @@ private:
     * 时间:  2023年8月29日 14:49:05
     * 描述:  杭州台:在其它报警时,不一致不报警且后台不进行不一致比对,在其它报警恢复后,不一致重新计时比对
     *        可以,加个配置项吧;这样的不一致更纯粹。1表示按上面的逻辑来,0表示不按上面的逻辑来
+    * 注:现在这个开关配置已经搬到对比项类中了,这里不再生效
     *************************************************************/
-    bool m_isAINotConsistencyAlone;
+    // bool m_isAINotConsistencyAlone;
     /**********金海林加入结束*************/
     /* 因为音频播放存在时间偏移,判断两个都是静音,或者判断一个静音一个非静音时,
      * 需要有延时时间(次数),CalcRefreshDataThread线程一秒一次 */
     int m_nIsSameBothMinDBWaitNum;
 
-    bool m_isHasAlarmExecpt = false;        /* 是否还有其他报警 */
+    // bool m_isHasAlarmExecpt = false;        /* 是否还有其他报警 */
 
     /* -----------------------------------------------------------------------
      * ConsistencyCompareThread 一致性检测功能线程,从这里开启

+ 67 - 28
Server/ThreadCalculate/CompareItemThread.cpp

@@ -8,7 +8,7 @@
 #include "ThreadManager.h"
 #include "CalculateDBThread.h"
 #include "NoiseDetectThread.h"
-#include "CompareDoubleThread.h"
+#include "ConsistencyCompareThread.h"
 #include "ThreadPool.h"
 #include "commonDefine.h"
 #include "ThreadAlarmManager.h"
@@ -202,7 +202,11 @@ bool CompareItemThread::initData()
 {
     /* 获取参数 */
     m_noiseDetectConfig = SysConfig.getNoiseDetectBaseConfig();
-
+    /* 一致性对比的一些参数 */
+    const auto& baseConfig = SysConfig.getBaseConfigSrc();
+    m_isConsistencyNoWarnWhenOtherAlarm = (baseConfig.nNotConsistency == 1);
+    m_isNotConsistencyOneRoadNoise = (baseConfig.nNotConsistency == 2);
+    m_isNotConsistencyIgnoreSilent = (baseConfig.nNotConsistency == 3);
 
     /* 创建录音通道线程 */
     for(const auto& road : m_threadInfo.compareItemInfo.mapRoad)
@@ -238,6 +242,7 @@ bool CompareItemThread::initData()
     getRecordThread();
     /* 开始录音 */
     startOrStopRecord(true);
+
     
 
     /* 初始化存储结果的数据结构 */
@@ -417,15 +422,15 @@ bool CompareItemThread::createCompareThreads()
         compareThreadInfo.compareItemInfo.mapRoad.insert(mainRoad.nCompareRoadNum, mainRoad);   // 添加主通道
         compareThreadInfo.compareItemInfo.mapRoad.insert(it.key(), it.value());                 // 添加当前通道
         compareThreadInfo.threadState = EThreadState::State_Inited;
-        CompareDoubleThread* pThread = new CompareDoubleThread(compareThreadInfo);
+        ConsistencyCompareThread* pThread = new ConsistencyCompareThread(compareThreadInfo);
         if(pThread == nullptr)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "{} 创建对比线程 {} - {} 失败", m_logBase, mainRoad.strCompareRoadName.toStdString(), it.value().strCompareRoadName.toStdString());
             return false;
         }
-        m_mapCompareDoubleThreads.insert({it.key(), pThread}); // 保存线程指针
+        m_mapCpmsistencyThreads.insert({it.key(), pThread}); // 保存线程指针
         /* 开始运行 */
-        CPPTP.add_task(&CompareDoubleThread::threadTask, pThread);
+        CPPTP.add_task(&ConsistencyCompareThread::threadTask, pThread);
     }
 
     return true;
@@ -434,12 +439,12 @@ bool CompareItemThread::createCompareThreads()
 /* 销毁两两对比线程 */
 void CompareItemThread::destroyCompareThreads()
 {
-    if(m_mapCompareDoubleThreads.size() == 0)
+    if(m_mapCpmsistencyThreads.size() == 0)
     {
         return; // 没有对比线程
     }
     SPDLOG_LOGGER_INFO(m_logger, "{} 销毁对比线程", m_logBase);
-    for(auto& pair : m_mapCompareDoubleThreads)
+    for(auto& pair : m_mapCpmsistencyThreads)
     {
         if(pair.second != nullptr)
         {
@@ -448,7 +453,7 @@ void CompareItemThread::destroyCompareThreads()
             pair.second = nullptr;          // 设置为nullptr
         }
     }
-    m_mapCompareDoubleThreads.clear();
+    m_mapCpmsistencyThreads.clear();
     m_mapCDBUpdated.clear(); // 清空更新标志位
     SPDLOG_LOGGER_INFO(m_logger, "{} 对比线程销毁完成", m_logBase);
 }
@@ -559,6 +564,8 @@ void CompareItemThread::destroyNoiseDetectThreads()
         3、客户端依赖音量包绘制波形,因此音量包尽可能地快速发送
 
     检测结果更新逻辑
+        1、获取音量计算线程的结果,获取静音、过载、反相等信息无需关心是否已经更新,结果大概1秒更新一次,
+            音量包100ms发送一次
         2、获取噪音检测线程的噪音信息和获取一致性信息的线程的结果无需关心是否是最新的
 
  */
@@ -627,7 +634,7 @@ bool CompareItemThread::updateResultData()
         if(pThread == nullptr)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "{} 音量计算线程失效", m_logBase);
-            continue; // 跳过这个线程
+            continue;
         }
         /* 获取最新的音量数据 */
         OneRoadVolume_t roadVolume;
@@ -636,11 +643,15 @@ bool CompareItemThread::updateResultData()
             m_compareResult.mapRoadVolumes[pair.first].similarity = roadVolume.similarity;
             m_compareResult.mapRoadVolumes[pair.first].isSilence = roadVolume.isSilence;
             m_compareResult.mapRoadVolumes[pair.first].isOverload = roadVolume.isOverload;
+            m_compareResult.mapRoadVolumes[pair.first].isReversed = roadVolume.isReversed;
             m_compareResult.mapRoadVolumes[pair.first].roadInfo = pThread->getRoadInfo();
+
         }else {
             SPDLOG_LOGGER_WARN(m_logger, "{} 获取音量计算结果失败,通道: {}", m_logBase, pair.first);
         }
     }
+    // SPDLOG_LOGGER_TRACE(m_logger, "{} 获取音量计算结果完成, 静音: {}, 过载: {}, 反相: {}",
+    //                     m_logBase, m_compareResult.mapRoadVolumes[1].isSilence, m_compareResult.mapRoadVolumes[1].isOverload, m_compareResult.mapRoadVolumes[1].isReversed);
 
 
     /* -------------------------------------------------------------------------------------
@@ -652,40 +663,68 @@ bool CompareItemThread::updateResultData()
         if(pThread == nullptr)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "{} 噪音检测线程失效", m_logBase);
-            continue; // 跳过这个线程
+            continue;
         }
-        /* 获取最新的噪音数据,噪音警那个标志位貌似没用到 */
+        /* 获取最新的噪音数据,噪音警那个标志位貌似没用到 */
         m_compareResult.mapRoadVolumes[pair.first].isNoise = pThread->isNoise();
+        m_compareResult.mapRoadVolumes[pair.first].isNoiseWarning = pThread->isNoiseWarning();
     }
 
     /* -------------------------------------------------------------------------------------
      * 从对比项中获取核对过后的一致性结果
      * ------------------------------------------------------------------------------------- */
-    for(auto& pair : m_mapCompareDoubleThreads)
+    /* 报警标志位,判断静音、过载、反相是否有在报警,给不一致检测使用的 */
+    std::map<int, bool> mapAlarmFlags;
+    for(const auto& roadVolume : m_compareResult.mapRoadVolumes)
+    {
+        bool isAlarm = (roadVolume.second.isSilence || roadVolume.second.isOverload || roadVolume.second.isReversed || roadVolume.second.isNoiseWarning);
+        mapAlarmFlags.insert({roadVolume.first, isAlarm});
+    }
+
+    for(auto& pair : m_mapCpmsistencyThreads)
     {
-        CompareDoubleThread* pThread = pair.second;
+        ConsistencyCompareThread* pThread = pair.second;
         if(pThread == nullptr)
         {
             SPDLOG_LOGGER_ERROR(m_logger, "{} 一致性对比线程失效", m_logBase);
             continue;
         }
+        
         /* 获取最新的一致性结果 */
-        OneRoadVolume_t roadVolume;
-        if(pThread->getlastResult(roadVolume))
+        m_compareResult.mapRoadVolumes[pair.first].isConsistency = pThread->isConsistency();
+        m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = pThread->isNotConsistencyWarning();
+        
+
+        /* 下面这两个条件不会同时设置为true,只会二选一 */
+
+        /* 判断是否开启了不一致报警条件: 在其他报警时,不一致不报警且后台不进行不一致对比 */
+        if(m_isConsistencyNoWarnWhenOtherAlarm == true)
         {
-            m_compareResult.mapRoadVolumes[pair.first].isConsistency = roadVolume.isConsistency;
-            m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = roadVolume.isNotConsistencyWarning;
+            /* 有其他报警,不一致不报警,并且暂停计算,直到其他报警结束后再继续计算 */
+            if(mapAlarmFlags[pair.first] == true)
+            {
+                m_compareResult.mapRoadVolumes[pair.first].isConsistency = false;
+                m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = false;
+                pThread->enableNotConsistencyDetect(false);
+                continue;
+            }else {
+                pThread->enableNotConsistencyDetect(true); // 继续进行不一致对比
+            }
         }
-    }
 
-    // for(const auto& roadVolume : m_compareResult.mapRoadVolumes)
-    // {
-    //     const OneRoadVolume_t& volume = roadVolume.second;
-    //     for(int i = 0; i < VOLUME_INFO_NUM; ++i)
-    //     {
-    //         fmt::print("LDB:{}, RDB:{}\n", volume.vecleftDB[i], volume.vecrightDB[i]);
-    //     }
-    // }
+        /* 判断是否开启了不一致报警条件: 如果主通道、其他通道,二者一个噪音,一个非噪音,直接判定为不一致 */
+        if(m_isNotConsistencyOneRoadNoise == true)
+        {
+            bool isMainRoadNoise = m_compareResult.mapRoadVolumes[1].isNoise;
+            bool isOtherRoadNoise = m_compareResult.mapRoadVolumes[pair.first].isNoise;
+            if(isMainRoadNoise != isOtherRoadNoise)
+            {
+                m_compareResult.mapRoadVolumes[pair.first].isConsistency = false;
+                m_compareResult.mapRoadVolumes[pair.first].isNotConsistencyWarning = true;
+                continue; // 直接进入下一个通道
+            }
+        }
+    }
 
     return true;
 }
@@ -849,9 +888,9 @@ bool CompareItemThread::checkDetectPeriod()
             }
         }
     }
-
+    // SPDLOG_LOGGER_TRACE(m_logger, "{} 检测时间段更新,当前时间: {}, 是否在检测时段内: {}", m_logBase, currentTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), isInDetectPeriod);
     /* 应用于对比项检测,对比项不设置日期不会进行检测 */
-    for(auto& pThread : m_mapCompareDoubleThreads)
+    for(auto& pThread : m_mapCpmsistencyThreads)
     {
         pThread.second->setInDetectPeriod(isInDetectPeriod);
     }

+ 11 - 5
Server/ThreadCalculate/CompareItemThread.h

@@ -16,9 +16,9 @@
 
 class CalculateDBThread;
 class NoiseDetectThread;
-class CompareDoubleThread;
 class CreateDBThread;
 class CreateRecordFileThread;
+class ConsistencyCompareThread;
 
 
 /**
@@ -31,7 +31,7 @@ class CreateRecordFileThread;
                一致性报警信息从两两对比线程中计算得出,直接写入数据库
                噪音报警信息从噪音检测线程中计算得出,直接写入数据库
             4、这里创建的线程包含:两两对比线程、音量检测线程,这两个都和对比项相关联
-            5、噪音检测线程从线程管理器中获取的,这里不负责创建和销毁
+            5、噪音检测线程现在也移动到这里创建,因为噪音报警需要对比项信息
         其他说明:
             1、这个线程由于需要使用qmqtt发布数据,需要使用到Qt的事件循环,所以多继承了 QObject,
                线程的使用权会交给 Qt 的事件循环来管理,通过定时器定时调用 task() 函数
@@ -83,9 +83,9 @@ private:
     /* 获取录音线程,这个属于录音线程,不需要移除释放  */
     void getRecordThread();
 
-    /* 创建两个对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
+    /* 创建一致性对比线程,主通道是第一个通道,其他都需要和主通道进行对比 */
     bool createCompareThreads();
-    /* 销毁两两对比线程 */
+    /* 销毁一致性对比线程 */
     void destroyCompareThreads();
     
     /* 创建计算音量报警的线程 */
@@ -128,7 +128,13 @@ private:
     /* ---------------------- DEBUG ---------------------- */
     std::chrono::steady_clock::time_point m_nowTimePoint;
     
+    /* ---------------------- 动态库设置的参数 ---------------------- */
+    /* 这三个参数从设置动态库中获取 */
+    bool m_isConsistencyNoWarnWhenOtherAlarm = false;   /* 在其他报警时,不一致不报警且后台不进行不一致对比 */
+    bool m_isNotConsistencyOneRoadNoise = false;        /* 如果主通道、其他通道,二者一个噪音,一个非噪音,直接判定为不一致 */
+    bool m_isNotConsistencyIgnoreSilent = false;        /* 不一致对比不进行静音、反相等处理 */
     
+
     /* ---------------------- 对比项 ---------------------- */
 
     /* 计算音量信息的线程指针,第一个是主通道线程,int是对比项中的通道号 */
@@ -136,7 +142,7 @@ private:
     /* 计算噪音的线程指针 */
     std::map<int, NoiseDetectThread*> m_mapNoiseDetectThreads;
     /* 对比项信息线程,这个线程在这里创建,不会和其他对比项复用,int是第二路对比通道的编号 */
-    std::map<int, CompareDoubleThread*> m_mapCompareDoubleThreads;
+    std::map<int, ConsistencyCompareThread*> m_mapCpmsistencyThreads;
     /* 创建音量包的线程指针 */
     std::map<int, CreateDBThread*> m_mapCreateDBThreads;
 

+ 193 - 32
Server/ThreadCalculate/ConsistencyCompareThread.cpp

@@ -2,6 +2,8 @@
 
 #include "GlobalVariable.h"
 #include "ThreadManager.h"
+#include "CreateRecordFileThread.h"
+#include "ThreadAlarmManager.h"
 
 #include "CreateWAVThread.h"
 #include "LHCompareAPI.h"
@@ -17,32 +19,26 @@ ConsistencyCompareThread::~ConsistencyCompareThread()
 
 }
 
-/* 获取一致性比对的结果 */
-StConsistencyResult ConsistencyCompareThread::getConsistencyResult()
-{
-    std::lock_guard<std::mutex> lock(m_mutexResult);
-    return m_consistencyResult;
-}
 
 /* 判断录音通道是否相等 */
-bool ConsistencyCompareThread::isRoadEqual(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2)
-{
-    /* r1对比m_r1,r2对比M_r2 */
-    if( roadInfo1.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum &&
-        roadInfo2.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum )
-    {
-        return true;
-    }
+// bool ConsistencyCompareThread::isRoadEqual(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2)
+// {
+//     /* r1对比m_r1,r2对比M_r2 */
+//     if( roadInfo1.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum &&
+//         roadInfo2.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum )
+//     {
+//         return true;
+//     }
     
-    /* 反过来对比一下 */
-    if( roadInfo1.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum &&
-        roadInfo2.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum )
-    {
-        return true;
-    }
+//     /* 反过来对比一下 */
+//     if( roadInfo1.nSoundCardNum == m_roadInfo2.nSoundCardNum && roadInfo1.roadInfo.nRoadNum == m_roadInfo2.roadInfo.nRoadNum &&
+//         roadInfo2.nSoundCardNum == m_roadInfo1.nSoundCardNum && roadInfo2.roadInfo.nRoadNum == m_roadInfo1.roadInfo.nRoadNum )
+//     {
+//         return true;
+//     }
 
-    return false;
-}
+//     return false;
+// }
 
 /* 初始化 */
 bool ConsistencyCompareThread::initConsistencyCompare()
@@ -80,6 +76,8 @@ bool ConsistencyCompareThread::compareConsistencyData()
     {
         return false;
     }
+    /* 计算一致性结果 */
+    computeResult();
     m_prevWavFilePath1 = m_wavFilePath1; // 更新上一个wav文件路径
     m_prevWavFilePath2 = m_wavFilePath2; // 更新上一个wav文件路径
 
@@ -112,6 +110,29 @@ void ConsistencyCompareThread::task()
     {
         std::this_thread::sleep_for(std::chrono::milliseconds(100));
 
+        /* 判断是否开启不一致检测 */
+        if(m_isEnableNotConsistencyDetect.load() == false)
+        {
+            /* 不开启不一致检测,直接返回一致性结果 */
+            m_isConsistency = true;
+            m_isConsistencyWarning = false;
+            continue; // 跳过后续的计算
+        }
+
+        /* 判断是否在检测时间段内 */
+        if(m_isInDetectPeriod.load() == false)
+        {
+            /* 不在检测时间段内,不需要比对,结果一直为一致性 */
+            m_isConsistency = true;
+            m_isConsistencyWarning = false;
+            /* 如果此时还在非一致性报警中,结束报警 */
+            if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
+            {
+                saveAlarmInfo();
+            }
+            continue;
+        }
+
         compareConsistencyData();
     }
     clearData();
@@ -129,13 +150,13 @@ bool ConsistencyCompareThread::initData()
     }
     /* 获取两个录音通道的信息 */
     auto it = m_threadInfo.compareItemInfo.mapRoad.begin();
-    m_roadInfo1 = it.value().scRoadInfo; // 第一个通道
+    m_itemRoadInfo1 = it.value(); // 第一个通道
     it++;
-    m_roadInfo2 = it.value().scRoadInfo; // 第二个通道
+    m_itemRoadInfo2 = it.value(); // 第二个通道
 
     m_logBase = fmt::format("对比通道 {}:{} - {}:{}", 
-                    m_roadInfo1.strSoundCardName.toStdString(), m_roadInfo1.roadInfo.nRoadNum, 
-                    m_roadInfo2.strSoundCardName.toStdString(), m_roadInfo2.roadInfo.nRoadNum);
+                    m_itemRoadInfo1.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum, 
+                    m_itemRoadInfo2.scRoadInfo.strSoundCardName.toStdString(), m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
     
     /* 获取创建wav文件的指针 */
     auto startTime = std::chrono::steady_clock::now(); // 记录开始时间
@@ -143,13 +164,25 @@ bool ConsistencyCompareThread::initData()
     {
         if(m_pCreateWAVThread1 == nullptr)
         {
-            m_pCreateWAVThread1 = ThreadMan.getCreateWAVThread(m_roadInfo1.nSoundCardNum, m_roadInfo1.roadInfo.nRoadNum);
+            m_pCreateWAVThread1 = ThreadMan.getCreateWAVThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
         }
         if(m_pCreateWAVThread2 == nullptr)
         {
-            m_pCreateWAVThread2 = ThreadMan.getCreateWAVThread(m_roadInfo2.nSoundCardNum, m_roadInfo2.roadInfo.nRoadNum);
+            m_pCreateWAVThread2 = ThreadMan.getCreateWAVThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
         }
-        if(m_pCreateWAVThread1 != nullptr && m_pCreateWAVThread2 != nullptr)
+        
+        /* 获取生成报警音频文件的线程 */
+        if(m_threadCreateAlarmFile1 == nullptr)
+        {
+            m_threadCreateAlarmFile1 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo1.scRoadInfo.nSoundCardNum, m_itemRoadInfo1.scRoadInfo.roadInfo.nRoadNum);
+        }
+        if(m_threadCreateAlarmFile2 == nullptr)
+        {
+            m_threadCreateAlarmFile2 = ThreadMan.getCreateRecordFileThread(m_itemRoadInfo2.scRoadInfo.nSoundCardNum, m_itemRoadInfo2.scRoadInfo.roadInfo.nRoadNum);
+        }
+
+        if( m_pCreateWAVThread1 != nullptr && m_pCreateWAVThread2 != nullptr && 
+            m_threadCreateAlarmFile1 != nullptr && m_threadCreateAlarmFile2 != nullptr )
         {
             break; // 获取到两个线程,跳出循环
         }
@@ -167,6 +200,12 @@ bool ConsistencyCompareThread::initData()
         SPDLOG_LOGGER_ERROR(m_logger, "{} 获取录音线程失败", m_logBase);
         return false;
     }
+    
+    if(m_threadCreateAlarmFile1 == nullptr || m_threadCreateAlarmFile2 == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{} 获取生成报警音频文件的线程失败", m_logBase);
+        return false;
+    }
 
     return true;
 }
@@ -217,12 +256,134 @@ bool ConsistencyCompareThread::compareConsistency()
     //     m_logBase, m_wavFilePath1.fileName, m_wavFilePath2.fileName, result->highest_similarity, result->average_similarity);
 
     /* 保存结果 */
-    m_mutexResult.lock();
-    m_consistencyResult.AddRetAICompareFile(result->highest_similarity / 100.0);
-    m_mutexResult.unlock();
+    m_consistencyResult.AddResult(result->highest_similarity / 100.0);
 
     delete result;
     result = nullptr;
 
     return true;
 }
+
+
+
+/* 根据动态库返回的结果计算一致性 */
+bool ConsistencyCompareThread::computeResult()
+{
+    std::string strAIValue, strAIValueNot;
+    auto consistencyState = m_consistencyResult.computeConsistency(m_numCompareContinue, m_fConsistencyThreshold, strAIValue);
+    auto notConsisencyState = m_consistencyResult.computeNotConsistency(m_numCompareContinue, m_fNotConsistencyThreshold, strAIValueNot);
+
+    if (eConsistencyState::eCS_Consistency == consistencyState)
+    {
+        /* 计算出的一致性是确定的 */
+        m_isConsistency.store(true);
+        m_isConsistencyWarning.store(false);
+    }
+    else if(eConsistencyState::eCS_Consistency == notConsisencyState)
+    {
+        /* 计算出的不一致性是确定的 */
+        m_isConsistency.store(false);
+        m_isConsistencyWarning.store(true);
+    }else 
+    {
+        /* 都不是确定的一致性和不一致性,使用上次的结果 */
+        m_isConsistency.store(m_isConsistencyLatest.load());
+        m_isConsistencyWarning.store(true);
+    }
+
+    return true;
+}
+
+
+/* 保存报警信息 */
+void ConsistencyCompareThread::saveAlarmInfo()
+{
+    if(m_isConsistency)
+    {
+        /* 这次是一致的,判断之前是否在一致性报警中 */
+        if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
+        {
+            /* 之前在一致性报警中,这次一致,结束不一致性报警 */
+            m_alarmConsistencyMain.isAlarm = false;
+            m_alarmConsistencySub.isAlarm = false;
+            /* 结束时间向前推1秒 */
+            m_alarmConsistencyMain.EndTime = m_wavFilePath1.endDateTime.addSecs(1);
+            m_alarmConsistencySub.EndTime = m_wavFilePath2.endDateTime.addSecs(1);
+            /* 结束录制报警音频 */
+            m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
+            m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
+
+            /* 将报警信息写入数据库 */
+            AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
+            AlarmManager.addAlarmInfo(m_alarmConsistencySub);
+            
+            SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
+            /* 清除报警信息 */
+            m_alarmConsistencyMain = AlarmInfo_t();
+            m_alarmConsistencySub = AlarmInfo_t();
+        }
+    }else 
+    {
+        /* 不一致,判断之前的一致性,判断一个就可以了 */
+        if(!m_alarmConsistencySub.isAlarm)
+        {
+            /* 开是不一致报警 */
+            m_alarmConsistencyMain.isAlarm = true;
+            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.RoadInfo = m_itemRoadInfo1;
+            m_alarmConsistencySub.RoadInfo = m_itemRoadInfo2;
+
+            m_alarmConsistencyMain.AlarmType = EAlarmType::EAR_Consistency;
+            m_alarmConsistencySub.AlarmType = EAlarmType::EAR_Consistency;
+            
+            /* 计算开始时间,开始时间计算方法:
+               单次计算的时间长度是 numFileDuration, 计算 m_numCompareContinue 次才会不一致性报警,因此向前推
+                m_numFileDuration * m_numCompareContinue 秒
+            */
+            int seconds = m_numFileDuration * m_numCompareContinue;
+            /* 因为 m_numCompareContinue 次计算也包括这次的文件,所以从结束时间开始向前推 */
+            m_alarmConsistencyMain.StartTime = m_wavFilePath1.endDateTime.addSecs(-seconds);
+            m_alarmConsistencySub.StartTime = m_wavFilePath2.endDateTime.addSecs(-seconds);
+
+            SPDLOG_LOGGER_WARN(m_logger, "{}: 不一致报警开始", m_logBase);
+            m_threadCreateAlarmFile1->startRecordAlarmFile(m_alarmConsistencyMain);
+            m_threadCreateAlarmFile2->startRecordAlarmFile(m_alarmConsistencySub);
+        }
+    }
+}
+
+/* 结束报警 */
+void ConsistencyCompareThread::endAlarm()
+{
+    m_isConsistency = true;
+
+    /* 这次是一致的,判断之前是否在一致性报警中 */
+    if(m_alarmConsistencyMain.isAlarm || m_alarmConsistencySub.isAlarm)
+    {
+        /* 之前在一致性报警中,这次一致,结束不一致性报警 */
+        m_alarmConsistencyMain.isAlarm = false;
+        m_alarmConsistencySub.isAlarm = false;
+        /* 结束时间向前推1秒 */
+        m_alarmConsistencyMain.EndTime = m_wavFilePath1.endDateTime.addSecs(1);
+        m_alarmConsistencySub.EndTime = m_wavFilePath2.endDateTime.addSecs(1);
+        /* 结束录制报警音频 */
+        m_threadCreateAlarmFile1->stopRecordAlarmFile(m_alarmConsistencyMain);
+        m_threadCreateAlarmFile2->stopRecordAlarmFile(m_alarmConsistencySub);
+        /* 将报警信息写入数据库 */
+        AlarmManager.addAlarmInfo(m_alarmConsistencyMain);
+        AlarmManager.addAlarmInfo(m_alarmConsistencySub);
+        
+        SPDLOG_LOGGER_INFO(m_logger, "{}: 一致性报警结束", m_logBase);
+        /* 清除报警信息 */
+        m_alarmConsistencyMain = AlarmInfo_t();
+        m_alarmConsistencySub = AlarmInfo_t();
+    }
+    
+}
+
+
+

+ 52 - 8
Server/ThreadCalculate/ConsistencyCompareThread.h

@@ -9,6 +9,7 @@
 
 
 class CreateWAVThread;
+class CreateRecordFileThread;
 
 
 
@@ -24,10 +25,12 @@ public:
     ~ConsistencyCompareThread() override;
 
     /* 获取一致性比对的结果 */
-    StConsistencyResult getConsistencyResult();
+    bool isConsistency() { return m_isConsistency.load(); }
+    /* 获取不一致性预警 */
+    bool isNotConsistencyWarning() { return m_isConsistencyWarning.load(); }
 
     /* 判断录音通道是否相等 */
-    bool isRoadEqual(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2);
+    // bool isRoadEqual(const SoundCardRoadInfo_t& roadInfo1, const SoundCardRoadInfo_t& roadInfo2);
 
     /* 这几个函数给外部线程调用,无需单独开启子线程了 */
     /* 初始化 */
@@ -38,6 +41,12 @@ public:
     void clearConsistencyCompareData();
 
 
+    /* 设置是否在检测时间段 */
+    void setInDetectPeriod(bool isInDetectPeriod) { m_isInDetectPeriod = isInDetectPeriod; }
+    /* 设置是否开启不一致检测 */
+    void enableNotConsistencyDetect(bool isNotConsistencyDetect) { m_isEnableNotConsistencyDetect.store(isNotConsistencyDetect); }
+
+
 protected:
     /* 线程功能函数 */
     void task() override;
@@ -50,10 +59,22 @@ private:
     /* 比对两个wav文件的一致性 */
     bool compareConsistency();
 
+    /* 根据动态库返回的结果计算一致性 */
+    bool computeResult();
+
+    /* 保存报警信息 */
+    void saveAlarmInfo();
+    /* 结束报警 */
+    void endAlarm();
+
 private:
+    std::atomic_bool m_isInDetectPeriod = true;             /* 是否在检测时段内 */
+    std::atomic_bool m_isEnableNotConsistencyDetect = true; /* 是否开启不一致检测 */
+
     /* 两个录音通道的信息 */
-    SoundCardRoadInfo_t m_roadInfo1;                     /* 录音通道1信息,这里不使用通道num */
-    SoundCardRoadInfo_t m_roadInfo2;                     /* 录音通道2信息 */
+    CompareItemRoadInfo_t m_itemRoadInfo1;               /* 对比项通道1信息,这两个给报警信息使用的 */
+    CompareItemRoadInfo_t m_itemRoadInfo2;               /* 对比项通道2信息 */
+
     /* 两个录音通道的线程指针,直接通过录音类获取最新的数据 */
     CreateWAVThread* m_pCreateWAVThread1 = nullptr; /* 通道1的录音线程 */
     CreateWAVThread* m_pCreateWAVThread2 = nullptr; /* 通道2的录音线程 */
@@ -64,12 +85,35 @@ private:
     WavFilePath m_prevWavFilePath1;                 /* 通道1的上一个wav文件路径 */
     WavFilePath m_prevWavFilePath2;                 /* 通道2的上一个wav文件路径 */
 
+    /* ---------------------------------- 动态库检测参数和结果 ---------------------------------- */
     double m_sensitivity = 20.0;                    /* 比对灵敏度,默认20,范围[0-100] */
-
-    std::mutex m_mutexResult;                       /* 互斥锁,一致性比对的结果 */
-    StConsistencyResult m_consistencyResult;        /* 一致性计算结果 */
-
     double m_similarity = 0.0;                      /* 比对结果相似度 */
+
+    /* ---------------------------------- 一致性计算参数 ---------------------------------- */
+    /* 这些都是从设置动态库中获取 */
+    int m_numFileDuration = 8;                      /* 文件对比的时间长度,单位秒 */
+    int m_numCompareContinue = 3;                   /* 持续对比次数 */
+    double m_fNotConsistencyThreshold = 0.6;        /* 不相似度阈值,小于这个就不一致的 */
+    double m_fConsistencyThreshold = 0.7;           /* 相似度阈值,高于这个就是一致的 */
+    // int m_arryAIChangeRetNum[2] = {0};          /* AI对比更正次数,默认10次 */
+
+
+    /* ---------------------------------- 计算的一致性结果 ---------------------------------- */
+    /* 动态库只检测出相似度,没有给出是否一致的定论,需要手动判断 */
+    ConsistencyResult_t m_consistencyResult;    /* 存储动态库计算的结果,并计算出一致性结论 */
+    // StConsistencyParam m_consistencyParam;      /* 一致性检测需要的参数 */
+
+    std::atomic_bool m_isConsistency = true;    /* 是否一致性,默认一致性 */
+    std::atomic_bool m_isConsistencyLatest = true;/* 上一次检测的一致性结果 */
+    std::atomic_bool m_isConsistencyWarning = false; /* 是否有不一致性预警 */
+
+    /* ---------------------------------- 报警信息 ---------------------------------- */
+    /* 生成报警音频文件的线程  */
+    CreateRecordFileThread* m_threadCreateAlarmFile1 = nullptr;
+    CreateRecordFileThread* m_threadCreateAlarmFile2 = nullptr;
+    /* 一致性报警信息 */
+    AlarmInfo_t m_alarmConsistencyMain;         /* 一致性报警信息,主通道 */
+    AlarmInfo_t m_alarmConsistencySub;          /* 一致性报警信息,次通道 */
 };
 
 

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

@@ -16,8 +16,14 @@
  * GCC9会在标准库中,GCC8.3需要手动链接库stdc++fs才可以使用
  */
 
+std::atomic_bool g_isLogInit(false); // 是否已经初始化日志
+
 void initLog(QString ModuleName, CLHQLogApi& lhQLog)
 {
+    if(g_isLogInit.load())
+    {
+        return;
+    }
 
     try {
         /* 创建一个控制台sink */
@@ -118,6 +124,8 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
     catch (const spdlog::spdlog_ex& ex) {
         qDebug() << "Log initialization failed: " << ex.what() ;
     }
+
+    g_isLogInit.store(true);
 }
 
 

+ 91 - 6
SettingLibrary/Modules/AICompare/aicomparewidget.ui

@@ -63,6 +63,78 @@
         </property>
        </widget>
       </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;AI每次判断的文件时长(秒):</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QLineEdit" name="lineEdit_similarThrehold">
+        <property name="minimumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_4">
+        <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;不相似度&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="4" column="0">
+       <widget class="QLabel" name="label_5">
+        <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;相似度&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="2" column="0">
+       <widget class="QLabel" name="label_3">
+        <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;AI对比持续次数:&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="3" column="1">
+       <widget class="QLineEdit" name="lineEdit_notSimilarThrehold">
+        <property name="minimumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+       </widget>
+      </item>
       <item row="0" column="1">
        <widget class="QLineEdit" name="lineEdit_length">
         <property name="minimumSize">
@@ -79,6 +151,22 @@
         </property>
        </widget>
       </item>
+      <item row="2" column="1">
+       <widget class="QLineEdit" name="lineEdit_compareCount">
+        <property name="minimumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>168</width>
+          <height>32</height>
+         </size>
+        </property>
+       </widget>
+      </item>
       <item row="1" column="1">
        <widget class="QLineEdit" name="lineEdit_dir">
         <property name="minimumSize">
@@ -95,13 +183,10 @@
         </property>
        </widget>
       </item>
-      <item row="0" column="0">
-       <widget class="QLabel" name="label">
+      <item row="5" column="0" colspan="2">
+       <widget class="QCheckBox" name="checkBox_noConsistencyOtherAlarm">
         <property name="text">
-         <string>&lt;font color = #D21F21 &gt;*&lt;/font&gt;AI每次判断的文件时长(秒):</string>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+         <string>其他报警时,不一致不报警且后台不进行不一致对比</string>
         </property>
        </widget>
       </item>

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

@@ -56,6 +56,10 @@ BasicWidget::BasicWidget(QWidget *parent) :
         ui->comBox_notConsistency->addItem(it.value(), it.key());
     }
 
+    /* 隐藏不一致判断选项,这个大部分没用了,有用的搬到AI对比中了 */
+    ui->label_5->hide();
+    ui->comBox_notConsistency->hide();
+
     /* 设置从数据库读取到的选项 */
     restoreBasicSettingInfo();
 

+ 1 - 1
SettingLibrary/Modules/Database/databasewidget.ui

@@ -227,7 +227,7 @@
       <item row="4" column="0">
        <widget class="QLabel" name="label_5">
         <property name="text">
-         <string>&lt;font color = #D21F21 &gt;*&lt;/font&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;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>