Parcourir la source

V0.5
1、调试完成了获取设备的服务
2、调试完成了分配任务的功能

Apple il y a 10 heures
Parent
commit
ccd2f26174
28 fichiers modifiés avec 842 ajouts et 482 suppressions
  1. 13 9
      CMakeLists.txt
  2. 1 1
      SQL/SecurePlay.sqlbook
  3. 12 2
      SecurePlayAuxServer/Application/FuncBase.cpp
  4. 9 9
      SecurePlayAuxServer/Application/FuncIllegalInvasion.cpp
  5. 4 4
      SecurePlayAuxServer/Application/FuncOnAndOffJob.cpp
  6. 7 7
      SecurePlayAuxServer/Application/FuncOrdinary.cpp
  7. 3 3
      SecurePlayAuxServer/Application/FuncPersonOnWork.cpp
  8. 1 1
      SecurePlayAuxServer/Application/FuncRegionalPerson.cpp
  9. 5 1
      SecurePlayAuxServer/CMakeLists.txt
  10. 211 31
      SecurePlayAuxServer/GlobalInfo/GlobalConfig.cpp
  11. 122 21
      SecurePlayAuxServer/GlobalInfo/GlobalConfig.h
  12. 56 115
      SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.cpp
  13. 2 0
      SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.h
  14. 0 3
      SecurePlayAuxServer/GlobalInfo/GlobalVariable.cpp
  15. 2 40
      SecurePlayAuxServer/GlobalInfo/GlobalVariable.h
  16. 6 3
      SecurePlayAuxServer/GlobalInfo/UniversalFunc.cpp
  17. 145 131
      SecurePlayAuxServer/SPAServer.cpp
  18. 6 5
      SecurePlayAuxServer/SPAServer.h
  19. 11 8
      SecurePlayAuxServer/common/LHLog/LHLogInit.cpp
  20. 26 0
      SecurePlayAuxServer/communication/FromMQTT.cpp
  21. 26 0
      SecurePlayAuxServer/communication/FromMQTT.h
  22. 29 15
      SecurePlayAuxServer/communication/FromSuperBrain.cpp
  23. 5 1
      SecurePlayAuxServer/communication/FromSuperBrain.h
  24. 115 62
      SecurePlayAuxServer/communication/FromWebAPI.cpp
  25. 1 1
      SecurePlayAuxServer/communication/FromWebAPI.h
  26. 9 7
      SecurePlayAuxServer/main.cpp
  27. BIN
      image.png
  28. 15 2
      安播辅助服务程序说明.md

+ 13 - 9
CMakeLists.txt

@@ -122,17 +122,21 @@ add_compile_definitions(SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE)
 #*******************  搜索库添加库 ***********************
 #=========================================================
 
-# find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
-# find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
-
-find_package(Qt5 COMPONENTS
-    # Widgets
-    Core
-    # Network
-    # Sql
-    REQUIRED
+find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
+find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS 
+        Core
+        # Widgets
+        Network
 )
 
+# find_package(Qt5 COMPONENTS
+#     # Widgets
+#     Core
+#     # Network
+#     # Sql
+#     REQUIRED
+# )
+
 #包含外部通用库
 include(${CMAKE_SOURCE_DIR}/External/Libraries/Libraries.cmake)
 

+ 1 - 1
SQL/SecurePlay.sqlbook

@@ -7,7 +7,7 @@ FROM "tAction";
 
 #插入信息
 INSERT INTO "tAction" ("ActionId","ActionTaskid","ActionName")
-VALUES ('1',1,'test');
+VALUES ('OD210_022_001835_029-CYl65jlE', 8, '人员计数');
 
 #插入信息,带有参数
 INSERT INTO "tAction" ("ActionId","ActionTaskid","ActionName")

+ 12 - 2
SecurePlayAuxServer/Application/FuncBase.cpp

@@ -49,11 +49,21 @@ void FuncBase::thread_task()
         SPDLOG_LOGGER_ERROR(m_logger, "未设置线程功能信息");
         return;
     }
-    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 功能线程, ChannelID:{}",m_funcThreadInfo.strFunctionName, m_funcThreadInfo.ChannelID);
+    SPDLOG_LOGGER_INFO(m_logger, "开启频道: [{}:{}] {}功能线程", m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName, m_funcThreadInfo.strFunctionName);
+    for(auto& room : m_funcThreadInfo.listRoomCamActInfo)
+    {
+        for(auto& cam : room.mapCameraAction)
+        {
+            for(auto& act : cam.second)
+            {
+                SPDLOG_LOGGER_DEBUG(m_logger, "房间ID: {}, 摄像机ID: {}, 算法ID: {}", room.RoomID, cam.first, act);
+            }
+        }
+    }
     /* 设置线程运行状态 */
     m_bRunning = true;
     /* 执行线程功能,会一直阻塞,直到退出 */
-    task();
+    // task();
     /* 设置线程退出的状态,设置成 RUN_STATE_EXITCOMPLET ,就会被管理线程回收 */
     GThreadInfo.setThreadState(m_funcThreadInfo, RunTimeState::RUN_STATE_EXITCOMPLET);
     SPDLOG_LOGGER_INFO(m_logger, "{} 功能线程退出,Channel:{}", m_funcThreadInfo.strFunctionName, m_funcThreadInfo.ChannelID);

+ 9 - 9
SecurePlayAuxServer/Application/FuncIllegalInvasion.cpp

@@ -219,16 +219,16 @@ void FuncIllegalInvasion::task()
         /* 判断是否在检测时间段内 */
         if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
         {
-            std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
         /* 更新算法ActionID */
         {
-            g_actionList.mutexRW.lockForRead();
-            strFaceActionID = g_actionList.ActFace;
-            strCountActionID = g_actionList.ActPersonNumber;
-            g_actionList.mutexRW.unlock();
+            GVariable.mutexRW.lockForRead();
+            strFaceActionID = GVariable.ActFaceIdentify;
+            strCountActionID = GVariable.ActPersonCount;
+            GVariable.mutexRW.unlock();
         }
 
         /* 读取Redis数据 */
@@ -369,7 +369,7 @@ void FuncIllegalInvasion::task()
                 /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */
                 QDateTime currTime = QDateTime::currentDateTime();
                 int secs = currTime.toSecsSinceEpoch() - pIll->FirstTime.toSecsSinceEpoch();
-                if(secs >= GConfig.AppBadMan_Time)
+                if(secs >= GVariable.AppBadMan_Time)
                 {
                     if(!pIll->strImageInfo.empty())
                     {
@@ -377,7 +377,7 @@ void FuncIllegalInvasion::task()
                         AlarmInfo ai;
                         ai.ChannelID = m_funcThreadInfo.ChannelID;
                         ai.RoomID = pIll->RoomID;
-                        ai.ActionID = g_actionList.ActPersonNumber;
+                        ai.ActionID = GVariable.ActPersonCount;
                         ai.ActionDes = pIll->strActionDec;
                         ai.ImageInfo = pIll->strImageInfo;
                         ai.StartTime = pIll->FirstTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
@@ -388,7 +388,7 @@ void FuncIllegalInvasion::task()
                         bool insertRet  = m_fromWebAPI->insertAlarmInfo(ai);
                         if(insertRet)
                         {
-                            std::string actionName = g_actionList.getActionName(ai.ActionID);
+                            std::string actionName = GVariable.getActionName(ai.ActionID);
                             SPDLOG_LOGGER_INFO(m_logger, "☆ 新增报警信息,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸,{}", 
                             pIll->ChannelID, pIll->RoomID, pIll->CameraID, actionName, ai.ActionDes, ai.listBbox.size(), ai.FaceIDList.size(), ai.ImageInfo);
                         }
@@ -402,7 +402,7 @@ void FuncIllegalInvasion::task()
                 }
             }
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
     }
 
 }

+ 4 - 4
SecurePlayAuxServer/Application/FuncOnAndOffJob.cpp

@@ -270,7 +270,7 @@ void FuncOnAndOffJob::task()
         if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
         {
             /* 休眠一段时间 */
-            std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
@@ -290,7 +290,7 @@ void FuncOnAndOffJob::task()
         if(!getCurrentFrequencyInfo(m_funcThreadInfo.ChannelID, m_nowChnDetecRule))
         {
             SPDLOG_LOGGER_ERROR(m_logger, "获取当前频率信息失败, ChannelID:{}", m_funcThreadInfo.ChannelID);
-            std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
@@ -342,7 +342,7 @@ void FuncOnAndOffJob::task()
             {
                 if(alarm->RoomID == roomInfo.first)
                 {
-                    if(alarm->ActionID == g_actionList.ActPersonNumber)
+                    if(alarm->ActionID == GVariable.ActPersonCount)
                     {
                         if(alarm->listBbox.size() > 0)
                         {
@@ -360,7 +360,7 @@ void FuncOnAndOffJob::task()
                 {
                     if(alarm->RoomID == roomInfo.first)
                     {
-                        if(alarm->ActionID == g_actionList.ActFace)
+                        if(alarm->ActionID == GVariable.ActFaceIdentify)
                         {
                             if(alarm->listPersonInfo.size() > 0)
                             {

+ 7 - 7
SecurePlayAuxServer/Application/FuncOrdinary.cpp

@@ -39,7 +39,7 @@ void FuncOrdinary::task()
         /* 判断是否在检测时间段内 */
         if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
         {
-            std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
@@ -165,7 +165,7 @@ void FuncOrdinary::task()
         }
         
         /* 休眠设置的时间 */
-        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
     }
 }
 
@@ -175,7 +175,7 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     /* 违禁品物品 */
     if(info.appFunction == AppFunction::APP_Contraband)
     {
-        if(timeDiffWithNow(info.EventTime) < GConfig.AppContraband_Time)
+        if(timeDiffWithNow(info.EventTime) < GVariable.AppContraband_Time)
         {
             return false;
         }
@@ -183,7 +183,7 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     /* 玩手机识别 */
     else if(info.appFunction == AppFunction::APP_PlayPhone)
     {
-        if(timeDiffWithNow(info.EventTime) < GConfig.AppPlayPhone)
+        if(timeDiffWithNow(info.EventTime) < GVariable.AppPlayPhone)
         {
             return false;
         }
@@ -191,7 +191,7 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     /* 老鼠识别 */
     else if(info.appFunction == AppFunction::APP_Mouse)
     {
-        if(timeDiffWithNow(info.EventTime) < GConfig.AppMouse)
+        if(timeDiffWithNow(info.EventTime) < GVariable.AppMouse)
         {
             return false;
         }
@@ -199,7 +199,7 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     /* 未戴口罩识别 */
     else if(info.appFunction == AppFunction::APP_NoMask)
     {
-        if(timeDiffWithNow(info.EventTime) < GConfig.AppMask)
+        if(timeDiffWithNow(info.EventTime) < GVariable.AppMask)
         {
             return false;
         }
@@ -207,7 +207,7 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     /* 疲劳检测 */
     else if(info.appFunction == AppFunction::APP_Fatigue)
     {
-        if(timeDiffWithNow(info.EventTime) < GConfig.AppTired_Time)
+        if(timeDiffWithNow(info.EventTime) < GVariable.AppTired_Time)
         {
             return false;
         }

+ 3 - 3
SecurePlayAuxServer/Application/FuncPersonOnWork.cpp

@@ -51,7 +51,7 @@ void FuncPersonOnWork::task()
         /* 判断是否在检测时间段内 */
         if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
         {
-            std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
@@ -111,7 +111,7 @@ void FuncPersonOnWork::task()
                 it->MinNum = it->listPersonInfo.size();
             }
             /* 判断是否需要写入数据库,一定时间写入一次,默认是10分钟写一次 */
-            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GConfig.AppUpdateOnWorkTimeInterval_Time)
+            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GVariable.AppUpdateOnWorkTimeInterval_Time)
             {
                 /* 写入数据库 */
                 if(m_fromWebAPI->insertOnWorkInfo(*it))
@@ -130,7 +130,7 @@ void FuncPersonOnWork::task()
             }
             ++it;
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
     }
 
 }

+ 1 - 1
SecurePlayAuxServer/Application/FuncRegionalPerson.cpp

@@ -145,7 +145,7 @@ void FuncRegionalPersonCount::task()
     
     while (m_bRunning)
     {
-        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
         /* 更新线程信息,并判断是否需要退出 */
         GThreadInfo.updateFuncInfo(m_funcThreadInfo);
         if( (m_funcThreadInfo.appFunction == AppFunction::APP_NONE) ||

+ 5 - 1
SecurePlayAuxServer/CMakeLists.txt

@@ -14,6 +14,7 @@ file(GLOB LOCAL_SRC
     ${CMAKE_SOURCE_DIR}/External/common/Thread/*.cpp
     ${CMAKE_SOURCE_DIR}/External/module/CurlHttp/*.cpp
     ${CMAKE_SOURCE_DIR}/External/module/ThreadPool/*.cpp
+    ${CMAKE_SOURCE_DIR}/External/module/mqtt/*.cpp
     
     ${LHQLog_SOURCE_DIRS}/*.cpp
     ${LHHTTPAPI_SOURCE_DIRS}/*.cpp
@@ -40,6 +41,7 @@ target_include_directories(${loaclExeName} PRIVATE
     ${CMAKE_SOURCE_DIR}/External/module/CurlHttp
     ${CMAKE_SOURCE_DIR}/External/module/RingQueue
     ${CMAKE_SOURCE_DIR}/External/module/ThreadPool
+    ${CMAKE_SOURCE_DIR}/External/module/mqtt
 
     ${LHQLog_INCLUDE_DIRS}
     ${LHHTTPAPI_SOURCE_DIRS}
@@ -47,6 +49,7 @@ target_include_directories(${loaclExeName} PRIVATE
     ${CURL_INCLUDE_DIR}
     ${spdlog_INCLUDE_DIR}
     ${hiredis_INCLUDE_DIR}
+    ${qmqtt_INCLUDE_DIR}
 )
 
 
@@ -54,7 +57,7 @@ target_include_directories(${loaclExeName} PRIVATE
 target_link_libraries(${loaclExeName} PRIVATE
     # Qt5::Widgets
     Qt5::Core
-    # Qt5::Network
+    Qt5::Network
     # Qt5::Sql
 )
 #链接外部库
@@ -64,6 +67,7 @@ target_link_libraries(${loaclExeName} PRIVATE
     ${hiredis_LIBRARY}
     ${CURL_LIBRARY}
     ${spdlog_LIBRARY}
+    ${qmqtt_LIBRARY}
 )
 
 #连接stdc++fs库,如果编译器版本低于GCC9.0,则需要连接这个库

+ 211 - 31
SecurePlayAuxServer/GlobalInfo/GlobalConfig.cpp

@@ -1,8 +1,70 @@
 #include "GlobalConfig.h"
 #include <QSettings>
+#include <QCoreApplication>
 
 #include "spdlog/spdlog.h"
 
+#include "GlobalVariable.h"
+
+
+GlobalVariable::GlobalVariable()
+{
+    ThreadSleepMS = 300;
+
+    ActFaceIdentify.clear();
+    ActPersonCount.clear();
+    ActContraband.clear();
+    ActPlayPhone.clear();
+}
+
+std::string GlobalVariable::getActionName(const std::string& actionID) 
+{
+    std::string actionName;
+    mutexRW.lockForRead();
+    auto it = m_mapAction.find(actionID);
+    if(it != m_mapAction.end()) {
+        actionName = it->second;
+    }
+    mutexRW.unlock();
+    return actionName;
+}
+
+/* 设置算法名称和算法ID对应关系,没有算法不会添加 */
+void GlobalVariable::setActionName(const std::map<std::string, std::string>& mapAction)
+{
+    mutexRW.lockForWrite();
+    for(const auto& it : m_mapAction)
+    {
+        auto it0 = mapAction.find(it.first);
+        if(it0 != mapAction.end())
+        {
+            m_mapAction[it.second] = it0->second;
+        }
+    }
+    mutexRW.unlock();
+}
+
+/* 通过不带后缀的算法ID获取完整的算法ID,后缀通过“-”连接 */
+std::string GlobalVariable::getFullActionID(const std::string& actionID)
+{
+    std::string fullActionID;
+    for(const auto& it : m_mapAction)
+    {
+        /* 去掉“-”以及后面的字符串 */
+        auto tmpStr = it.first;
+        auto pos = tmpStr.find("-");
+        if(pos != std::string::npos)
+        {
+            tmpStr = tmpStr.substr(0, pos);
+        }
+        if(tmpStr == actionID)
+        {
+            fullActionID = it.first;
+            break;
+        }
+    }
+    return fullActionID;
+}
 
 /* ====================================================================================
  * **************************    GlobalConfig成员函数    ******************************
@@ -12,12 +74,48 @@
 
 GlobalConfig::GlobalConfig()
 {
-    ThreadSleepMS = 300;
+    
 }
 
 
-/* 读取配置文件 */
-bool GlobalConfig::readConfig(const QString& strConfigFile)
+/* 初始化服务 */
+void GlobalConfig::initService()
+{
+    /* 读取基础配置文件 */
+    QString strBaseConfig = QCoreApplication::applicationDirPath() + "/config/BaseConfig.ini";
+    if(!GConfig.readBaseConfig(strBaseConfig))
+    {
+        /* 读取配置文件失败,直接退出程序 */
+        SPDLOG_ERROR("读取配置文件失败! 退出程序,{}", strBaseConfig.toStdString());
+        exit(-1);
+    }
+    printBaseConfig();
+
+    /* 读取算法配置 */
+    QString strAlgorithmConfig = QCoreApplication::applicationDirPath() + "/config/Actions.ini";
+    if(!GConfig.readAlgorithmConfig(strAlgorithmConfig))
+    {
+        /* 读取配置文件失败,直接退出程序 */
+        SPDLOG_ERROR("读取配置文件失败! 退出程序,{}", strAlgorithmConfig.toStdString());
+        exit(-1);
+    }
+    printAlgorithmConfig();
+
+    /* 读取应用配置文件 */
+    QString strAppConfig = QCoreApplication::applicationDirPath() + "/config/AppConfig.ini";
+    if(!GConfig.readAppConfig(strAppConfig))
+    {
+        /* 读取配置文件失败,直接退出程序 */
+        SPDLOG_ERROR("读取配置文件失败! 退出程序,{}", strAppConfig.toStdString());
+        exit(-1);
+    }
+    printAppConfig();
+
+    SPDLOG_INFO("========================================================");
+}
+
+/* 读取基础配置文件 */
+bool GlobalConfig::readBaseConfig(const QString& strConfigFile)
 {
     if(strConfigFile.isEmpty())
     {
@@ -28,49 +126,131 @@ bool GlobalConfig::readConfig(const QString& strConfigFile)
     QSettings settings(strConfigFile, QSettings::IniFormat);
     settings.setIniCodec("UTF-8");
 
-    settings.beginGroup("System");
+    /* 读取WebAPI配置 */
+    settings.beginGroup("WebAPI");
+    m_webAPIUrl = settings.value("ServerURL", "").toString();
+    m_webAPIKey = settings.value("ServerKey", "").toString();
+    settings.endGroup();
+
+    /* 读取Redis配置 */
+    settings.beginGroup("Redis");
+    m_redisIP = settings.value("URL", "").toString().toStdString();
+    m_redisPort = settings.value("Port", 0).toInt();
+    m_redisPWD = settings.value("Password", "").toString().toStdString();
+    settings.endGroup();
+
+    /* 读取SuperBrain配置 */
+    settings.beginGroup("SuperBrain");
+    m_superBrainUrl = settings.value("URL", "").toString().toStdString();
+    m_superBrainAppKey = settings.value("AppKey", "").toString().toStdString();
+    m_superBrainAppSecret = settings.value("AppSecret", "").toString().toStdString();
+    settings.endGroup();
 
-    AppUpdateOnWorkTimeInterval_Time = settings.value("WorkOnInfoSecond", 600).toInt();  /* 更新在岗信息的时间间隔 */
-    AppPeopleOnWork_Time = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
-    AppContraband_Time = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
-    AppBadMan_Time = settings.value("APPBADMAN", 50).toInt();                     /* 非法入侵 */
-    AppTired_Time = settings.value("APPTIRED", 50).toInt();                       /* 疲劳检测时间 */
-    AppPeopleCont = settings.value("APPPEPOLECONT", 50).toInt();             /* 人员聚集时间 */
-    AppPlayPhone = settings.value("APPPLAYPHONE", 50).toInt();               /* 玩手机识别 */
-    AppMouse = settings.value("APPMOUSE", 50).toInt();                       /* 手势识别 */
-    AppMask = settings.value("APPMASK", 5).toInt();                         /* 戴口罩识别 */
+    return true;
+}
 
-    CheckSet = settings.value("CHECKSET", 300).toInt();                       /* 服务端多久检测一次配置 */
-    EventTimeValid = settings.value("EventTimeValid", 300).toInt();           /* 事件时间有效期 */
+/* 打印基础配置文件 */
+void GlobalConfig::printBaseConfig()
+{
+    SPDLOG_INFO("========================================================");
+    SPDLOG_INFO("WebAPI URL:            {}", m_webAPIUrl.toStdString());
+    SPDLOG_INFO("WebAPI Key:            {}", m_webAPIKey.toStdString());
+    SPDLOG_INFO("--------------------------------------------------------");
+    SPDLOG_INFO("Redis IP:              {}", m_redisIP);
+    SPDLOG_DEBUG("Redis Port:           {}", m_redisPort);
+    SPDLOG_DEBUG("Redis Password:       {}", m_redisPWD);
+    SPDLOG_INFO("--------------------------------------------------------");
+    SPDLOG_INFO("SuperBrain URL:        {}", m_superBrainUrl);
+    SPDLOG_DEBUG("SuperBrain AppKey:    {}", m_superBrainAppKey);
+    SPDLOG_DEBUG("SuperBrain AppSecret: {}", m_superBrainAppSecret);
+}
 
-    Key = settings.value("Key").toString().toStdString();                           /* Key */
-    Secret = settings.value("Secret").toString().toStdString();                     /* Secret */
 
+/* 读取算法配置文件 */
+bool GlobalConfig::readAlgorithmConfig(const QString& strConfigFile)
+{
+    if(strConfigFile.isEmpty())
+    {
+        SPDLOG_ERROR("读取配置文件失败! 配置文件名为空");
+        return false;
+    }
+    // SPDLOG_DEBUG("读取配置文件: {}", strConfigFile.toStdString());
+    QSettings settings(strConfigFile, QSettings::IniFormat);
+    settings.setIniCodec("UTF-8");
+
+    settings.beginGroup("Actions");
+    GVariable.ActFaceIdentify = settings.value("FaceIdentify", "").toString().toStdString();      /* 人脸识别算法ID */
+    GVariable.ActPersonCount = settings.value("PersonCount", "").toString().toStdString();        /* 人员计数算法ID */
+    GVariable.ActPlayPhone = settings.value("PlayPhone", "").toString().toStdString();            /* 玩手机算法ID */
+    GVariable.ActContraband = settings.value("Contraband", "").toString().toStdString();          /* 违禁品算法ID */
     settings.endGroup();
 
-    if(Key.empty() || Secret.empty())
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.ActFaceIdentify, "人脸识别"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.ActPersonCount, "人员计数"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.ActPlayPhone, "玩手机识别"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.ActContraband, "违禁品检测"));
+
+    return true;
+}
+
+/* 打印算法配置文件 */
+void GlobalConfig::printAlgorithmConfig()
+{
+    SPDLOG_DEBUG("========================================================");
+    SPDLOG_DEBUG("人脸识别算法ID:       {}", GVariable.ActFaceIdentify);
+    SPDLOG_DEBUG("人员计数算法ID:       {}", GVariable.ActPersonCount);
+    SPDLOG_DEBUG("玩手机算法ID:         {}", GVariable.ActPlayPhone);
+    SPDLOG_DEBUG("违禁品算法ID:         {}", GVariable.ActContraband);
+}
+
+
+/* 读取配置文件 */
+bool GlobalConfig::readAppConfig(const QString& strConfigFile)
+{
+    if(strConfigFile.isEmpty())
     {
-        SPDLOG_ERROR("读取配置文件失败! Key或Secret为空");
+        SPDLOG_ERROR("读取配置文件失败! 配置文件名为空");
         return false;
     }
+    // SPDLOG_DEBUG("读取配置文件: {}", strConfigFile.toStdString());
+    QSettings settings(strConfigFile, QSettings::IniFormat);
+    settings.setIniCodec("UTF-8");
+
+    settings.beginGroup("System");
+
+    GVariable.AppUpdateOnWorkTimeInterval_Time = settings.value("WorkOnInfoSecond", 600).toInt();  /* 更新在岗信息的时间间隔 */
+    GVariable.AppPeopleOnWork_Time = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
+    GVariable.AppContraband_Time = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
+    GVariable.AppBadMan_Time = settings.value("APPBADMAN", 50).toInt();                     /* 非法入侵 */
+    GVariable.AppTired_Time = settings.value("APPTIRED", 50).toInt();                       /* 疲劳检测时间 */
+    GVariable.AppPeopleCont = settings.value("APPPEPOLECONT", 50).toInt();             /* 人员聚集时间 */
+    GVariable.AppPlayPhone = settings.value("APPPLAYPHONE", 50).toInt();               /* 玩手机识别 */
+    GVariable.AppMouse = settings.value("APPMOUSE", 50).toInt();                       /* 手势识别 */
+    GVariable.AppMask = settings.value("APPMASK", 5).toInt();                         /* 戴口罩识别 */
+
+    GVariable.CheckSet = settings.value("CHECKSET", 300).toInt();                       /* 服务端多久检测一次配置 */
+    GVariable.EventTimeValid = settings.value("EventTimeValid", 300).toInt();           /* 事件时间有效期 */
+
+    settings.endGroup();
 
     return true;
 }
 
 
 /* 打印读取到的值 */
-void GlobalConfig::printValue()
-{
-    SPDLOG_INFO("APPPEPOLEONWORK:   {}", AppPeopleOnWork_Time);
-    SPDLOG_INFO("APPBADTHING:       {}", AppContraband_Time);
-    SPDLOG_INFO("APPBADMAN:         {}", AppBadMan_Time);
-    SPDLOG_INFO("APPTIRED:          {}", AppTired_Time);
-    SPDLOG_INFO("APPPEOPLECONT:     {}", AppPeopleCont);
-    SPDLOG_INFO("APPPLAYPHONE:      {}", AppPlayPhone);
-    SPDLOG_INFO("APPMOUSE:          {}", AppMouse);
-    SPDLOG_INFO("APPMASK:           {}", AppMask);
-    SPDLOG_INFO("CHECKSET:          {}", CheckSet);
-    SPDLOG_INFO("EventTimeValid:    {}", EventTimeValid);
+void GlobalConfig::printAppConfig()
+{
+    SPDLOG_INFO("========================================================");
+    SPDLOG_INFO("APPPEPOLEONWORK:   {}", GVariable.AppPeopleOnWork_Time);
+    SPDLOG_INFO("APPBADTHING:       {}", GVariable.AppContraband_Time);
+    SPDLOG_INFO("APPBADMAN:         {}", GVariable.AppBadMan_Time);
+    SPDLOG_INFO("APPTIRED:          {}", GVariable.AppTired_Time);
+    SPDLOG_INFO("APPPEOPLECONT:     {}", GVariable.AppPeopleCont);
+    SPDLOG_INFO("APPPLAYPHONE:      {}", GVariable.AppPlayPhone);
+    SPDLOG_INFO("APPMOUSE:          {}", GVariable.AppMouse);
+    SPDLOG_INFO("APPMASK:           {}", GVariable.AppMask);
+    SPDLOG_INFO("CHECKSET:          {}", GVariable.CheckSet);
+    SPDLOG_INFO("EventTimeValid:    {}", GVariable.EventTimeValid);
 }
 
 /* 添加通道信息 */

+ 122 - 21
SecurePlayAuxServer/GlobalInfo/GlobalConfig.h

@@ -2,7 +2,86 @@
 #define GLOBALCONFIG_H
 
 #include <QString>
-#include "GlobalVariable.h"
+#include <QReadWriteLock>
+#include <map>
+
+#define GVariable GlobalVariable::getInstance()
+
+/**
+ * @brief 全局应用使用到的变量
+ * 
+ */
+class GlobalVariable
+{
+    friend class GlobalConfig;
+
+    GlobalVariable();
+    GlobalVariable(const GlobalVariable& other) = delete;
+    GlobalVariable& operator=(const GlobalVariable& other) = delete;
+
+public:
+    ~GlobalVariable() {}
+    static GlobalVariable& getInstance()
+    {
+        static GlobalVariable gv;
+        return gv;
+    }
+
+    int AppUpdateOnWorkTimeInterval_Time;   /* 更新在岗信息的时间间隔 */
+    int AppPeopleOnWork_Time;               /* 离岗时间 */
+    int AppContraband_Time;                 /* 违禁物品出现的时间 */
+    int AppBadMan_Time;                     /* 非法入侵超时时间 */
+    int AppTired_Time;                      /* 疲劳检测时间 */
+    int AppPeopleCont;                      /* 区域人员统计 */
+    int AppPlayPhone;                       /* 玩手机识别 */
+    int AppMouse;                           /* 老鼠识别 */
+    int AppMask;                            /* 戴口罩识别 */
+
+    int CheckSet;                           /* 服务端多久检测一次配置 */
+    int EventTimeValid;                     /* 事件时间有效期 */
+
+    int ThreadSleepMS;                      /* 任务线程休眠时间,单位是ms */
+    const int CheckDeviceTime = 20;         /* 从超脑平台检测设备的时间间隔,单位是秒 */
+
+    /* 算法ID,通过这个识别从超脑平台获取到的算法,这个算法ID是全的,带有后缀的 */
+    /* 人脸识别算法ID */
+    std::string ActFaceIdentify;
+    /* 人员统计算法ID */
+    std::string ActPersonCount;
+    /* 违禁品算法ID */
+    std::string ActContraband;
+    /* 玩手机算法ID */
+    std::string ActPlayPhone;
+    /* 疲劳检测算法ID */
+    std::string ActFatigueDetection;
+    /* 睡岗识别算法ID */
+    std::string ActSleep;
+    /* 老鼠检测 */
+    std::string ActMouseDetect;
+    /* 未戴口罩识别 */
+    std::string ActNoMask;
+    /* 摔倒识别 */
+    std::string ActAllDown;
+    /* 动物识别 */
+    std::string ActAnimalDetect;
+
+    QReadWriteLock mutexRW;               /* 读写锁 */
+    
+
+    std::string getActionName(const std::string& actionID);
+    /* 设置算法名称和算法ID对应关系,没有算法不会添加 */
+    void setActionName(const std::map<std::string, std::string>& mapAction);
+    /* 通过不带后缀的算法ID获取完整的算法ID,后缀通过“-”连接 */
+    std::string getFullActionID(const std::string& actionID);
+    
+
+private:
+    std::map<std::string, std::string> m_mapAction;     /* 算法ID和算法名称的对应关系,算法ID是完整的ID */
+
+};
+
+
+
 
 /* ====================================================================================
  * *****************************    GlobalConfig   ***********************************
@@ -29,28 +108,38 @@ public:
         return gc;
     }
 
-    /* 读取配置文件 */
-    bool readConfig(const QString& strConfigFile);
-    /* 打印读取到的值 */
-    void printValue();
-    
-    int AppUpdateOnWorkTimeInterval_Time;   /* 更新在岗信息的时间间隔 */
-    int AppPeopleOnWork_Time;               /* 离岗时间 */
-    int AppContraband_Time;                 /* 违禁物品出现的时间 */
-    int AppBadMan_Time;                     /* 非法入侵超时时间 */
-    int AppTired_Time;                      /* 疲劳检测时间 */
-    int AppPeopleCont;                      /* 区域人员统计 */
-    int AppPlayPhone;                       /* 玩手机识别 */
-    int AppMouse;                           /* 老鼠识别 */
-    int AppMask;                            /* 戴口罩识别 */
+    /* 初始化服务 */
+    void initService();
 
-    int CheckSet;               /* 服务端多久检测一次配置 */
-    int EventTimeValid;         /* 事件时间有效期 */
+    /* 读取基础配置文件 */
+    bool readBaseConfig(const QString& strConfigFile);
+    /* 打印基础配置文件 */
+    void printBaseConfig();
 
-    int ThreadSleepMS;          /* 任务线程休眠时间,单位是ms */
+    /* 读取算法配置文件 */
+    bool readAlgorithmConfig(const QString& strConfigFile);
+    /* 打印算法配置文件 */
+    void printAlgorithmConfig();
+    
+    /* 读取应用配置文件 */
+    bool readAppConfig(const QString& strConfigFile);
+    /* 打印读取到的值 */
+    void printAppConfig();
+
+    /* 获取webapi信息 */
+    QString webapiUrl() { return m_webAPIUrl; }
+    QString webapiKey() { return m_webAPIKey; }
+    QString webapiAppType() { return m_webAPIAppType; }
+    /* 获取Redis信息 */
+    std::string redisIP() { return m_redisIP; }
+    int redisPort() { return m_redisPort; }
+    std::string redisPWD() { return m_redisPWD; }
+    /* 获取超脑信息 */
+    std::string superBrainUrl() { return m_superBrainUrl; }
+    std::string superBrainAppKey() { return m_superBrainAppKey; }
+    std::string superBrainAppSecret() { return m_superBrainAppSecret; }
 
-    std::string Key;            /* Key */
-    std::string Secret;         /* Secret */
+    
 
 public:
     /* 添加通道信息 */
@@ -74,7 +163,19 @@ private:
     std::map<int, std::string> m_mapChannelName;        /* 通道名称 */
     /* 摄像机名称 */
     QReadWriteLock m_rwLockCamInfo;                     /* 读写锁 */
-    std::map<int, std::string> m_mapCameraName;        /* 摄像机名称 */
+    std::map<int, std::string> m_mapCameraName;         /* 摄像机名称 */
+
+    QString m_webAPIUrl;                                /* WebAPI的URL */
+    QString m_webAPIKey;                                /* WebAPI的Key */
+    const QString m_webAPIAppType = "SPSS";             /* WebAPI的Secret */
+
+    std::string m_redisIP;                              /* Redis的IP */
+    int m_redisPort;                                    /* Redis的端口 */
+    std::string m_redisPWD;                             /* Redis的密码 */
+
+    std::string m_superBrainUrl;                          /* 超脑的URL */
+    std::string m_superBrainAppKey;                       /* 超脑的AppKey */
+    std::string m_superBrainAppSecret;                    /* 超脑的AppSecret */
  };
 
 

+ 56 - 115
SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.cpp

@@ -1,4 +1,5 @@
 #include "GlobalFuncThread.h"
+#include "GlobalConfig.h"
 
 #include "spdlog/spdlog.h"
 
@@ -299,7 +300,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         return false;
     }
     /* 人脸识别算法(人员在岗识别、非法入侵检测需要) */
-    if(info.ActionID == g_actionList.ActFace)
+    if(info.ActionID == GVariable.ActFaceIdentify)
     {
         /* 人员在岗识别 */
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_OnWork);
@@ -315,7 +316,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 人员计数 */
-    else if (info.ActionID == g_actionList.ActPersonNumber)
+    else if (info.ActionID == GVariable.ActPersonCount)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Regional);
         if(pFuncThreadInfo != nullptr)
@@ -324,7 +325,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 违禁物品 */
-    else if (info.ActionID == g_actionList.ActContraband)
+    else if (info.ActionID == GVariable.ActContraband)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Contraband);
         if(pFuncThreadInfo != nullptr)
@@ -333,7 +334,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 玩手机 */
-    else if (info.ActionID == g_actionList.ActPlayPhone)
+    else if (info.ActionID == GVariable.ActPlayPhone)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_PlayPhone);
         if(pFuncThreadInfo != nullptr)
@@ -342,7 +343,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 睡岗识别 */
-    else if (info.ActionID == g_actionList.ActSleep)
+    else if (info.ActionID == GVariable.ActSleep)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
         if(pFuncThreadInfo != nullptr)
@@ -351,7 +352,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 疲劳检测 */
-    else if(info.ActionID == g_actionList.ActFatigueDetection)
+    else if(info.ActionID == GVariable.ActFatigueDetection)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
         if(pFuncThreadInfo != nullptr)
@@ -360,7 +361,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 动物识别 */
-    else if (info.ActionID == g_actionList.ActAnimalDetect)
+    else if (info.ActionID == GVariable.ActAnimalDetect)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
         if(pFuncThreadInfo != nullptr)
@@ -369,7 +370,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 老鼠识别 */
-    else if (info.ActionID == g_actionList.ActMouseDetect)
+    else if (info.ActionID == GVariable.ActMouseDetect)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
         if(pFuncThreadInfo != nullptr)
@@ -378,7 +379,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 口罩识别 */
-    else if (info.ActionID == g_actionList.ActMask)
+    else if (info.ActionID == GVariable.ActNoMask)
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_NoMask);
         if(pFuncThreadInfo != nullptr)
@@ -517,6 +518,12 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
     /* 解出这条信息里包含几个App,AppType按位计算,总共8个应用信息 */
     for(int i = 0; i < 8; ++i)
     {
+        FuncThreadInfo* fa = new FuncThreadInfo;
+        fa->ChannelID = func.ChannelID;
+        fa->StartTime = func.StartTime;
+        fa->EndTime = func.EndTime;
+        fa->RunState = RunTimeState::RUN_STATE_NONE;
+
         if(func.AppType & 0x01)
         {
             /* 查找有没有这个应用 */
@@ -528,12 +535,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_OnWork;
             fa->strFunctionName = "人员在岗识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if(func.AppType & 0x02)
@@ -546,12 +549,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_Contraband;
             fa->strFunctionName = "违禁品识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x04)
@@ -564,12 +563,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_Illegal;
             fa->strFunctionName = "非法入侵检测";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x08)
@@ -582,12 +577,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_Fatigue;
             fa->strFunctionName = "疲劳检测";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x10)
@@ -600,12 +591,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_Regional;
             fa->strFunctionName = "区域人员检测";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x20)
@@ -618,12 +605,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_Mouse;
             fa->strFunctionName = "老鼠识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x40)
@@ -636,12 +619,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_PlayPhone;
             fa->strFunctionName = "玩手机识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x80)
@@ -654,12 +633,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_NoMask;
             fa->strFunctionName = "未戴口罩识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
         else if (func.AppType & 0x0100)
@@ -672,12 +647,8 @@ bool GlobalThreadInfo::addFuncThreadInfo(const AppAndTimeInfo& func)
                 pFuncThreadInfo->EndTime = func.EndTime;
                 continue;
             }
-            FuncThreadInfo* fa = new FuncThreadInfo;
-            fa->ChannelID = func.ChannelID;
             fa->appFunction = AppFunction::APP_AllDown;
             fa->strFunctionName = "摔倒识别";
-            fa->StartTime = func.StartTime;
-            fa->EndTime = func.EndTime;
             m_listFuncThreadInfo.push_back(fa);
         }
     }
@@ -703,105 +674,57 @@ bool GlobalThreadInfo::addActionInfo(const ActionInfo& info)
         return false;
     }
     /* 人脸识别算法(人员在岗识别、非法入侵检测需要) */
-    if(info.ActionID == g_actionList.ActFace)
+    if(info.ActionID == GVariable.ActFaceIdentify)
     {
         /* 人员在岗识别 */
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_OnWork);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_OnWork);
         /* 非法入侵检测 */
-        pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Illegal);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Illegal);
     }
     /* 人员计数 */
-    else if (info.ActionID == g_actionList.ActPersonNumber)
+    else if (info.ActionID == GVariable.ActPersonCount)
     {
         /* 区域人员检测(人员计数?) */
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Regional);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Regional);
         /* 非法入侵检测 */
-        pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Illegal);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Illegal);
         /* 人员在岗识别 */
-        pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_OnWork);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_OnWork);
     }
     /* 违禁物品 */
-    else if (info.ActionID == g_actionList.ActContraband)
+    else if (info.ActionID == GVariable.ActContraband)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Contraband);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Contraband);
     }
     /* 玩手机 */
-    else if (info.ActionID == g_actionList.ActPlayPhone)
+    else if (info.ActionID == GVariable.ActPlayPhone)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_PlayPhone);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_PlayPhone);
     }
     /* 睡岗识别 */
-    else if (info.ActionID == g_actionList.ActSleep)
+    else if (info.ActionID == GVariable.ActSleep)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Fatigue);
     }
     /* 疲劳检测 */
-    else if(info.ActionID == g_actionList.ActFatigueDetection)
+    else if(info.ActionID == GVariable.ActFatigueDetection)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Fatigue);
     }
     /* 动物识别 */
-    else if (info.ActionID == g_actionList.ActAnimalDetect)
+    else if (info.ActionID == GVariable.ActAnimalDetect)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Mouse);
     }
     /* 老鼠识别 */
-    else if (info.ActionID == g_actionList.ActMouseDetect)
+    else if (info.ActionID == GVariable.ActMouseDetect)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_Mouse);
     }
     /* 口罩识别 */
-    else if (info.ActionID == g_actionList.ActMask)
+    else if (info.ActionID == GVariable.ActNoMask)
     {
-        auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_NoMask);
-        if(pFuncThreadInfo != nullptr)
-        {
-            pFuncThreadInfo->addActionInfo(info);
-        }
+        setAppFunction(info, AppFunction::APP_NoMask);
     }
     else {
         SPDLOG_WARN("未知的算法ID: {}", info.ActionID);
@@ -850,8 +773,15 @@ void GlobalThreadInfo::setNoneCameraFuncStop()
     {
         if(it->listRoomCamActInfo.empty())
         {
+            if(it->RunState == RunTimeState::RUN_STATE_NONE)
+            {
+                SPDLOG_INFO("频道:{:<15} 功能:{:<20}房间信息为空,无需开启线程",it->strChannelName, it->strFunctionName);
+            }
+            else if(it->RunState == RunTimeState::RUN_STATE_RUN)
+            {
+                SPDLOG_INFO("频道:{:<10}功能:{:<20}房间信息为空,停止线程",it->strChannelName, it->strFunctionName);
+            }
             it->RunState = RunTimeState::RUN_STATE_STOP;
-            SPDLOG_INFO("《{}》房间信息为空,退出检测", it->strFunctionName);
         }
     }
 }
@@ -900,6 +830,17 @@ FuncThreadInfo* GlobalThreadInfo::findAppFunction(const FuncThreadInfo& func)
     return nullptr;
 }
 
+/* 设置应用信息 */
+void GlobalThreadInfo::setAppFunction(const ActionInfo& info, const AppFunction func)
+{
+    auto pFuncThreadInfo = findAppFunction(info.ChannelID, func);
+    if(pFuncThreadInfo != nullptr)
+    {
+        pFuncThreadInfo->addActionInfo(info);
+        pFuncThreadInfo->RunState = RunTimeState::RUN_STATE_INIT;
+    }
+}
+
 /* 设置线程状态 */
 void GlobalThreadInfo::setThreadState(FuncThreadInfo* pInfo, RunTimeState state)
 {

+ 2 - 0
SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.h

@@ -114,6 +114,8 @@ public:
     bool findAppFunction(const AppFunction func);
     FuncThreadInfo* findAppFunction(const int ChannelID, const AppFunction func);
     FuncThreadInfo* findAppFunction(const FuncThreadInfo& func);
+    /* 设置应用信息 */
+    inline void setAppFunction(const ActionInfo& info, const AppFunction func);
 
     /* 设置线程状态 */
     void setThreadState(FuncThreadInfo* pInfo, RunTimeState state);

+ 0 - 3
SecurePlayAuxServer/GlobalInfo/GlobalVariable.cpp

@@ -11,9 +11,6 @@
 int g_eventTimeVaild = 600;         /* 事件时间有效性,单位秒,超过这个时间就认为是无效数据 */
 
 
-
-ActionList g_actionList;            /* 全局算法列表 */
-
 /* ====================================================================================
  * ***************************    DeviceInfo成员函数    *******************************
  * ====================================================================================*/

+ 2 - 40
SecurePlayAuxServer/GlobalInfo/GlobalVariable.h

@@ -7,7 +7,7 @@
 #include <map>
 #include <mutex>
 #include <QDateTime>
-#include <QReadWriteLock>
+
 #include "nlohmann/json.hpp"
 
 
@@ -68,44 +68,6 @@ enum class Enum_RoomType
     ROOM_ALL = 3,               /* 所有房间 */
 };
 
-/**
- * @brief 全局算法列表,理论上算法ID是不会变的,但是现在好像是变化的,暂时还不知道从哪里区分
- * 
- */
-class ActionList
-{
-public:
-    /* 全局算法ID */
-    // std::mutex mutexActionID;             /* 算法ID的互斥锁 */
-    QReadWriteLock mutexRW;               /* 读写锁 */
-
-    std::string ActFace;                  /* 人脸识别 */
-    std::string ActPersonNumber;          /* 人员计数 */
-    std::string ActPlayPhone;             /* 玩手机 */
-    std::string ActContraband;            /* 违禁品物品 */
-    std::string ActSleep;                 /* 睡岗识别 */
-    std::string ActFatigueDetection;      /* 疲劳检测 */
-    std::string ActAnimalDetect;          /* 动物识别 */
-    std::string ActMouseDetect;           /* 老鼠识别 */
-    std::string ActMask;                  /* 口罩识别 */
-
-    std::map<std::string, std::string> mapAction;   /* 算法ID和算法名称的对应关系 */
-
-    ActionList() = default;
-
-    std::string getActionName(const std::string& actionID) {
-        std::string actionName;
-        mutexRW.lockForRead();
-        auto it = mapAction.find(actionID);
-        if(it != mapAction.end()) {
-            actionName = it->second;
-        }
-        mutexRW.unlock();
-        return actionName;
-    }
-};
-
-extern ActionList g_actionList;
 
 
 
@@ -151,7 +113,7 @@ struct DeviceInfo
     int DevicePort;             /* 设备端口 */
     std::string DeviceName;     /* 设备名称 */
     std::string DeviceIP;       /* 设备IP */
-    std::string DeviceSerial;   /* 设备序列号 */
+    std::string DeviceSerial;   /* 设备序列号,这里好像是IP */
     std::string DeviceType;     /* 设备类型 */
     std::string UserAccount;    /* 用户账号 */
     std::string UserPassword;   /* 用户密码 */

+ 6 - 3
SecurePlayAuxServer/GlobalInfo/UniversalFunc.cpp

@@ -2,6 +2,7 @@
 
 #include "spdlog/spdlog.h"
 #include "GlobalVariable.h"
+#include "GlobalConfig.h"
 
 /**
  * @brief 解析Redis的基础通用数据,不包含bBoxes数组数据
@@ -76,7 +77,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
                 /* 这一条Box数据报警了将其内容存储起来 */
                 alarmInfo.Is_Alarm = true;
                 /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
-                if(alarmInfo.ActionID == g_actionList.ActContraband)
+                if(alarmInfo.ActionID == GVariable.ActContraband)
                 {
                     /* 解析报警,取出报警类型 */
                     nJson label = it0["label"];
@@ -120,7 +121,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
             /* 添加报警信息的提示信息 */
             alarmInfo.listBbox = listBbox;
             /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
-            if( (alarmInfo.ActionID == g_actionList.ActContraband) && !labelList.empty() )
+            if( (alarmInfo.ActionID == GVariable.ActContraband) && !labelList.empty() )
             {
                 alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
                 SPDLOG_INFO("{}", alarmInfo.ActionDes);
@@ -135,7 +136,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
                 return;
             }
             /* 如果是人员报警,就存储人员报警信息 */
-            if(alarmInfo.ActionID == g_actionList.ActFace)
+            if(alarmInfo.ActionID == GVariable.ActFaceIdentify)
             {
                 nJson jsonArray = json0["personList"];
                 for(auto& it : jsonArray)
@@ -269,3 +270,5 @@ std::string getAppFunctionName(const AppFunction appID)
     return strRet;
 }
 
+
+

+ 145 - 131
SecurePlayAuxServer/SPAServer.cpp

@@ -8,6 +8,9 @@
 #include "UniversalFunc.h"
 #include "FuncOrdinary.h"
 #include "FuncIllegalInvasion.h"
+#include "FuncOnAndOffJob.h"
+#include "FuncRegionalPerson.h"
+
 #include "GlobalFuncThread.h"
 
 #include <QCoreApplication>
@@ -21,22 +24,13 @@ SPAServer::SPAServer()
         SPDLOG_ERROR("APAServer logger is nullptr");
         return;
     }
-
-    /* 读取全局的配置文件 */
-    QString strConfigFile = QCoreApplication::applicationDirPath() + "/config.ini";
-    if(!GConfig.readConfig(strConfigFile))
-    {
-        /* 读取配置文件失败,直接退出程序 */
-        return;
-    }
-    GConfig.printValue();
     
 
     m_threadRunning = true;
     /* 初始化WebAPI */
-    m_fromWebAPI.initWebApi("http://192.1.3.133:31000/v6/", "", "4c2f9fc91c22dd98331e47af2e2964f4");
+    // m_fromWebAPI.initWebApi("http://192.1.3.133:31000/v6/", "", "4c2f9fc91c22dd98331e47af2e2964f4");
     /* 模拟违禁品算法ID,后续需要动态调整 */
-    g_actionList.ActContraband = "OD210_026_005246_001-IZRTKyEx";
+    // GVariable.ActContraband = "OD210_026_005246_001-IZRTKyEx";
     
 }
 
@@ -49,16 +43,22 @@ SPAServer::~SPAServer()
 void SPAServer::startServer()
 {
     /* 添加获取基础信息的线程 */
-    // CPPTP.add_task(&SPAServer::threadFromSuperBrain, this);
+    CPPTP.add_task(&SPAServer::threadFromSuperBrain, this);
+    // threadFromSuperBrain();
+
+    /* 延时启动任务分配线程 */
+    std::this_thread::sleep_for(std::chrono::seconds(2));
+    /* 添加分配任务的线程 */
+    CPPTP.add_task(&SPAServer::threadDistribution, this);
 
     /* 测试Redis读取并解析数据线程 */
-    CameraThreadInfo info;
-    info.RedisIP = "172.16.36.80";
-    info.RedisPort = 32222;
-    info.RedisPWD = "Ff1z@TOFr^iwd%Ra";
-    info.DeviceID = 117;
-    info.vecAction.push_back("OD210_026_005246_001-IZRTKyEx");
-    g_actionList.ActContraband = "OD210_026_005246_001-IZRTKyEx";
+    // CameraThreadInfo info;
+    // info.RedisIP = "172.16.36.80";
+    // info.RedisPort = 32222;
+    // info.RedisPWD = "Ff1z@TOFr^iwd%Ra";
+    // info.DeviceID = 117;
+    // info.vecAction.push_back("OD210_026_005246_001-IZRTKyEx");
+    // GVariable.ActContraband = "OD210_026_005246_001-IZRTKyEx";
     // CPPTP.add_task(&SPAServer::threadFromRedis, this, info);
     // threadFromRedis(info);
 }
@@ -76,39 +76,84 @@ void SPAServer::threadFromSuperBrain()
     std::vector<AlgorithmInfo> vecAlgNewInfo;
     std::vector<DeviceInfo> vecDevNewInfo;
 
-    /* 获取一次token,后续失效了再获取 */
-    m_fromSuperBrain.getToken();
+    /* 初始化WebAPI */
+    if(!m_fromWebAPIUseSB.initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType()))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "threadFromSuperBrain线程初始化WebAPI失败");
+        return;
+    }
+
+    /* 初始化SuperBrain */
+    m_fromSuperBrain.initSuperBrain(GConfig.superBrainUrl(), GConfig.superBrainAppKey(), GConfig.superBrainAppSecret());
+    /* 获取一次Token,这玩意好像不是必须的 */
+    if(!m_fromSuperBrain.getToken())
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "FromSuperBrain线程获取Token失败");
+        return;
+    }
+    
     while (m_threadRunning)
     {
-        SPDLOG_LOGGER_INFO(m_logger, "刷新算法和设备信息");
+        SPDLOG_LOGGER_INFO(m_logger, "----------------- 刷新算法和设备信息 -----------------");
         /* 先更新数据库的信息,防止从其他地方更改了数据库,这里没有刷新本地缓存 */
-        m_fromWebAPI.getAlgorithmInfo(m_vecEqmAlgInfo);
-        m_fromWebAPI.getDeviceInfo(m_vecEqmDevInfo);
-        m_fromWebAPI.getDeviceAlgorithmInfo(m_vecEqmDevInfo, m_listDevIDDelete);
+        m_fromWebAPIUseSB.getAlgorithmInfo(m_vecEqmAlgInfo);
+        m_fromWebAPIUseSB.getDeviceInfo(m_vecEqmDevInfo);
+        m_fromWebAPIUseSB.getDeviceAlgorithmInfo(m_vecEqmDevInfo, m_listDevIDDelete);
 
         /* 从超脑获取基础信息 */
-        m_fromSuperBrain.getTaskTypeList(vecAlgNewInfo);
+        // m_fromSuperBrain.getTaskTypeList(vecAlgNewInfo);
         m_fromSuperBrain.getDeviceList(vecDevNewInfo);
+        // SPDLOG_LOGGER_INFO(m_logger, "获取到的设备信息数量: {}", vecDevNewInfo.size());
 
-        /* 处理算法信息 */
-        bool algIsUpdate = processAlgorithmInfo(vecAlgNewInfo);
+        /* 将设备返回的算法ID替换成带有后缀的全ID */
+        checkAlgorithmID(vecDevNewInfo);
+        /* 处理算法信息,算法信息不需要在服务里处理了,在外部手动处理 */
+        // bool algIsUpdate = processAlgorithmInfo(vecAlgNewInfo);
         /* 处理设备信息 */
         bool devIsUpdate = processDeviceInfo(vecDevNewInfo);
+        if(!devIsUpdate)
+        {
+            SPDLOG_LOGGER_INFO(m_logger, "设备信息和算法信息没有更新");
+        }
 
         vecAlgNewInfo.clear();
         vecDevNewInfo.clear();
 
         /* 更新算法详细信息 */
         m_mutexActionInfo.lock();
-        m_fromWebAPI.getActionInfo(m_listActionInfo);
+        m_fromWebAPIUseSB.getActionInfo(m_listActionInfo);
         m_mutexActionInfo.unlock();
 
-        /* 10秒更新一次 */
-        std::this_thread::sleep_for(std::chrono::seconds(10));
+        /* 20秒更新一次 */
+        std::this_thread::sleep_for(std::chrono::seconds(GVariable.CheckDeviceTime));
     }
     SPDLOG_LOGGER_INFO(m_logger, "退出 fromSuperBrainThread 线程");
 }
 
+
+/* 替换算法ID为全ID */
+void SPAServer::checkAlgorithmID(std::vector<DeviceInfo>& vecDevInfo)
+{
+    /* 替换算法ID为全ID */
+    for(auto& dev : vecDevInfo)
+    {
+        for(auto act = dev.vecAlgorithmInfo.begin(); act != dev.vecAlgorithmInfo.end(); act++)
+        {
+            /* 替换算法ID为全ID */
+            std::string strFullID = GVariable.getFullActionID(act->ActionID);
+            if(strFullID.empty())
+            {
+                SPDLOG_LOGGER_INFO(m_logger, "未知的算法ID: {}", act->ActionID);
+                /* 删除算法ID */
+                // act = dev.vecAlgorithmInfo.erase(act);
+            }else {
+                /* 替换算法ID */
+                act->ActionID = strFullID;
+            }
+        }
+    }
+}
+
 /* 处理算法信息,返回值为true,说明有改变,需要重新读取 */
 bool SPAServer::processAlgorithmInfo(std::vector<AlgorithmInfo> vecNewAlgInfo)
 {
@@ -117,19 +162,19 @@ bool SPAServer::processAlgorithmInfo(std::vector<AlgorithmInfo> vecNewAlgInfo)
 
     /* 对比数据库表格信息,这里只有插入和删除,没有更新 */
     compareAlgorithmInfo(vecNewAlgInfo, vecAlgUpdate, vecAlgDelete);
-        
+    
     /* 更新数据库,先删除,再写入刷新 */
     bool isUpdate = false;
     if(vecAlgDelete.size() > 0)
     {
         SPDLOG_LOGGER_DEBUG(m_logger, "删除算法信息");
-        m_fromWebAPI.deleteAlgorithmInfo(vecAlgDelete);
+        m_fromWebAPIUseSB.deleteAlgorithmInfo(vecAlgDelete);
         isUpdate = true;
     }
     if(vecAlgUpdate.size() > 0)
     {
         SPDLOG_LOGGER_DEBUG(m_logger, "写入算法信息");
-        m_fromWebAPI.writeAlgorithmInfo(vecAlgUpdate);
+        m_fromWebAPIUseSB.writeAlgorithmInfo(vecAlgUpdate);
         isUpdate = true;
     }
 
@@ -212,53 +257,74 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
     /* 先删除多余的数据 */
     if(vecDevDelete.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "删除设备信息, 表: tActionCamer");
-        m_fromWebAPI.deleteDeviceInfo(vecDevDelete);
-        isUpdate = true;
+        if(m_fromWebAPIUseSB.deleteDeviceInfo(vecDevDelete))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到 tCamerInfo, 数量:{}",vecDevDelete.size());
+            isUpdate = true;
+        }
     }
     /* 更新数据 */
     if(vecDevUpdate.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息, 表: tActionCamer");
-        m_fromWebAPI.updateDeviceInfo(vecDevUpdate);
-        isUpdate = true;
+        if(m_fromWebAPIUseSB.updateDeviceInfo(vecDevUpdate))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息到 tCamerInfo, 数量:{}", vecDevUpdate.size());
+            isUpdate = true;
+        }
     }
     /* 插入数据 */
     if(vecDevInsert.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息, 表: tActionCamer");
-        m_fromWebAPI.insertDeviceInfo(vecDevInsert);
-        isUpdate = true;
+        if(m_fromWebAPIUseSB.insertDeviceInfo(vecDevInsert))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息到 tCamerInfo, 数量:{}", vecDevInsert.size());
+            isUpdate = true;
+        }
     }
 
+    // for(auto& it : vecNewDevInfo)
+    // {
+    //     for(auto& it0 : it.vecAlgorithmInfo)
+    //     {
+    //         SPDLOG_LOGGER_DEBUG(m_logger, "设备ID: {}, 算法ID: {}", it.DeviceID, it0.ActionID);
+    //     }
+    // }
+
     /*-------------------------------------------------------------------------
      ************* 处理设备和算子关联的表格,单独对比设备的算法信息 *************
      *------------------------------------------------------------------------*/
 
     /* 插入新的设备信息 */
-    if(vecDevInsert.size() > 0)
-    {
-        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表(tActionCamer)");
-        m_fromWebAPI.insertDeviceAlgorithmInfo(vecDevInsert);
-        isUpdate = true;
-    }
+    // if(vecDevInsert.size() > 0)
+    // {
+    //     if(m_fromWebAPIUseSB.insertDeviceAlgorithmInfo(vecDevInsert))
+    //     {
+    //         SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表(tActionCamer), 数量: {}", vecDevInsert.size());
+    //         isUpdate = true;
+    //     }
+    // }
 
     vecDevUpdate.clear();
     /* 对比现有的设备是否需要更新算法 */
     compareDeviceAlgorithmInfo(vecNewDevInfo, vecDevUpdate);
     if(vecDevUpdate.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表(tActionCamer), 更新设备数目:{}", vecDevUpdate.size());
-        m_fromWebAPI.updateDeviceAlgorithmInfo(vecDevUpdate);
+        if(m_fromWebAPIUseSB.updateDeviceAlgorithmInfo(vecDevUpdate))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表(tActionCamer), 更新设备数目:{}", vecDevUpdate.size());
+            isUpdate = true;
+        }
     }
     
     
     /* 删除tActionCamer表中消失的设备信息 */
     if(m_listDevIDDelete.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法(tActionCamer)");
-        m_fromWebAPI.deleteDeviceAlgorithmInfo(m_listDevIDDelete);
-        isUpdate = true;
+        if(m_fromWebAPIUseSB.deleteDeviceAlgorithmInfo(m_listDevIDDelete))
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法(tActionCamer), 数目: {}", m_listDevIDDelete.size());
+            isUpdate = true;
+        }
     }
 
 
@@ -377,70 +443,6 @@ void SPAServer::compareDeviceAlgorithmInfo(const std::vector<DeviceInfo>& vecNew
 
 
 
-/**
- * @brief 从Redis获取数据线程函数,这个是摄像机线程
- *        一个设备一个线程,这个线程的相关变量只在这个线程中使用
- *      (注意,这个函数未被使用,不从这里获取Redis数据)
- * @param info 
- */
-void SPAServer::threadFromRedis(const CameraThreadInfo& info)
-{
-    SPDLOG_LOGGER_INFO(m_logger, "开启 fromRedisThread 线程,设备ID:{}", info.DeviceID);
-    FromRedis fromRedis;
-    fromRedis.setRedisIPAndPort(info.RedisIP, info.RedisPort);
-    fromRedis.setRedisPassword(info.RedisPWD);
-    if(fromRedis.connectRedis())
-    {
-        SPDLOG_LOGGER_INFO(m_logger, "连接Redis成功");
-    }else {
-        SPDLOG_LOGGER_ERROR(m_logger, "连接Redis失败");
-        return;
-    }
-    CameraThreadInfo threadInfo = info;
-    // std::string strKey = "117:OD210_026_005246_001-IZRTKyEx";
-    /* 取出该设备的Key */
-    std::vector<std::string> vecKey;
-    for(const auto& it : info.vecAction)
-    {
-        std::string strKey = std::to_string(info.DeviceID) + ":" + it;
-        vecKey.push_back(strKey);
-    }
-    std::string strRetValue;
-    /* 进入线程循环 */
-    while (m_threadRunning)
-    {
-        /* 循环读取这个设备关联的算法信息 */
-        for(const auto& it : vecKey)
-        {
-            SPDLOG_LOGGER_INFO(m_logger, "读取Redis信息, Key: {}", it);
-            if( !fromRedis.getRedisString(it, strRetValue) )
-            {
-                continue;
-            }
-            SPDLOG_LOGGER_TRACE(m_logger, "Redis Value:\n{}", strRetValue);
-            /* 解析数据 */
-            AlarmInfo alarmInfo;
-            alarmInfo.ActionID = it.substr(it.find(":") + 1);
-            /* 解析数据 */
-            parseRedisBaseData(strRetValue, alarmInfo);
-            parseRedisBBoxesData(strRetValue, alarmInfo);
-            /* 信息时间有的效性判断,主要是记录Redis数据的有效性,是否长时间没有变化,排查错误时用的
-             * 如果数据长时间数据不变,那么超脑那里就挂了,写入日志 */
-            isEventTimeVaild(alarmInfo.EventTime);
-            
-            /* 是否需要写入EQM数据库判断
-             * 人员计数和区域人员检测需要多次判断,其他的直接写入即可 */
-            
-        }
-
-
-        std::this_thread::sleep_for(std::chrono::seconds(2));
-    }
-    
-    return;
-}
-
-
 /**
  * @brief 分派任务的线程
         1、 线程定时刷新房间和摄像机的关联关系,以及和算法Action的关联关系
@@ -455,26 +457,26 @@ void SPAServer::threadFromRedis(const CameraThreadInfo& info)
  */
 void SPAServer::threadDistribution()
 {
-    SPDLOG_LOGGER_INFO(m_logger, "开启分派任务线程");
+    SPDLOG_LOGGER_INFO(m_logger, "**************** 开启分派任务线程 ****************");
     /* 房间相机关联信息 */
     std::list<RoomCameraInfo> listRC;
     /* 存储获取到的应用和启用时间的信息 */
     std::list<AppAndTimeInfo> listAppAndTime;
-    /* 创建连接数据库实例 */
-    std::shared_ptr<FromWebAPI> fromWebAPI = std::make_shared<FromWebAPI>();
+
     /* 初始化WebAPI */
-    // fromWebAPI->initWebApi(const QString &url, const QString &serverIP, const QString &serID)
+    std::shared_ptr<FromWebAPI> pFromWebAPI = std::make_shared<FromWebAPI>();
+    pFromWebAPI->initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType());
 
     while (m_threadRunning)
     {
         /* ======================================================= */
         /* 更新通道名称和摄像机名称信息 */
         std::map<int, std::string> mapChannelName;
-        m_fromWebAPI.getChannelInfo(mapChannelName);
+        pFromWebAPI->getChannelInfo(mapChannelName);
         GConfig.setChannelInfo(mapChannelName);
 
         std::map<int, std::string> mapCameraName;
-        m_fromWebAPI.getCameraInfo(mapCameraName);
+        pFromWebAPI->getCameraInfo(mapCameraName);
         GConfig.setCameraInfo(mapCameraName);
 
         /* ======================================================= */
@@ -487,7 +489,7 @@ void SPAServer::threadDistribution()
 
         /* ======================================================= */
         /* 创建应用信息,根据从EQM数据库读取到的配置的应用信息创建 */
-        fromWebAPI->getAlarmAppInfo(listAppAndTime);
+        pFromWebAPI->getAlarmAppInfo(listAppAndTime);
         for(const auto& it : listAppAndTime)
         {
             /* 创建应用信息,如果已有该应用,就更新时间
@@ -508,7 +510,7 @@ void SPAServer::threadDistribution()
 
         /* 先获取EQM数据库信息,取出房间和摄像机关联信息,包括所在的频率 */
         m_mutexActionInfo.lock();
-        fromWebAPI->getActionInfo(m_listActionInfo);
+        pFromWebAPI->getActionInfo(m_listActionInfo);
         /* 将算法信息加入到不同的功能列表中,先清空功能对应的算法设备列表 */
         GThreadInfo.clearActionList();
         for(const auto& it : m_listActionInfo.getData())
@@ -521,15 +523,15 @@ void SPAServer::threadDistribution()
         m_mutexActionInfo.unlock();
 
         /* 开启线程 */
-        for(const auto& it0 : GThreadInfo.getList())
+        for(const auto& func : GThreadInfo.getList())
         {
-            if(it0->RunState == RunTimeState::RUN_STATE_INIT)
+            if(func->RunState == RunTimeState::RUN_STATE_INIT)
             {
                 /* 创建实例 */
-                FuncBase* pFunc = createFuncInstance(*it0);
+                FuncBase* pFunc = createFuncInstance(*func);
                 if(pFunc == nullptr)
                 {
-                    SPDLOG_LOGGER_ERROR(m_logger, "创建功能实例失败:{}", it0->strFunctionName);
+                    SPDLOG_LOGGER_ERROR(m_logger, "创建功能实例失败:{}", func->strFunctionName);
                     continue;
                 }
                 CPPTP.add_task(&FuncBase::thread_task, pFunc);
@@ -540,7 +542,7 @@ void SPAServer::threadDistribution()
         GThreadInfo.unlockRunFAI();
 
         /* 休眠n秒,默认应该是300秒 */
-        std::this_thread::sleep_for(std::chrono::seconds(GConfig.CheckSet));
+        std::this_thread::sleep_for(std::chrono::seconds(GVariable.CheckSet));
     }
 
     SPDLOG_LOGGER_INFO(m_logger, "分派任务线程退出");
@@ -571,6 +573,9 @@ FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
     else if(info.appFunction == AppFunction::APP_OnWork)
     {
         /* 人员在岗检测 */
+        auto tmpFunc = new FuncOnAndOffJob();
+        tmpFunc->setFuncThreadInfo(info);
+        pFunc = tmpFunc;
     }
     else if(info.appFunction == AppFunction::APP_Illegal)
     {
@@ -582,6 +587,9 @@ FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
     else if(info.appFunction == AppFunction::APP_Regional)
     {
         /* 区域人员检测 */
+        auto tmpFunc = new FuncRegionalPersonCount();
+        tmpFunc->setFuncThreadInfo(info);
+        pFunc = tmpFunc;
     }
 
     return pFunc;
@@ -605,14 +613,20 @@ void SPAServer::clearNoneFuncThreadInfo()
             else if((*it)->getApp() == AppFunction::APP_OnWork)
             {
                 /* 人员在岗检测 */
+                FuncOnAndOffJob* p = dynamic_cast<FuncOnAndOffJob*>(*it);
+                delete p;
             }
             else if((*it)->getApp() == AppFunction::APP_Illegal)
             {
                 /* 非法入侵 */
+                FuncIllegalInvasion* p = dynamic_cast<FuncIllegalInvasion*>(*it);
+                delete p;
             }
             else if((*it)->getApp() == AppFunction::APP_Regional)
             {
                 /* 区域人员检测 */
+                FuncRegionalPersonCount* p = dynamic_cast<FuncRegionalPersonCount*>(*it);
+                delete p;
             }
             it = m_listFuncBase.erase(it);
         }else {

+ 6 - 5
SecurePlayAuxServer/SPAServer.h

@@ -27,10 +27,13 @@ private:
     /*--------------------------------------------------------------------------------
      * 从基础平台获取算法信息和设备信息功能线程和所需要的函数,这里更新维护EQM数据库的tAction、
      * tCameraInfo、tActionCamera等表格
+     * 注:tAction不需要在服务里维护,在外部手动维护
      *-------------------------------------------------------------------------------*/
     /* 从基础平台获取算法信息和设备信息的线程函数 */
     void threadFromSuperBrain();
-    /* 处理算法信息,返回值为true,说明有改变,需要重新读取 */
+    /* 替换算法ID为全ID */
+    void checkAlgorithmID(std::vector<DeviceInfo>& vecDevInfo);
+    /* 处理算法信息,返回值为true,说明有改变,需要重新读取(不需要在服务里维护,手动配置) */
     bool processAlgorithmInfo(std::vector<AlgorithmInfo> vecNewAlgInfo);
     /* 处理设备信息,传入新获取到的值,返回true需要更新本地数据缓存 */
     bool processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo);
@@ -39,8 +42,6 @@ private:
     /* 对比设备和算法关联表是否需要更新 */
     void compareDeviceAlgorithmInfo(const std::vector<DeviceInfo>& vecNewInfo, std::vector<DeviceInfo>& vecDevUpdate);
 
-    /* 从Redis获取数据线程函数,这个是摄像机线程(注意,这个函数未被使用,不从这里获取Redis数据) */
-    void threadFromRedis(const CameraThreadInfo& info);
 
     /*--------------------------------------------------------------------------------
      * 分派任务的线程,这里是根据房间和摄像机的关联信息,给任务创建不同的功能线程
@@ -55,10 +56,10 @@ private:
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
 
-    bool m_threadRunning = true;                        /* 线程正在运行 */
+    std::atomic_bool m_threadRunning = true;                        /* 线程正在运行 */
 
     FromSuperBrain m_fromSuperBrain;
-    FromWebAPI m_fromWebAPI;
+    FromWebAPI m_fromWebAPIUseSB;                       /* 用于SuperBrain的WebAPI */
 
     /* 算法信息,这个就是tAction在内存中的数据,方便后续对比,程序启动的时候会先获取一份 */
     std::vector<AlgorithmInfo> m_vecEqmAlgInfo;

+ 11 - 8
SecurePlayAuxServer/common/LHLog/LHLogInit.cpp

@@ -40,10 +40,10 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
         auto sink_default = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
  
         /* 修改输出格式 */
-        sink_consolse->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] [%n] [%s %#] %v %$");
+        sink_consolse->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] [%n] [%s %#] %v%$");
         // sink_file->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%n%$] [%^%l%$] %s %#: %v");
         sink_custom->set_pattern("%v");
-        sink_default->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] [%s %#] %v %$");
+        sink_default->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] [%s %#] %v%$");
 
         /* 日志输出方向,终端和文件 */
         std::vector<spdlog::sink_ptr> sinks;
@@ -62,14 +62,16 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
         // }
         /* 创建一个标准输出 */
         auto logger_main = std::make_shared<spdlog::logger>("main",begin(sinks),end(sinks));
-        /* 创建一个FromSuperBrain Logger */
+        /* 创建一个 FromSuperBrain Logger */
         auto logger_FromSuperBrain = std::make_shared<spdlog::logger>("FromSuperBrain",begin(sinks),end(sinks));
-        /* 创建一个SPAServer logger */
+        /* 创建一个 SPAServer logger */
         auto logger_SPAServer = std::make_shared<spdlog::logger>("SPAServer",begin(sinks),end(sinks));
-        /* 创建一个FromRedis logger */
+        /* 创建一个 FromRedis logger */
         auto logger_FromRedis = std::make_shared<spdlog::logger>("FromRedis",begin(sinks),end(sinks));
-        /* 创建一个ToEQMDataBase logger */
-        auto logger_ToEQMDataBase = std::make_shared<spdlog::logger>("ToEQMDataBase",begin(sinks),end(sinks));
+        /* 创建一个 FromWebAPI logger */
+        auto logger_webapi = std::make_shared<spdlog::logger>("FromWebAPI",begin(sinks),end(sinks));
+        /* 创建一个MQTT logger */
+        auto logger_MQTT = std::make_shared<spdlog::logger>("MQTT",begin(sinks),end(sinks));
 
 
         /* 注册到注册表 */
@@ -77,7 +79,8 @@ void initLog(QString ModuleName, CLHQLogApi& lhQLog)
         spdlog::register_logger(logger_FromSuperBrain);
         spdlog::register_logger(logger_SPAServer);
         spdlog::register_logger(logger_FromRedis);
-        spdlog::register_logger(logger_ToEQMDataBase);
+        spdlog::register_logger(logger_webapi);
+        spdlog::register_logger(logger_MQTT);
 
         /* 设置spdlog输出级别,默认的估计不输出debug这个级别
          * 这是默认的设置,可以在外面单数设置输出方式

+ 26 - 0
SecurePlayAuxServer/communication/FromMQTT.cpp

@@ -0,0 +1,26 @@
+#include "FromMQTT.h"
+
+
+FromMQTT::FromMQTT(MQTTBase* parent) : MQTTBase(parent)
+{
+    m_logger = spdlog::get("MQTT");
+    if(m_logger == nullptr)
+    {
+        fmt::print("MQTT logger is nullptr");
+        return;
+    }
+}
+
+FromMQTT::~FromMQTT()
+{
+    /* 断开连接 */
+    m_client.disconnect();
+}
+
+
+/* 接收到消息,子类继承这个解析消息数据 */
+void FromMQTT::recvMessage(const QMQTT::Message& message)
+{
+
+}
+

+ 26 - 0
SecurePlayAuxServer/communication/FromMQTT.h

@@ -0,0 +1,26 @@
+#ifndef FromMQTT_H
+#define FromMQTT_H
+
+#include "MQTTBase.h"
+#include "spdlog/spdlog.h"
+
+
+
+class FromMQTT : public MQTTBase
+{
+
+public:
+    FromMQTT(MQTTBase* parent = nullptr);
+    ~FromMQTT();
+
+
+protected:
+    /* 接收到消息,子类继承这个解析消息数据 */
+    virtual void recvMessage(const QMQTT::Message& message) override;
+
+private:
+    std::shared_ptr<spdlog::logger> m_logger = nullptr;
+
+};
+
+#endif // FromMQTT_H

+ 29 - 15
SecurePlayAuxServer/communication/FromSuperBrain.cpp

@@ -11,13 +11,13 @@ FromSuperBrain::FromSuperBrain()
     m_logger = spdlog::get("FromSuperBrain");
     if(m_logger == nullptr)
     {
-        SPDLOG_ERROR("FromSuperBrain logger is nullptr");
+        fmt::print("FromSuperBrain logger is nullptr");
         return;
     }
 
-    m_url = "http://192.1.2.64:30000/vos";
-    m_appKey = "x1pcq13r";
-    m_appSecret = "Setyir9yxvSiFGB/wsv4YHWiNmrgeaZhzJKi7c7Gmk04Z5Kd/hCifL+0WnfCRDJF";
+    // m_url = "http://192.1.2.64:30000/vos";
+    // m_appKey = "x1pcq13r";
+    // m_appSecret = "Setyir9yxvSiFGB/wsv4YHWiNmrgeaZhzJKi7c7Gmk04Z5Kd/hCifL+0WnfCRDJF";
 }
 
 FromSuperBrain::~FromSuperBrain()
@@ -25,6 +25,15 @@ FromSuperBrain::~FromSuperBrain()
 
 }
 
+
+/* 初始化地址信息 */
+void FromSuperBrain::initSuperBrain(const std::string& url, const std::string& appKey, const std::string& appSecret)
+{
+    m_url = url;
+    m_appKey = appKey;
+    m_appSecret = appSecret;
+}
+
 /* 获取token */
 bool FromSuperBrain::getToken()
 {
@@ -41,7 +50,7 @@ bool FromSuperBrain::getToken()
         SPDLOG_LOGGER_ERROR(m_logger, "{}", response);
         return false;
     }
-    // SPDLOG_LOGGER_DEBUG(m_logger, "response:{}", response);
+    // SPDLOG_LOGGER_TRACE(m_logger, "response:{}", nJson::parse(response).dump(4));
     /* 解析json信息 */
     try
     {
@@ -49,7 +58,9 @@ bool FromSuperBrain::getToken()
         auto code = json0["code"].get<std::string>();
         if(code != "0")
         {
-            SPDLOG_LOGGER_ERROR(m_logger, "Get Token failed");
+            SPDLOG_LOGGER_ERROR(m_logger, "Get Token failed, URL: {}", m_url);
+            SPDLOG_LOGGER_ERROR(m_logger, "code: {}", code);
+            SPDLOG_LOGGER_ERROR(m_logger, "message: {}", json0["message"].get<std::string>());
             return false;
         }
         json0["data"]["accessToken"].get_to(m_token);
@@ -62,11 +73,6 @@ bool FromSuperBrain::getToken()
         SPDLOG_LOGGER_ERROR(m_logger,"解析 Token 数据失败:{}, 错误ID:{}",e.what(), e.id);
         return false;
     }
-    catch(const std::exception& e)
-    {
-        SPDLOG_LOGGER_ERROR(m_logger,"解析 Token 数据失败:{}",e.what());
-        return false;
-    }
     catch(...)
     {
         SPDLOG_LOGGER_ERROR(m_logger,"解析 Token 数据失败");
@@ -93,7 +99,7 @@ bool FromSuperBrain::getTaskTypeList(std::vector<AlgorithmInfo>& vecInfo)
         SPDLOG_LOGGER_ERROR(m_logger, "{}}", response);
         return false;
     }
-    // SPDLOG_LOGGER_DEBUG(m_logger, "TaskTypeList: \n{}", response);
+    // SPDLOG_LOGGER_TRACE(m_logger, "TaskTypeList: \n{}", nJson::parse(response).dump(4));
     /* 解析json信息 */
     try
     {
@@ -148,7 +154,7 @@ bool FromSuperBrain::getDeviceList(std::vector<DeviceInfo>& vecInfo)
         SPDLOG_LOGGER_ERROR(m_logger, "{}", response);
         return false;
     }
-    // SPDLOG_LOGGER_DEBUG(m_logger, "DeivceList: \n{}", response);
+    // SPDLOG_LOGGER_TRACE(m_logger, "DeivceList: \n{}", nJson::parse(response).dump(4));
     /* 解析JSON信息 */
     try
     {
@@ -159,16 +165,23 @@ bool FromSuperBrain::getDeviceList(std::vector<DeviceInfo>& vecInfo)
             SPDLOG_LOGGER_ERROR(m_logger, "Get DeviceList failed");
             return false;
         }
-        DeviceInfo info;
+        
         nJson json1 = json0["data"];
         for(const auto& it : json1)
         {
+            DeviceInfo info;
             info.DeviceID = it["deviceId"].get<int>();
             info.DeviceName = it["deviceName"].is_null() ? "" : it["deviceName"].get<std::string>();
             info.DeviceSerial = it["deviceSerial"].is_null() ? "" : it["deviceSerial"].get<std::string>();
             info.DeviceType = it["deviceType"].is_null() ? "" : it["deviceType"].get<std::string>();
             /* 这三个可能是null */
-            info.DevicePort = it["port"].is_null() ? 0 : it["port"].get<int>();
+            auto tmpPort = it["port"].is_null() ? "" : it["port"].get<std::string>();
+            if(tmpPort.empty())
+            {
+                info.DevicePort = 0;
+            }else {
+                info.DevicePort = std::stoi(tmpPort);
+            }
             info.UserAccount = it["userAccount"].is_null() ? "" : it["userAccount"].get<std::string>();
             info.UserPassword = it["userPWD"].is_null() ? "" : it["userPWD"].get<std::string>();
             /* 解析任务类型列表 */
@@ -179,6 +192,7 @@ bool FromSuperBrain::getDeviceList(std::vector<DeviceInfo>& vecInfo)
                 info1.ActionID = it1["ability"].get<std::string>();
                 info1.ActionName = it1["taskTypeName"].get<std::string>();
                 info1.ActionTaskID = it1["taskTypeId"].get<int>();
+
                 info.vecAlgorithmInfo.push_back(info1);
             }
             vecInfo.push_back(info);

+ 5 - 1
SecurePlayAuxServer/communication/FromSuperBrain.h

@@ -13,6 +13,10 @@ class FromSuperBrain
 public:
     FromSuperBrain();
     ~FromSuperBrain();
+
+    /* 初始化地址信息 */
+    void initSuperBrain(const std::string& url, const std::string& appKey, const std::string& appSecret);
+
     /* 获取token */
     bool getToken();
     /* 获取算法列表 */
@@ -31,7 +35,7 @@ private:
     std::string m_appKey;       /* 授权码 */
     std::string m_appSecret;    /* 授权码 */
 
-    std::string m_token;                            /* token */
+    std::string m_token;                                                        /* token */
     const std::string m_tokenPath = "/external/broadcastToken";                 /* 获取token数据 */
     const std::string m_taskTypeListPath = "/external/getTaskTypeList";         /* 获取任务类型数据 */
     const std::string m_deviceListPath = "/external/getBaseDeviceList";         /* 获取设备列表数据 */

+ 115 - 62
SecurePlayAuxServer/communication/FromWebAPI.cpp

@@ -12,7 +12,7 @@ FromWebAPI::FromWebAPI()
     m_logger = spdlog::get("FromWebAPI");
     if(m_logger == nullptr)
     {
-        SPDLOG_ERROR("FromWebAPI logger is nullptr");
+        fmt::print("FromWebAPI logger is nullptr");
         return;
     }
 }
@@ -28,7 +28,7 @@ FromWebAPI::~FromWebAPI()
 
 
 /* 初始化WebApi */
-bool FromWebAPI::initWebApi(const QString& url, const QString& serverIP, const QString& serID)
+bool FromWebAPI::initWebApi(const QString& url,const QString& serID, const QString appType, const QString& serverIP)
 {
     if(m_httpApi == nullptr)
     {
@@ -57,10 +57,10 @@ bool FromWebAPI::initWebApi(const QString& url, const QString& serverIP, const Q
         SPDLOG_LOGGER_DEBUG(m_logger,"Get server list failed:{}, error info:{}",ret, m_httpApi->DoGetLastError(&ret).toStdString());
         return false;
     }
-    SPDLOG_LOGGER_TRACE(m_logger,"Server list:{}", serverList);
-    SPDLOG_LOGGER_DEBUG(m_logger,"WebAPI Sucess!");
+    // SPDLOG_LOGGER_TRACE(m_logger,"Server list:{}", serverList);
+    SPDLOG_LOGGER_DEBUG(m_logger,"WebAPI Load Sucess!");
     /* 登录,第二个参数是限制的服务 */
-    ret = m_httpApi->DBLogin(serverIP, serID, "SPSS", m_userToken);
+    ret = m_httpApi->DBLogin(serverIP, serID, appType, m_userToken);
     if(ret != 0)
     {
         SPDLOG_LOGGER_ERROR(m_logger,"Login failed:{}, error info:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
@@ -297,7 +297,7 @@ bool FromWebAPI::insertDeviceInfo(std::vector<DeviceInfo>& vecInfo)
         auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"插入设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             isSuccess = false;
         }
         
@@ -387,10 +387,10 @@ bool FromWebAPI::updateDeviceInfo(std::vector<DeviceInfo>& vecUpdateInfo)
 
         QString strCmd = QString::fromStdString(json0.dump());
         QString strRet;
-        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strCmd, strRet);
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"更新设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"更新设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             isSuccess = false;
         }
 
@@ -438,16 +438,16 @@ bool FromWebAPI::deleteDeviceInfo(std::vector<DeviceInfo>& vecDeleteInfo)
 
             nJson json2;
             json2["camerID"] = it.DeviceID;
-            json1["paramList"] = json1;
+            json1["paramList"] = json2;
             
             json0.push_back(json1);
         }
         QString strCmd = QString::fromStdString(json0.dump());
         QString strRet;
-        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strCmd, strRet);
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"删除tCamerinfo设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"删除tCamerinfo设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             isSuccess = false;
         }
 
@@ -489,6 +489,8 @@ bool FromWebAPI::getDeviceInfo(std::vector<DeviceInfo>& vecInfo)
         return false;
     }
 
+    // SPDLOG_LOGGER_TRACE(m_logger, "摄像机信息:\n{}", nJson::parse(strRet.toStdString()).dump(4));
+
     /* 解析信息 */
     try {
         nJson json1 = nJson::parse(strRet.toStdString());
@@ -735,10 +737,10 @@ bool FromWebAPI::insertDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo)
         }
         QString strRet;
         QString strCmd = QString::fromStdString(json0.dump());
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             return false;
         }
     }
@@ -767,45 +769,52 @@ bool FromWebAPI::updateDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo)
         return false;
     }
     /* 更新之前先删除相关的信息 */
-    for(const auto& it : vecInfo)
+    if(!deleteDeviceAlgorithmInfo(vecInfo))
     {
-        nJson json0;
-        json0["opName"] = "SPSS_DeleteFromActionCamer";
-        nJson json1;
-        json1["camerID"] = it.DeviceID;
-        json0["paramList"] = json1;
-        QString strCmd = QString::fromStdString(json0.dump());
-        QString strRet;
-        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strCmd, strRet);
-        if(ret != 0)
-        {
-            SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-            // return false;
-        }
-        SPDLOG_LOGGER_DEBUG(m_logger,"从 ActionCamer 删除DeviceID {} 成功!", it.DeviceID);
+        SPDLOG_LOGGER_ERROR(m_logger,"删除 tActionCamer 关联表失败");
+        return false;
     }
     /* 插入信息到tActionCamer表 */
     bool isSuccess = true;
-    for(const auto& it0 : vecInfo)
+    try
     {
-        for(const auto& it1 : it0.vecAlgorithmInfo)
+        nJson json0 = nJson::array();
+        for(const auto& it0 : vecInfo)
         {
-            nJson json0;
-            json0["opName"] = "SPSS_InsertToActionCamer";
-            nJson json1;
-            json1["actionID"] = it1.ActionID;
-            json1["camerID"] = it0.DeviceID;
-            json0["paramList"] = json1;
-            QString strCmd = QString::fromStdString(json0.dump());
-            QString strRet;
-            auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
-            if(ret != 0)
+            for(const auto& it1 : it0.vecAlgorithmInfo)
             {
-                SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-                isSuccess = false;
+                nJson json1;
+                json1["opName"] = "SPSS_InsertToActionCamer";
+                json1["Key"] = QUuid::createUuid().toString().toStdString();
+                nJson json2;
+                json2["actionID"] = it1.ActionID;
+                json2["camerID"] = it0.DeviceID;
+                json1["paramList"] = json2;
+
+                json0.push_back(json1);
             }
-            SPDLOG_LOGGER_DEBUG(m_logger,"插入DeviceID {} ActionID {} 到 ActionCamer 成功!", it0.DeviceID, it1.ActionID);
         }
+        QString strCmd = QString::fromStdString(json0.dump());
+        QString strRet;
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
+        if(ret != 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            isSuccess = false;
+        }
+        // SPDLOG_LOGGER_DEBUG(m_logger,"插入数据到ActionCamer 成功! 数目: {}", json0.size());
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 插入tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch (const nJson::type_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 插入tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 插入tActionCamer JSON失败 数据失败");
+        return false;
     }
 
 
@@ -822,23 +831,44 @@ bool FromWebAPI::deleteDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo)
     }
     bool isSuccess = true;
     /* 更新之前先删除相关的信息 */
-    for(const auto& it : vecInfo)
+    try
     {
-        nJson json0;
-        json0["opName"] = "SPSS_DeleteFromActionCamer";
-        nJson json1;
-        json1["camerID"] = it.DeviceID;
-        json0["paramList"] = json1;
+        nJson json0 = nJson::array();
+        /* 更新之前先删除相关的信息 */
+        for(const auto& it : vecInfo)
+        {
+            nJson json1;
+            json1["opName"] = "SPSS_DeleteFromActionCamer";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
+            json2["camerID"] = it.DeviceID;
+            json1["paramList"] = json2;
+            
+            json0.push_back(json1);
+        }
+
         QString strCmd = QString::fromStdString(json0.dump());
         QString strRet;
-        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strCmd, strRet);
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"删除设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             // return false;
             isSuccess = false;
         }
-        SPDLOG_LOGGER_DEBUG(m_logger,"从 ActionCamer 删除DeviceID {} 成功!", it.DeviceID);
+        // SPDLOG_LOGGER_DEBUG(m_logger,"从 ActionCamer 删除成功! 数目:{}", vecInfo.size());
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch (const nJson::type_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败");
+        return false;
     }
 
     return isSuccess;
@@ -854,25 +884,47 @@ bool FromWebAPI::deleteDeviceAlgorithmInfo(std::list<int>& vecID)
         return false;
     }
     bool isSuccess = true;
-    /* 更新之前先删除相关的信息 */
-    for(const auto& it : vecID)
+    
+    try
     {
-        nJson json0;
-        json0["opName"] = "SPSS_DeleteFromActionCamer";
-        nJson json1;
-        json1["camerID"] = it;
-        json0["paramList"] = json1;
+        nJson json0 = nJson::array();
+        /* 更新之前先删除相关的信息 */
+        for(const auto& it : vecID)
+        {
+            nJson json1;
+            json1["opName"] = "SPSS_DeleteFromActionCamer";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
+            json2["camerID"] = it;
+            json1["paramList"] = json2;
+            
+            json0.push_back(json1);
+        }
+
         QString strCmd = QString::fromStdString(json0.dump());
         QString strRet;
-        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strCmd, strRet);
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret != 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"删除设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"删除设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             // return false;
             isSuccess = false;
         }
-        SPDLOG_LOGGER_DEBUG(m_logger,"从 ActionCamer 删除DeviceID {} 成功!", it);
+        // SPDLOG_LOGGER_DEBUG(m_logger,"从 ActionCamer 删除成功! 数目:{}", vecID.size());
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch (const nJson::type_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除tActionCamer JSON失败 数据失败");
+        return false;
     }
+    
 
     return isSuccess;
 }
@@ -1578,6 +1630,7 @@ bool FromWebAPI::getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo)
             QString strEnd = QString::fromStdString(it["endTime"].get<std::string>());
             info.StartTime = QDateTime::fromString(strStart, "yyyy-MM-ss hh:mm:ss");
             info.EndTime = QDateTime::fromString(strEnd, "yyyy-MM-ss hh:mm:ss");
+            
             listInfo.push_back(info);
         }
     } 

+ 1 - 1
SecurePlayAuxServer/communication/FromWebAPI.h

@@ -18,7 +18,7 @@ public:
     ~FromWebAPI();
 
     /* 初始化WebAPI */
-    bool initWebApi(const QString& url,const QString& serverIP,const QString& serID);
+    bool initWebApi(const QString& url,const QString& serID, const QString appType, const QString& serverIP = "");
     
     /* 写入算法信息,写入tAction表 */
     bool writeAlgorithmInfo(std::vector<AlgorithmInfo>& vecInfo);

+ 9 - 7
SecurePlayAuxServer/main.cpp

@@ -4,11 +4,10 @@
 #include "SPAServer.h"
 #include "LHLogInit.h"
 #include "LHQLogAPI.h"
-#include "ThreadPool/ThreadPool.h"
-#include <QCoreApplication>
-
+#include "ThreadPool.h"
+#include "GlobalConfig.h"
 
-// #include "RingQueue.hpp"
+#include <QCoreApplication>
 
 
 void test1();
@@ -22,17 +21,20 @@ int main(int argc, char* argv[])
     auto logger = spdlog::get("main");
     if(logger == nullptr)
     {
-        SPDLOG_ERROR("main logger is nullptr");
+        fmt::print("main logger is nullptr");
         return -1;
     }
     SPDLOG_LOGGER_INFO(logger, "★  ★  ★  ★  ★  ★  ☆  ☆  SecurePlayAuxServer  ☆  ☆  ★  ★  ★  ★  ★  ★");
     /* 设置线程池最大线程个数 */
     CPPTP.setThreadMaxNum(256);
 
+    /* 初始化服务配置 */
+    GConfig.initService();
+
     SPAServer server;
-    // server.startServer();
+    server.startServer();
 
-    // return app.exec();
+    return app.exec();
 
     // test1();
 }

BIN
image.png


+ 15 - 2
安播辅助服务程序说明.md

@@ -13,10 +13,19 @@
 
 ## 使用到的地址
 1. 超脑基础信息API地址 [apifox](https://apifox.com/apidoc/shared-1f40509b-3aca-4c2c-9d8e-381b986b085a/api-183796683)
+    - `SuperBrainURL`: http://172.16.38.194:30000/vos
+        - 后台账号: admin
+        - 密码: Ff1z@TOFr^iwd%Ra
+    - 可用的AppKey: nkf52ec2
+    - AppSecret: 2zTz79ERs5I+M846TLp8USRsJiGowWCnLGsuAvnPIeKLruZjmsx0lJOTV5juBsjk
 2. Redis地址
-    - IP:http://172.16.36.80:30000/vos/
+    <!-- - IP:http://172.16.36.80:30000/vos/ -->
+    <!-- - 端口:32222 -->
+    <!-- - 密码:Ff1z@TOFr^iwd%Ra -->
+    - IP:172.16.38.194
     - 端口:32222
     - 密码:Ff1z@TOFr^iwd%Ra
+    - 数据库:database:4
 3. 总控数据库
     - SQL Server
         - 数据表:EQM_BJ
@@ -34,8 +43,12 @@
 
 ## 从行业超脑获取基础信息
 1. 使用http从行业超脑获取到`算法列表`和`设备列表`
+    - 获取Token:从超脑的URL地址获取token,后缀:`SuperBrainURL`+`/external/broadcastToken`,需要两个参数`appKey`和`appSecret`两个参数,返回`accessToken`
+     1) `appKey`和`appSecret`在`SuperBrainURL`中的`系统管理`->`订阅方管理`中获取
+    - 获取算法列表:`SuperBrainURL`+`/external/getTaskTypeList`,参数: `accessToken`
+    - 获取设备列表:`SuperBrainURL`+`/external/getBaseDeviceList`,参数: `accessToken`
 2. 这里使用一个线程单独读取,可能需要定时更新
-3. `算法列表`和`设备列表`和`tAction`对应的值,`算法列表`好像只有这三个只有用,读取到后写入到EQM数据库
+3. `算法列表`和`设备列表`和`tAction`对应的值,`算法列表`好像只有这三个有用,读取到后写入到EQM数据库
     |算法列表|设备列表|EQM|
     |:--|:--|:--|
     |ability|ability|ActionId|