Просмотр исходного кода

V0.4.4
1、完成了房间内人员信息记录的功能
2、获取摄像机和频率名称的WebAPI还未完成

Apple 1 месяц назад
Родитель
Сommit
f057d04983

+ 2 - 2
CMakeLists.txt

@@ -126,9 +126,9 @@ add_compile_definitions(SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE)
 # find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
 
 find_package(Qt5 COMPONENTS
-    Widgets
+    # Widgets
     Core
-    Network
+    # Network
     # Sql
     REQUIRED
 )

+ 8 - 2
SQL/SecurePlay.sqlbook

@@ -78,8 +78,10 @@ SELECT *
 FROM "tRoomInfo";
 
 
+
+
 #关联算法信息,"tRoomInfo"."PKID" = "tRoomCamer"."RoomId"
-SELECT "tRoomCamer".PKID, "tRoomCamer".RoomId, "tRoomCamer".CamerId, "tActionCamer".ActionId, "tRoomInfo"."Chnid", "tRoomInfo"."Rtype", "tRoomInfo"."Rname"
+SELECT "tRoomCamer"."PKID", "tRoomCamer"."RoomId", "tRoomCamer"."CamerId", "tActionCamer"."ActionId", "tRoomInfo"."ChnId", "tRoomInfo"."Rtype", "tRoomInfo"."Rname"
 FROM "tRoomCamer"
 LEFT JOIN "tActionCamer"
 ON "tRoomCamer"."CamerId" = "tActionCamer"."CamerId"
@@ -138,4 +140,8 @@ INSERT INTO "tWorkOnInfo" ("nChID", "FaceIdList", "FaceNameList", "StartTime", "
 VALUES (:nChID, :FaceIdList, :FaceNameList, :StartTime, :EndTime, :MaxNumber, :MinNumber, :CamerId);
 
 INSERT INTO "tWorkOnInfo" ("nChID", "FaceIdList", "FaceNameList", "StartTime", "EndTime", "MaxNumber", "MinNumber", "CamerId")
-VALUES (1, '-1;-1', '未知;未知', '2024-10-21 18:03:00', '2024-10-21 18:13:00', 5, 1, 117);
+VALUES (1, '-1;-1', '未知;未知', '2024-10-21 18:03:00', '2024-10-21 18:13:00', 5, 1, 117);
+-- SQLBook: Code
+#查看通道信息
+SELECT *
+FROM "tChannel";

+ 17 - 1
SecurePlayAuxServer/Application/FuncBase.cpp

@@ -18,5 +18,21 @@ FuncBase::~FuncBase()
 /* 设置功能信息 */
 void FuncBase::setFuncActionInfo(FuncActionInfo* pFuncAct)
 {
-    m_pFuncAct = pFuncAct;
+    m_funcAct = *pFuncAct;
 }
+void FuncBase::setFuncActionInfo(FuncActionInfo& FuncAct)
+{
+    m_funcAct = FuncAct;
+}
+
+/* 获取该实例的功能 */
+AppFunction FuncBase::getApp()
+{
+    return m_funcAct.appFunction;
+}
+
+/* 获取线程运行状态 */
+bool FuncBase::getThreadRunning() const
+{
+    return m_bRunning;
+}

+ 9 - 1
SecurePlayAuxServer/Application/FuncBase.h

@@ -2,6 +2,7 @@
 #define FUNCBASE_H
 
 #include <memory>
+#include "GlobalVariable.h"
 
 class FromRedis;
 class ToEQMDataBase;
@@ -23,6 +24,11 @@ public:
 
     /* 设置功能信息 */
     void setFuncActionInfo(FuncActionInfo* pFuncAct);
+    void setFuncActionInfo(FuncActionInfo& FuncAct);
+    /* 获取该实例的功能 */
+    AppFunction getApp();
+    /* 获取线程运行状态 */
+    bool getThreadRunning() const;
 
 protected:
     /* 读取Redis的实例 */
@@ -30,7 +36,9 @@ protected:
     /* 写入EQM数据库的实例 */
     std::shared_ptr<ToEQMDataBase> m_toEQMDataBase = nullptr;
     /* 线程信息 */
-    FuncActionInfo* m_pFuncAct = nullptr;
+    FuncActionInfo m_funcAct;
+
+    std::atomic_bool m_bRunning = false;     /* 线程运行状态 */
 };
 
 

+ 146 - 71
SecurePlayAuxServer/Application/FuncOrdinary.cpp

@@ -14,41 +14,38 @@ FuncOrdinary::FuncOrdinary()
         return;
     }
     /* 给变量分配内存 */
-    m_listAlarm = new ListAlarmInfo();
+
 }
 
 FuncOrdinary::~FuncOrdinary()
 {
-    if(m_listAlarm != nullptr)
-    {
-        delete m_listAlarm;
-        m_listAlarm = nullptr;
-    }
+
 }
 
 /* 任务线程 */
 void FuncOrdinary::thread_task()
 {
-    if(m_pFuncAct == nullptr)
+    if(m_funcAct.appFunction == AppFunction::APP_NONE)
     {
         SPDLOG_LOGGER_ERROR(m_logger, "未设置线程功能信息");
         return;
     }
-    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 功能线程, ChannelID:{}",m_pFuncAct->strFunctionName, m_pFuncAct->ChannelID);
-
+    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 功能线程, ChannelID:{}",m_funcAct.strFunctionName, m_funcAct.ChannelID);
+    /* 设置线程运行状态 */
+    m_bRunning = true;
     while (GThreadInfo.getRunning())
     {
         /* 从全局的信息块中更新功能信息,如是否需要退出线程,主要是更新摄像机关联的算法信息 */
-        GThreadInfo.updateFuncInfo(m_pFuncAct);
+        GThreadInfo.updateFuncInfo(m_funcAct);
         /* 如果线程的运行状态为停止 */
-        if(m_pFuncAct->RunState == RunTimeState::RUN_STATE_STOP)
+        if(m_funcAct.RunState == RunTimeState::RUN_STATE_STOP)
         {
-            /* 设置为NONE,就会被管理线程回收释放内存 */
-            m_pFuncAct->appFunction = AppFunction::APP_NONE;
+            /* 退出线程 */
             break;
         }
+
         /* 读取Redis信息,处理数据,第一层循环是根据房间读取,第二个循环是根据房间内的摄像机读取 */
-        for(const auto& roomInfo : m_pFuncAct->listRoomCamActInfo)
+        for(const auto& roomInfo : m_funcAct.listRoomCamActInfo)
         {
             for(const auto& it : roomInfo.mapCameraAction)
             {
@@ -58,92 +55,170 @@ void FuncOrdinary::thread_task()
                 if(!m_fromRedis->getRedisString(strKey, strRetValue))
                 {
                     SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
-                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    std::this_thread::sleep_for(std::chrono::milliseconds(10));
                     continue;
                 }
-                /* 解析数据 */
-                AlarmInfo alarmInfo;
-                parseRedisBaseData(strRetValue, alarmInfo);
-                parseRedisBBoxesData(strRetValue, alarmInfo);
+                /* 解析数据,先设置基础数据 */
+                AlarmInfo newAlarmInfo;
+                newAlarmInfo.ActionID = it.second;
+                newAlarmInfo.appFunction = m_funcAct.appFunction;
+
+                parseRedisBaseData(strRetValue, newAlarmInfo);
+                parseRedisBBoxesData(strRetValue, newAlarmInfo);
                 /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                if(isEventTimeVaild(alarmInfo.EventTime))
+                if(isEventTimeVaild(newAlarmInfo.EventTime))
                 {
-                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime);
                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
                     continue;
                 }
+
+                /* -------------------------------------------------------------------------------
+                 * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
+                 * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
+                 * 报警数据的结束时间,并清空pAlarmInfo 
+                 * ------------------------------------------------------------------------------- */
+
                 /* 找出数组中与当前报警ID相同的的报警信息 */
-                auto pAlarmInfo = m_listAlarm->findAlarmInfo(alarmInfo);
+                auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarmInfo);
+                /* 没有找到报警记录,就新建一个 */
                 if(pAlarmInfo == nullptr)
                 {
-                    /* 没有找到报警记录,就新建一个 */
-                    AlarmInfo newAlarmInfo = alarmInfo;
-                    m_listAlarm->addAlarmInfo(newAlarmInfo);
-                    /* 重新查找该报警信息 */
-                    pAlarmInfo = m_listAlarm->findAlarmInfo(alarmInfo);
-                    if(pAlarmInfo == nullptr)
+                    /* 新记录有报警,新建报警记录 */
+                    if(newAlarmInfo.Is_Alarm)
                     {
-                        SPDLOG_LOGGER_ERROR(m_logger, "查找报警信息失败, Key:{}", strKey);
-                        continue;
+                        /* 图片不能是空,如果是空的,就不写入数据库 */
+                        if(!newAlarmInfo.ImageInfo.empty())
+                        {
+                            /* 违禁品检测,开始时间是事件时间 */
+                            newAlarmInfo.StartTime = newAlarmInfo.EventTime;
+                            newAlarmInfo.EndTime = "";
+                            /* 保存新的报警记录 */
+                            newAlarmInfo.Is_InsertEQM = false;
+                            m_listAlarm.addAlarmInfo(newAlarmInfo);
+                        }else 
+                        {
+                            SPDLOG_LOGGER_WARN(m_logger, "频道:{}, 房间:{}, 摄像机:{}, 算法:{}, 有报警区域, 但是没有图片信息", m_funcAct.ChannelID, roomInfo.RoomID, it.first, it.second);
+                        }
                     }
-                }
-                /* 判断有无报警记录,新的报警就写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,
-                * 结束报警就更新tAlarmInfo的报警数据的结束时间,并清空pAlarmInfo */
-                if(pAlarmInfo->Is_Alarm)
+                } 
+                /* 已有报警记录 */
+                else 
                 {
-                    /* 正在报警中,检查是否报警结束 */
-                    if(alarmInfo.Is_Alarm)
+                    /* 更新图片信息 */
+                    if(!newAlarmInfo.ImageInfo.empty())
+                    {
+                        pAlarmInfo->ImageInfo = newAlarmInfo.ImageInfo;
+                    }
+                    /* 判断是否还在报警中 */
+                    if(newAlarmInfo.Is_Alarm)
                     {
-                        /* 更新图片信息 */
-                        if(!alarmInfo.ImageInfo.empty())
+                        /* 正在报警中,检查是否已经写入到数据库中 */
+                        if(pAlarmInfo->Is_InsertEQM)
                         {
-                            pAlarmInfo->ImageInfo = alarmInfo.ImageInfo;
-                        }
-                    } else {
-                        /* 报警结束,判断时长,更新数据库结束时间,结束时间是此时电脑时间 */
-                        if(timeDiffWithNow(pAlarmInfo->EventTime) > GConfig.Contraband)
+                            /* 已经写入到数据库中,不做处理 */
+                        }else 
                         {
-                            pAlarmInfo->EndTime = chronoToStrTime(std::chrono::system_clock::now());
-                            m_toEQMDataBase->updateAlarmEndTime(*pAlarmInfo);
-                        }else {
-                            /* 不够报警时间,目前不做任何处理,不删除EQM报警记录 */
-                        }
+                            /* 判断报警时长间隔是否足够 */
+                            if(!isAlarmTimeVaild(*pAlarmInfo))
+                            {
+                                /* 不够报警时间,直接进行下一个循环 */
+                                continue;
+                            }
 
-                        /* 清空报警信息 */
-                        pAlarmInfo->reInit();
-                    }
-                }
-                else
-                {
-                    /* 是新的报警 */
-                    if(alarmInfo.Is_Alarm)
+                            /* 写入到数据库 */
+                            pAlarmInfo->Is_InsertEQM = false;
+                            if(m_toEQMDataBase->insertAlarmInfo(*pAlarmInfo))
+                            {
+                                pAlarmInfo->Is_InsertEQM = true;
+                            }else {
+                                SPDLOG_LOGGER_ERROR(m_logger, "写入tAlarmInfo报警数据失败, 频率:{}, 房间:{}, 算法:{} ", m_funcAct.ChannelID, roomInfo.RoomID, it.second);
+                            }
+                        }
+                        
+                    } else 
                     {
-                        /* 图片不能是空,如果是空的,就不写入数据库 */
-                        if(!alarmInfo.ImageInfo.empty())
+                        /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
+                         * 更新数据库结束时间,结束时间是此时电脑时间 */
+                        if(isAlarmTimeVaild(*pAlarmInfo))
                         {
-                            /* 违禁品检测,开始时间是事件时间 */
-                            alarmInfo.StartTime = alarmInfo.EventTime;
-                            alarmInfo.EndTime = "";
-                            if(m_toEQMDataBase->insertAlarmInfo(alarmInfo))
+                            pAlarmInfo->EndTime = chronoToStrTime(std::chrono::system_clock::now());
+                            /* 判断是否已经写入到数据库中 */
+                            if(pAlarmInfo->Is_InsertEQM)
                             {
-                                /* 保存新的报警记录 */
-                                *pAlarmInfo = alarmInfo;
+                                /* 已经写入到数据库中,更新结束时间 */
+                                m_toEQMDataBase->updateAlarmEndTime(*pAlarmInfo);
                             }else {
-                                SPDLOG_LOGGER_ERROR(m_logger, "写入tAlarmInfo报警数据失败, Key: {}", strKey);
+                                /* 没有写入到数据库中,写入到数据库中 */
+                                m_toEQMDataBase->insertAlarmInfo(*pAlarmInfo);
                             }
-                        }else {
-                            SPDLOG_LOGGER_ERROR(m_logger, "频道:{}, 房间:{}, 摄像机:{}, 算法:{}, 有报警区域, 但是没有图片信息", m_pFuncAct->ChannelID, roomInfo.RoomID, it.first, it.second);
+                            SPDLOG_LOGGER_INFO(m_logger, "频率:{}, 房间:{}, 摄像机:{}, 算法:{}, 报警结束", m_funcAct.ChannelID, roomInfo.RoomID, it.first, it.second);
                         }
+
+                        /* 删除这个报警信息 */
+                        m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
                     }
                 }
-
             }
         }
         
         /* 休眠设置的时间 */
         std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
     }
-    /* 设置线程退出的状态 */
-    // GThreadInfo.setThreadState(m_pFuncAct, RunTimeState::RUN_STATE_EXITCOMPLET);
-    SPDLOG_LOGGER_INFO(m_logger, "{} 功能线程退出,Channel:{}", m_pFuncAct->strFunctionName, m_pFuncAct->ChannelID);
+    /* 设置线程退出的状态,设置成 RUN_STATE_EXITCOMPLET ,就会被管理线程回收 */
+    GThreadInfo.setThreadState(m_funcAct, RunTimeState::RUN_STATE_EXITCOMPLET);
+    SPDLOG_LOGGER_INFO(m_logger, "{} 功能线程退出,Channel:{}", m_funcAct.strFunctionName, m_funcAct.ChannelID);
+    m_bRunning = false;
+}
+
+/* 判断报警时长是否符合不同应用的最小间隔 */
+bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
+{
+    /* 违禁品物品 */
+    if(info.appFunction == AppFunction::APP_Contraband)
+    {
+        if(timeDiffWithNow(info.EventTime) < GConfig.AppContraband_Time)
+        {
+            return false;
+        }
+    }
+    /* 玩手机识别 */
+    else if(info.appFunction == AppFunction::APP_PlayPhone)
+    {
+        if(timeDiffWithNow(info.EventTime) < GConfig.AppPlayPhone)
+        {
+            return false;
+        }
+    }
+    /* 老鼠识别 */
+    else if(info.appFunction == AppFunction::APP_Mouse)
+    {
+        if(timeDiffWithNow(info.EventTime) < GConfig.AppMouse)
+        {
+            return false;
+        }
+    }
+    /* 未戴口罩识别 */
+    else if(info.appFunction == AppFunction::APP_NoMask)
+    {
+        if(timeDiffWithNow(info.EventTime) < GConfig.AppMask)
+        {
+            return false;
+        }
+    }
+    /* 疲劳检测 */
+    else if(info.appFunction == AppFunction::APP_Fatigue)
+    {
+        if(timeDiffWithNow(info.EventTime) < GConfig.AppTired_Time)
+        {
+            return false;
+        }
+    }
+    /* 摔倒识别 */
+    else if(info.appFunction == AppFunction::APP_AllDown)
+    {
+        return true;
+    }
+    
+    return true;
 }

+ 5 - 1
SecurePlayAuxServer/Application/FuncOrdinary.h

@@ -27,10 +27,14 @@ public:
     /* 任务线程 */
     void thread_task() override;
 
+private:
+    /* 判断报警时长是否符合不同应用的最小间隔 */
+    bool isAlarmTimeVaild(const AlarmInfo& info);
+
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
 
-    ListAlarmInfo* m_listAlarm = nullptr;               /* 报警列表 */
+    ListAlarmInfo m_listAlarm;                  /* 报警列表 */
 };
 
 #endif // FuncOrdinary_H

+ 133 - 0
SecurePlayAuxServer/Application/FuncPersonOnWork.cpp

@@ -0,0 +1,133 @@
+#include "FuncPersonOnWork.h"
+
+#include "GlobalVariable.h"
+#include "GlobalConfig.h"
+#include "FromRedis.h"
+#include "ToEQMDataBase.h"
+#include "UniversalFunc.h"
+
+FuncPersonOnWork::FuncPersonOnWork()
+{
+    m_logger = spdlog::get("SPAServer");
+    if(m_logger == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "SPAServer logger is nullptr");
+        return;
+    }
+    /* 给变量分配内存 */
+    /* 保存每个摄像机的报警信息 */
+    m_pListAlarm = std::make_shared<std::list<AlarmInfo>>();
+    /* 保存人脸信息的数据 */
+    m_pListRoomFace = new ListRoomFaceInfo();
+}
+
+FuncPersonOnWork::~FuncPersonOnWork()
+{
+    if(m_pListRoomFace != nullptr)
+    {
+        delete m_pListRoomFace;
+        m_pListRoomFace = nullptr;
+    }
+}
+
+
+/**
+ * @brief 工作线程
+ * 
+ */
+void FuncPersonOnWork::thread_task()
+{
+    if(m_funcAct.appFunction == AppFunction::APP_NONE)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "未设置线程功能信息");
+        return;
+    }
+    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", m_funcAct.strFunctionName, m_funcAct.ChannelID);
+    
+    while (GThreadInfo.getRunning())
+    {
+        /* 更新线程信息 */
+        GThreadInfo.updateFuncInfo(m_funcAct);
+        if( (m_funcAct.appFunction == AppFunction::APP_NONE) ||
+            (m_funcAct.RunState == RunTimeState::RUN_STATE_STOP) )
+        {
+            break;
+        }
+
+        /* -----------------------------------------------------------------------
+         * 读取Redis数据 
+         * ----------------------------------------------------------------------- */
+        m_pListAlarm->clear();
+        for(const auto& RoomInfo : m_funcAct.listRoomCamActInfo)
+        {
+            for(const auto& it : RoomInfo.mapCameraAction)
+            {
+                std::string strKey = std::to_string(it.first) + ":" + it.second;
+                std::string strRetValue;
+                if(!m_fromRedis->getRedisString(strKey, strRetValue))
+                {
+                    SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+                    std::this_thread::sleep_for(std::chrono::milliseconds(10));
+                    continue;
+                }
+                /* 解析数据 */
+                AlarmInfo alarmInfo;
+                alarmInfo.ActionID = it.second;
+                parseRedisBaseData(strRetValue, alarmInfo);
+                parseRedisBBoxesData(strRetValue, alarmInfo);
+                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+                if(isEventTimeVaild(alarmInfo.EventTime))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    continue;
+                }
+                m_pListAlarm->push_back(alarmInfo);
+            }
+        }
+
+        /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
+        for(auto& alarmInfo : *m_pListAlarm)
+        {
+            /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
+            m_pListRoomFace->addRoomFaceInfo(alarmInfo);
+        }
+        /* 计算人脸个数,每个房间逐个对比 */
+        QDateTime now = QDateTime::currentDateTime();
+        for(auto it = m_pListRoomFace->listRoomFaceInfo.begin(); it != m_pListRoomFace->listRoomFaceInfo.end(); )
+        {
+            /* m_pListRoomFace的数据不会删除,会和历史对比,这里的MaxNum和MinNum就是历史数据 */
+            if(it->MaxNum < it->listPersonInfo.size())
+            {
+                it->MaxNum = it->listPersonInfo.size();
+            }
+            if(it->MinNum > it->listPersonInfo.size())
+            {
+                it->MinNum = it->listPersonInfo.size();
+            }
+            /* 判断是否需要写入数据库,离岗时间超过设置的时间就写入,默认是600秒 */
+            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GConfig.AppUpdateOnWorkTimeInterval_Time)
+            {
+                /* 写入数据库 */
+                if(m_toEQMDataBase->insertOnWorkInfo(*it))
+                {
+                    SPDLOG_LOGGER_INFO(m_logger, "☆ 新增人脸信息,频道[{}][{}],摄像头[{}][{}],时间范围[{} - {}],人数范围[{} - {}]", 
+                    it->ChannelID, GConfig.getChannelName(it->ChannelID), it->CameraID, GConfig.getCameraName(it->CameraID), 
+                    it->StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), it->EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+                    it->MinNum, it->MaxNum);
+
+                    /* 删除这条信息 */
+                    it = m_pListRoomFace->listRoomFaceInfo.erase(it);
+                    continue;
+                }
+            }
+            ++it;
+        }
+        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+    }
+    GThreadInfo.setThreadState(m_funcAct, RunTimeState::RUN_STATE_EXITCOMPLET);
+    SPDLOG_LOGGER_INFO(m_logger, "{} 功能线程退出,Channel:{}", m_funcAct.strFunctionName, m_funcAct.ChannelID);
+}
+
+
+

+ 36 - 0
SecurePlayAuxServer/Application/FuncPersonOnWork.h

@@ -0,0 +1,36 @@
+#ifndef FUNCPERSONONWORK_H
+#define FUNCPERSONONWORK_H
+
+#include "FuncBase.h"
+#include "spdlog/spdlog.h"
+
+
+/**
+ * @brief 人员在岗识别线程
+ *        1、这个写入tWorkOnInfo表格,十分钟写一次,记录这十分钟内的在岗离岗的人员信息,同时记录这十分钟房间内
+ *           的人员数量最大值和最小值。
+ *        2、
+ *        3、这个线程也会进行在岗离岗的识别报警
+ * 
+ */
+
+class FuncPersonOnWork : public FuncBase
+{
+public:
+    FuncPersonOnWork();
+    ~FuncPersonOnWork();
+
+    void thread_task() override;
+
+private:
+    std::shared_ptr<spdlog::logger> m_logger = nullptr;
+
+    ListAlarmInfo m_listAlarm;                  /* 报警列表 */
+    /* 保存每个摄像机的报警信息 */
+    std::shared_ptr<std::list<AlarmInfo>> m_pListAlarm = nullptr;
+    /* 保存人脸信息的数据 */
+    ListRoomFaceInfo* m_pListRoomFace = nullptr;
+
+};
+
+#endif /* FUNCPERSONONWORK_H */

+ 2 - 2
SecurePlayAuxServer/CMakeLists.txt

@@ -52,9 +52,9 @@ target_include_directories(${loaclExeName} PRIVATE
 
 #链接Qt库
 target_link_libraries(${loaclExeName} PRIVATE
-    Qt5::Widgets
+    # Qt5::Widgets
     Qt5::Core
-    Qt5::Network
+    # Qt5::Network
     # Qt5::Sql
 )
 #链接外部库

+ 92 - 10
SecurePlayAuxServer/GlobalInfo/GlobalConfig.cpp

@@ -30,11 +30,11 @@ bool GlobalConfig::readConfig(const QString& strConfigFile)
 
     settings.beginGroup("System");
 
-    AppUpdateOnWorkTimeInterval = settings.value("WorkOnInfoSecond", 600).toInt();  /* 更新在岗信息的时间间隔 */
-    AppPeopleOnWork = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
-    Contraband = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
+    AppUpdateOnWorkTimeInterval_Time = settings.value("WorkOnInfoSecond", 600).toInt();  /* 更新在岗信息的时间间隔 */
+    AppPeopleOnWork_Time = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
+    AppContraband_Time = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
     AppBadMan = settings.value("APPBADMAN", 50).toInt();                     /* 非法入侵 */
-    AppTired = settings.value("APPTIRED", 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();                       /* 手势识别 */
@@ -61,10 +61,10 @@ bool GlobalConfig::readConfig(const QString& strConfigFile)
 /* 打印读取到的值 */
 void GlobalConfig::printValue()
 {
-    SPDLOG_INFO("APPPEPOLEONWORK:   {}", AppPeopleOnWork);
-    SPDLOG_INFO("APPBADTHING:       {}", Contraband);
+    SPDLOG_INFO("APPPEPOLEONWORK:   {}", AppPeopleOnWork_Time);
+    SPDLOG_INFO("APPBADTHING:       {}", AppContraband_Time);
     SPDLOG_INFO("APPBADMAN:         {}", AppBadMan);
-    SPDLOG_INFO("APPTIRED:          {}", AppTired);
+    SPDLOG_INFO("APPTIRED:          {}", AppTired_Time);
     SPDLOG_INFO("APPPEOPLECONT:     {}", AppPeopleCont);
     SPDLOG_INFO("APPPLAYPHONE:      {}", AppPlayPhone);
     SPDLOG_INFO("APPMOUSE:          {}", AppMouse);
@@ -73,6 +73,60 @@ void GlobalConfig::printValue()
     SPDLOG_INFO("EventTimeValid:    {}", EventTimeValid);
 }
 
+/* 添加通道信息 */
+void GlobalConfig::setChannelInfo(std::map<int, std::string> mapChannelName)
+{
+    m_rwLockChnInfo.lockForWrite();
+    m_mapChannelName.clear();
+    m_mapChannelName = mapChannelName;
+    m_rwLockChnInfo.unlock();
+}
+
+/* 清空通道信息 */
+void GlobalConfig::clearChannelInfo()
+{
+    m_rwLockChnInfo.lockForWrite();
+    m_mapChannelName.clear();
+    m_rwLockChnInfo.unlock();
+}
+
+/* 获取通道名称 */
+std::string GlobalConfig::getChannelName(int ChannelID)
+{
+    m_rwLockChnInfo.lockForRead();
+    std::string strName = "";
+    auto it = m_mapChannelName.find(ChannelID);
+    if(it != m_mapChannelName.end())
+    {
+        strName = it->second;
+    }
+    m_rwLockChnInfo.unlock();
+    return strName;
+}
+
+/* 添加摄像机信息 */
+void GlobalConfig::setCameraInfo(std::map<int, std::string> mapCameraName)
+{
+    m_rwLockCamInfo.lockForWrite();
+    m_mapCameraName.clear();
+    m_mapCameraName = mapCameraName;
+    m_rwLockCamInfo.unlock();
+}
+/* 获取摄像机名称 */
+std::string GlobalConfig::getCameraName(int CameraID)
+{
+    m_rwLockCamInfo.lockForRead();
+    std::string strName = "";
+    auto it = m_mapCameraName.find(CameraID);
+    if(it != m_mapCameraName.end())
+    {
+        strName = it->second;
+    }
+    m_rwLockCamInfo.unlock();
+    return strName;
+}
+
+
 
 /* ====================================================================================
  * ************************    GlobalThreadInfo成员函数    *****************************
@@ -293,6 +347,7 @@ bool GlobalThreadInfo::addFuncActionInfo(const AppAndTimeInfo& func)
 
 /**
  * @brief 添加算法信息,根据传进来的算法ID,将其加入到对应的功能中
+ *        根据功能需要,将算法ID加入到对应的功能中
  * 
  * @param info 
  * @return true 
@@ -402,14 +457,14 @@ bool GlobalThreadInfo::addActionInfo(const ActionInfo& info)
 
 /**
  * @brief 清空无用的功能信息
- *          摄像机和算法信息为空的,或者运行状态为STOP,都会被清理掉
+ *          摄像机和算法信息为空的,或者运行状态为RUN_STATE_EXITCOMPLET,都会被清理掉
  * 
  */
 void GlobalThreadInfo::clearNoneFuncActionInfo()
 {
     for(auto it0 = m_listFuncActionInfo.begin(); it0 != m_listFuncActionInfo.end();)
     {
-        if((*it0)->listRoomCamActInfo.empty() || ((*it0)->RunState == RunTimeState::RUN_STATE_STOP))
+        if((*it0)->listRoomCamActInfo.empty() || ((*it0)->RunState == RunTimeState::RUN_STATE_EXITCOMPLET))
         {
             delete *it0;
             it0 = m_listFuncActionInfo.erase(it0);
@@ -419,11 +474,15 @@ void GlobalThreadInfo::clearNoneFuncActionInfo()
     }
 }
 
-/* 清空算法列表 */
+/* 清空算法列表(直接清空房间信息) */
 void GlobalThreadInfo::clearActionList()
 {
     for(auto& it0 : m_listFuncActionInfo)
     {
+        // for(auto& it1 : it0->listRoomCamActInfo)
+        // {
+        //     it1.mapCameraAction.clear();
+        // }
         it0->listRoomCamActInfo.clear();
     }
 }
@@ -495,6 +554,16 @@ void GlobalThreadInfo::setThreadState(FuncActionInfo* pInfo, RunTimeState state)
     }
 }
 
+void GlobalThreadInfo::setThreadState(FuncActionInfo& pInfo, RunTimeState state)
+{
+    std::lock_guard<std::mutex> look(m_mutexRunFAI);
+    auto p = findAppFunction(pInfo);
+    if(p != nullptr)
+    {
+        p->RunState = state;
+    }
+}
+
 /**
  * @brief 功能线程更新功能信息,这里是从内存中的数组里获取
  * 
@@ -515,4 +584,17 @@ void GlobalThreadInfo::setThreadState(FuncActionInfo* pInfo, RunTimeState state)
 
     return true;
 }
+bool GlobalThreadInfo::updateFuncInfo(FuncActionInfo& pInfo)
+{
+    pInfo.clearActionList();
+    std::lock_guard<std::mutex> look(m_mutexRunFAI);
+    auto fa = findAppFunction(pInfo);
+    if(fa == nullptr)
+    {
+        return false;
+    }
+    pInfo = *fa;
+
+    return true;
+}
 

+ 35 - 9
SecurePlayAuxServer/GlobalInfo/GlobalConfig.h

@@ -34,15 +34,15 @@ public:
     /* 打印读取到的值 */
     void printValue();
     
-    int AppUpdateOnWorkTimeInterval;/* 更新在岗信息的时间间隔 */
-    int AppPeopleOnWork;        /* 离岗时间 */
-    int Contraband;             /* 违禁物品出现的时间 */
-    int AppBadMan;              /* 非法入侵 */
-    int AppTired;               /* 疲劳检测时间 */
-    int AppPeopleCont;          /* 区域人员统计 */
-    int AppPlayPhone;           /* 玩手机识别 */
-    int AppMouse;               /* 老鼠识别 */
-    int AppMask;                /* 戴口罩识别 */
+    int AppUpdateOnWorkTimeInterval_Time;   /* 更新在岗信息的时间间隔 */
+    int AppPeopleOnWork_Time;               /* 离岗时间 */
+    int AppContraband_Time;                 /* 违禁物品出现的时间 */
+    int AppBadMan;                          /* 非法入侵 */
+    int AppTired_Time;                      /* 疲劳检测时间 */
+    int AppPeopleCont;                      /* 区域人员统计 */
+    int AppPlayPhone;                       /* 玩手机识别 */
+    int AppMouse;                           /* 老鼠识别 */
+    int AppMask;                            /* 戴口罩识别 */
 
     int CheckSet;               /* 服务端多久检测一次配置 */
     int EventTimeValid;         /* 事件时间有效期 */
@@ -51,6 +51,26 @@ public:
 
     std::string Key;            /* Key */
     std::string Secret;         /* Secret */
+
+public:
+    /* 添加通道信息 */
+    void setChannelInfo(std::map<int, std::string> mapChannelName);
+    /* 清空通道信息 */
+    void clearChannelInfo();
+    /* 获取通道名称 */
+    std::string getChannelName(int ChannelID);
+
+    /* 添加摄像机信息 */
+    void setCameraInfo(std::map<int, std::string> mapCameraName);
+    /* 获取摄像机名称 */
+    std::string getCameraName(int CameraID);
+
+private:
+    QReadWriteLock m_rwLockChnInfo;                     /* 读写锁 */
+    std::map<int, std::string> m_mapChannelName;        /* 通道名称 */
+    /* 摄像机名称 */
+    QReadWriteLock m_rwLockCamInfo;                     /* 读写锁 */
+    std::map<int, std::string> m_mapCameraName;        /* 摄像机名称 */
  };
 
 
@@ -108,8 +128,12 @@ public:
 
     /* 设置线程状态 */
     void setThreadState(FuncActionInfo* pInfo, RunTimeState state);
+    void setThreadState(FuncActionInfo& pInfo, RunTimeState state);
     /* 更新算法的摄像机ID */
     bool updateFuncInfo(FuncActionInfo* pInfo);
+    bool updateFuncInfo(FuncActionInfo& pInfo);
+
+    
 
 private:
     std::atomic_bool m_bRunning;    /* 线程运行状态 */
@@ -117,6 +141,8 @@ private:
     /* 运行时应用线程功能相关信息 */
     std::mutex m_mutexRunFAI;
     std::list<FuncActionInfo*> m_listFuncActionInfo;    /* 功能信息列表 */
+
+    
 };
 
 #endif /* GLOBALCONFIG_H */

+ 44 - 4
SecurePlayAuxServer/GlobalInfo/GlobalVariable.cpp

@@ -2,6 +2,8 @@
 
 #include "spdlog/spdlog.h"
 
+#include "FuncBase.h"
+
 /* ====================================================================================
  * *******************************    全局变量定义    **********************************
  * ====================================================================================*/
@@ -73,6 +75,7 @@ bool DeviceInfo::isEqualAlgorithmInfo(const std::vector<AlgorithmInfo>& other)
 AlarmInfo::AlarmInfo() 
 {
     Is_Alarm = false;
+    Is_InsertEQM = false;
     AlarmID = 0;
     DeviceID = 0;
     RoomID = 0;
@@ -90,12 +93,14 @@ AlarmInfo::AlarmInfo()
     FaceIDList = "";
     FaceNameList = "";
     listBbox.clear();
+    appFunction = AppFunction::APP_NONE;
 }
 
 
 AlarmInfo::AlarmInfo(const AlarmInfo& other)
 {
     Is_Alarm = other.Is_Alarm;
+    Is_InsertEQM = other.Is_InsertEQM;
     AlarmID = other.AlarmID;
     DeviceID = other.DeviceID;
     RoomID = other.RoomID;
@@ -114,6 +119,7 @@ AlarmInfo::AlarmInfo(const AlarmInfo& other)
     FaceNameList = other.FaceNameList;
     listBbox = other.listBbox;
     vecPersonInfo = other.vecPersonInfo;
+    appFunction = other.appFunction;
 }
 
 AlarmInfo& AlarmInfo::operator=(AlarmInfo& other)
@@ -121,6 +127,7 @@ AlarmInfo& AlarmInfo::operator=(AlarmInfo& other)
     if(this != &other)
     {
         Is_Alarm = other.Is_Alarm;
+        Is_InsertEQM = other.Is_InsertEQM;
         AlarmID = other.AlarmID;
         DeviceID = other.DeviceID;
         RoomID = other.RoomID;
@@ -139,6 +146,7 @@ AlarmInfo& AlarmInfo::operator=(AlarmInfo& other)
         FaceNameList = other.FaceNameList;
         listBbox = other.listBbox;
         vecPersonInfo = other.vecPersonInfo;
+        appFunction = other.appFunction;
     }
     return *this;
 }
@@ -164,6 +172,7 @@ void AlarmInfo::reInit()
     FaceIDList = "";
     FaceNameList = "";
     listBbox.clear();
+    appFunction = AppFunction::APP_NONE;
 }
 
 /**
@@ -181,7 +190,8 @@ bool ListAlarmInfo::addAlarmInfo(AlarmInfo& info)
     {
         return false;
     }
-    listAlarmInfo.push_back(info);
+    AlarmInfo* pNew = new AlarmInfo(info);
+    listAlarmInfo.push_back(pNew);
     return true;
 }
 
@@ -196,14 +206,29 @@ AlarmInfo* ListAlarmInfo::findAlarmInfo(AlarmInfo& info)
 {
     for(auto& it0 : listAlarmInfo)
     {
-        if(it0.ChannelID == info.ChannelID && it0.RoomID == info.RoomID && it0.DeviceID == info.DeviceID && it0.ActionID == info.ActionID)
+        if(it0->ChannelID == info.ChannelID && it0->RoomID == info.RoomID && it0->DeviceID == info.DeviceID && it0->ActionID == info.ActionID)
         {
-            return &it0;
+            return it0;
         }
     }
     return nullptr;
 }
 
+/* 删除报警记录 */
+void ListAlarmInfo::deleteAlarmInfo(AlarmInfo& info)
+{
+    for(auto it = listAlarmInfo.begin(); it != listAlarmInfo.end();)
+    {
+        if((*it)->ChannelID == info.ChannelID && (*it)->RoomID == info.RoomID && (*it)->DeviceID == info.DeviceID && (*it)->ActionID == info.ActionID)
+        {
+            delete *it;
+            it = listAlarmInfo.erase(it);
+        }else {
+            ++it;
+        }
+    }
+}
+
 
 /* 查找是否有相同的人脸信息 */
 bool RoomFaceInfo::findPersonInfo(const PersonInfo& info)
@@ -808,6 +833,13 @@ FuncActionInfo::FuncActionInfo()
     EndTime = QDateTime::currentDateTime();
     listRoomCamActInfo.clear();
 }
+
+FuncActionInfo::~FuncActionInfo()
+{
+    
+}
+
+
 FuncActionInfo& FuncActionInfo::operator=(FuncActionInfo& other)
 {
     if(this != &other)
@@ -823,7 +855,14 @@ FuncActionInfo& FuncActionInfo::operator=(FuncActionInfo& other)
     return *this;
 }
 
-/* 添加算法信息 */
+/**
+ * @brief 添加算法信息,这里不能直接创建房间,需要先判断有没有已有的房间,因为有的应用功能可能会包含多个房间
+ *        已经提前被创建过了
+ * 
+ * @param info 
+ * @return true 
+ * @return false 
+ */
 bool FuncActionInfo::addActionInfo(const ActionInfo& info)
 {
     /* 根据此类的功能,添加算法信息 */
@@ -839,6 +878,7 @@ bool FuncActionInfo::addActionInfo(const ActionInfo& info)
         {
             isFind = true;
             it0.mapCameraAction.insert(std::make_pair(info.CameraID, info.ActionID));
+            break;
         }
     }
     /* 没找到这个房间,就创建 */

+ 15 - 3
SecurePlayAuxServer/GlobalInfo/GlobalVariable.h

@@ -11,6 +11,7 @@
 #include "nlohmann/json.hpp"
 
 
+class FuncBase;
 
 /* ====================================================================================
  * *******************************    全局变量定义    **********************************
@@ -46,7 +47,7 @@ enum class AppFunction
     APP_NONE = 0,               /* 无功能 */
     APP_OnWork = 1,             /* 人员在岗识别(需要多个摄像机配合) */
     APP_Contraband,             /* 违禁品识别 */
-    APP_Illegal,                /* 非法入侵检测 */
+    APP_Illegal,                /* 非法入侵检测(需要多个摄像机配合) */
     APP_Fatigue,                /* 疲劳检测 */
     APP_Regional,               /* 区域人员检测,人员计数(需要多个摄像机配合) */
     APP_Mouse,                  /* 老鼠识别 */
@@ -56,7 +57,10 @@ enum class AppFunction
 };
 
 
-/* 全局算法列表 */
+/**
+ * @brief 全局算法列表,理论上算法ID是不会变的,但是现在好像是变化的,暂时还不知道从哪里区分
+ * 
+ */
 class ActionList
 {
 public:
@@ -236,6 +240,7 @@ struct PersonInfo
 struct AlarmInfo
 {
     bool Is_Alarm;              /* 是否报警 */
+    bool Is_InsertEQM;          /* 是否已经插入到EQM数据库中 */
     int AlarmID;                /* 报警ID */
     int DeviceID;               /* 设备ID,数据库表格中对应的是CamerID */
     
@@ -243,6 +248,7 @@ struct AlarmInfo
     int ChannelID;              /* 通道ID */
     int State;                  /* 状态 */
     int OnWork;                 /* 是否在工作 */
+    AppFunction appFunction;    /* 应用功能 */
     std::string ActionID;       /* 算法ID */
     std::string StartTime;      /* 报警开始时间 */
     std::string EndTime;        /* 报警结束时间 */
@@ -269,11 +275,14 @@ struct AlarmInfo
  */
 struct ListAlarmInfo
 {
-    std::list<AlarmInfo> listAlarmInfo;    /* 报警信息列表 */
+    std::list<AlarmInfo*> listAlarmInfo;    /* 报警信息列表 */
 
     /* 添加报警信息 */
     bool addAlarmInfo(AlarmInfo& info);
+    /* 查找报警记录 */
     AlarmInfo* findAlarmInfo(AlarmInfo& info);
+    /* 删除报警记录 */
+    void deleteAlarmInfo(AlarmInfo& info);
 };
 
 /**
@@ -650,11 +659,14 @@ public:
     std::list<RoomCamActInfo> listRoomCamActInfo;       /* 房间内的摄像机和算法关联信息 */
 
     FuncActionInfo();
+    ~FuncActionInfo();
     FuncActionInfo& operator=(FuncActionInfo& other);
     /* 添加算法信息 */
     bool addActionInfo(const ActionInfo& info);
     /* 清空算法信息 */
     void clearActionList();
+
+
     
  };
 

+ 2 - 4
SecurePlayAuxServer/GlobalInfo/UniversalFunc.cpp

@@ -188,8 +188,8 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
      // SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
      if(diff.count() > 600)
      {
-         // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
-         return false;
+        // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
+        return false;
      }
      return true;
  }
@@ -228,5 +228,3 @@ std::string chronoToStrTime(const std::chrono::system_clock::time_point& timePoi
 }
 
 
-
-

+ 214 - 165
SecurePlayAuxServer/SPAServer.cpp

@@ -6,9 +6,9 @@
 #include "GlobalInfo/GlobalVariable.h"
 #include "GlobalInfo/GlobalConfig.h"
 #include "UniversalFunc.h"
+#include "FuncOrdinary.h"
 
-#include <QApplication>
-#include <QVector>
+#include <QCoreApplication>
 
 
 SPAServer::SPAServer()
@@ -21,7 +21,7 @@ SPAServer::SPAServer()
     }
 
     /* 读取全局的配置文件 */
-    QString strConfigFile = QApplication::applicationDirPath() + "/config.ini";
+    QString strConfigFile = QCoreApplication::applicationDirPath() + "/config.ini";
     if(!GConfig.readConfig(strConfigFile))
     {
         /* 读取配置文件失败,直接退出程序 */
@@ -101,6 +101,10 @@ void SPAServer::threadFromSuperBrain()
         m_toEQMDataBase.getActionInfo(m_listActionInfo);
         m_mutexActionInfo.unlock();
 
+        /* 更新通道名称和摄像机名称信息 */
+        std::map<int, std::string> mapChannelName;
+        m_toEQMDataBase.getChannelInfo(mapChannelName);
+
         /* 10秒更新一次 */
         std::this_thread::sleep_for(std::chrono::seconds(10));
     }
@@ -210,21 +214,21 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
     /* 先删除多余的数据 */
     if(vecDevDelete.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "删除设备信息");
+        SPDLOG_LOGGER_DEBUG(m_logger, "删除设备信息, 表: tActionCamer");
         m_toEQMDataBase.deleteDeviceInfo(vecDevDelete);
         isUpdate = true;
     }
     /* 更新数据 */
     if(vecDevUpdate.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息");
+        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备信息, 表: tActionCamer");
         m_toEQMDataBase.updateDeviceInfo(vecDevUpdate);
         isUpdate = true;
     }
     /* 插入数据 */
     if(vecDevInsert.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息");
+        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备信息, 表: tActionCamer");
         m_toEQMDataBase.insertDeviceInfo(vecDevInsert);
         isUpdate = true;
     }
@@ -236,7 +240,7 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
     /* 插入新的设备信息 */
     if(vecDevInsert.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表");
+        SPDLOG_LOGGER_DEBUG(m_logger, "插入设备和算法关联表(tActionCamer)");
         m_toEQMDataBase.insertDeviceAlgorithmInfo(vecDevInsert);
         isUpdate = true;
     }
@@ -246,7 +250,7 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
     compareDeviceAlgorithmInfo(vecNewDevInfo, vecDevUpdate);
     if(vecDevUpdate.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表, 更新设备数目:{}", vecDevUpdate.size());
+        SPDLOG_LOGGER_DEBUG(m_logger, "更新设备和算法关联表(tActionCamer), 更新设备数目:{}", vecDevUpdate.size());
         m_toEQMDataBase.updateDeviceAlgorithmInfo(vecDevUpdate);
     }
     
@@ -254,7 +258,7 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
     /* 删除tActionCamer表中消失的设备信息 */
     if(m_listDevIDDelete.size() > 0)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法");
+        SPDLOG_LOGGER_DEBUG(m_logger, "删除消失的设备关联的算法(tActionCamer)");
         m_toEQMDataBase.deleteDeviceAlgorithmInfo(m_listDevIDDelete);
         isUpdate = true;
     }
@@ -439,49 +443,21 @@ void SPAServer::threadFromRedis(const CameraThreadInfo& info)
 }
 
 
-
-/**
- * @brief 判断时间是否长时间没有更新,默认的是600秒,超过这个时间Redis还未更新,可能是超脑挂了
- * 
- * @param strTime 
- * @return true 
- * @return false 
- */
-bool SPAServer::isEventTimeVaild(const std::string& strTime)
-{
-    /* 获取当前时间 */
-    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
-    /* 字符串转成时间 */
-    std::istringstream iss(strTime);
-    std::tm tmEvent = {};
-    iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
-    /* 时间差 */
-    std::chrono::system_clock::time_point eventTime = std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
-    std::chrono::duration<double> diff = now - eventTime;
-    // SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
-    if(diff.count() > 600)
-    {
-        // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
-        return false;
-    }
-    return true;
-}
-
-
 /**
  * @brief 分派任务的线程
         1、 线程定时刷新房间和摄像机的关联关系,以及和算法Action的关联关系
         2、 将算法信息加入到不同的列表中
-            需要多个摄像机配合的加入到m_runListRoomActionInfo列表
-            不需要多个摄像机配合的加入到m_runListActionInfo列表
+            需要多个摄像机配合的加入到 m_runListRoomActionInfo 列表
+            不需要多个摄像机配合的加入到 m_runListActionInfo 列表
         3、 每次刷新都会清空ActionInfo或者RoomActionInfo的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,
             就会创建新的ActionInfo,那么RunState的状态是INIT,需要开启新的线程
             如果刷新完成后,算法对应的摄像机列表为空,那么对应的线程就会停止运行,将RunState设置为STOP,本线程的下一轮
             循环就会删除这个ActionInfo
 
  */
-void SPAServer::threadRoomCamera()
+void SPAServer::threadDistribution()
 {
+    SPDLOG_LOGGER_INFO(m_logger, "开启分派任务线程");
     /* 房间相机关联信息 */
     std::list<RoomCameraInfo> listRC;
     /* 存储获取到的应用和启用时间的信息 */
@@ -495,18 +471,22 @@ void SPAServer::threadRoomCamera()
         /* 先清理已经退出的线程所用到的Action或者RoomAction */
         GThreadInfo.clearNoneFuncActionInfo();
 
+        /* 清空已经停止运行的功能类实例 */
+        clearNoneFuncActionInfo();
+
         /* 创建应用信息,根据从EQM数据库读取到的配置的应用信息创建 */
         toEQMDataBase->getAlarmAppInfo(listAppAndTime);
         for(const auto& it : listAppAndTime)
         {
-            /* 创建应用信息,如果已有该应用,就更新时间 */
+            /* 创建应用信息,如果已有该应用,就更新时间
+             * 这里只创建应用信息块,没有对应的房间、算法信息 */
             GThreadInfo.addFuncActionInfo(it);
         }
 
-        /* 先获取EQM数据库信息,取出房间和摄像机关联信息 */
+        /* 先获取EQM数据库信息,取出房间和摄像机关联信息,包括所在的频率 */
         m_mutexActionInfo.lock();
         toEQMDataBase->getActionInfo(m_listActionInfo);
-        /* 将算法信息加入到不同的列表中 */
+        /* 将算法信息加入到不同的功能列表中,先清空功能对应的算法设备列表 */
         GThreadInfo.clearActionList();
         for(const auto& it : m_listActionInfo.getData())
         {
@@ -520,136 +500,205 @@ void SPAServer::threadRoomCamera()
         /* 开启线程 */
         for(const auto& it0 : GThreadInfo.getList())
         {
-            /* 人员在岗识别 */
-
-            /* 区域人员检测 */
-
-            /* 非法入侵检测 */
-
-            /* 违禁品识别 */
-            
-            /* 普通任务线程,一个任务对应一个摄像机和一个算法ID,无需联动 */
-            if(it0->appFunction == AppFunction::APP_AllDown)
+            if(it0->RunState == RunTimeState::RUN_STATE_INIT)
             {
-                if(it0->RunState == RunTimeState::RUN_STATE_INIT)
+                /* 创建实例 */
+                FuncBase* pFunc = createFuncInstance(*it0);
+                if(pFunc == nullptr)
                 {
-                    // CPPTP.add_task(&SPAServer::threadActNormal, this, it0);
+                    SPDLOG_LOGGER_ERROR(m_logger, "创建功能实例失败:{}", it0->strFunctionName);
+                    continue;
                 }
+                CPPTP.add_task(&FuncBase::thread_task, pFunc);
+                m_listFuncBase.push_back(pFunc);
             }
         }
         
-
         GThreadInfo.unlockRunFAI();
 
         /* 休眠n秒,默认应该是300秒 */
         std::this_thread::sleep_for(std::chrono::seconds(GConfig.CheckSet));
     }
-}
-
-
 
+    SPDLOG_LOGGER_INFO(m_logger, "分派任务线程退出");
+}
 
 /**
- * @brief 人员在岗识别线程,这个功能主要是给客户端提供实时的人脸识别信息
- *        1、这个写入tWorkOnInfo表格,十分钟写一次
- *        2、理论上这里需要实时更新数据库,但是实际上时每十分钟写入一次数据
- *        3、这个线程也会进行在岗离岗的识别报警
+ * @brief 创建任务实例的函数,根据不同的功能创建出不同的实例
  * 
- * @param RFAInfo 传入房间ID和算法ID
+ * @param info 
+ * @return FuncBase* 
  */
-void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
+FuncBase* SPAServer::createFuncInstance(FuncActionInfo& info)
 {
-    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
-    /* 创建读取Redis的实例 */
-    std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
-    /* 创建写入数据库实例 */
-    std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
-    /* 局部变量 */
-    std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
-    *pRFAInfo = *RFAInfo;
-
-    /* 保存每个摄像机的报警信息 */
-    std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
-    /* 保存人脸信息的数据 */
-    std::shared_ptr<ListRoomFaceInfo> pListRoomFaceInfo = std::make_shared<ListRoomFaceInfo>();
-    
-    while (m_threadRunning)
+    if(info.appFunction == AppFunction::APP_NONE)
     {
-        /* 更新线程信息 */
-        GThreadInfo.updateFuncInfo(pRFAInfo.get());
-        if(pRFAInfo->appFunction == AppFunction::APP_NONE)
-        {
-            break;
-        }
+        return nullptr;
+    }
+    FuncBase* pFunc = nullptr;
+    /* 普通的功能,只用一个摄像机一个算法的功能 */
+    if( info.appFunction == AppFunction::APP_AllDown || info.appFunction == AppFunction::APP_NoMask ||
+        info.appFunction == AppFunction::APP_PlayPhone || info.appFunction == AppFunction::APP_Mouse ||
+        info.appFunction == AppFunction::APP_Fatigue || info.appFunction == AppFunction::APP_Contraband )
+    {
+        auto tmpFunc = new FuncOrdinary();
+        tmpFunc->setFuncActionInfo(info);
+        pFunc = tmpFunc;
+    }
+    else if(info.appFunction == AppFunction::APP_OnWork)
+    {
+        /* 人员在岗检测 */
+    }
+    else if(info.appFunction == AppFunction::APP_Illegal)
+    {
+        /* 非法入侵 */
+    }
+    else if(info.appFunction == AppFunction::APP_Regional)
+    {
+        /* 区域人员检测 */
+    }
 
-        /* 读取Redis数据 */
-        pListAlarmInfo->clear();
-        for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
+    return pFunc;
+}
+
+/* 清理没有在运行的线程实例 */
+void SPAServer::clearNoneFuncActionInfo()
+{
+    for(auto it = m_listFuncBase.begin(); it != m_listFuncBase.end(); )
+    {
+        if(!(*it)->getThreadRunning())
         {
-            for(const auto& it : RoomInfo.mapCameraAction)
+            /* 需要转换成相应的子类实例才能删除 */
+            if( (*it)->getApp() == AppFunction::APP_AllDown || (*it)->getApp() == AppFunction::APP_NoMask ||
+                (*it)->getApp() == AppFunction::APP_PlayPhone || (*it)->getApp() == AppFunction::APP_Mouse ||
+                (*it)->getApp() == AppFunction::APP_Fatigue || (*it)->getApp() == AppFunction::APP_Contraband )
             {
-                std::string strKey = std::to_string(it.first) + ":" + it.second;
-                std::string strRetValue;
-                if(!fromRedis->getRedisString(strKey, strRetValue))
-                {
-                    SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
-                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                    continue;
-                }
-                /* 解析数据 */
-                AlarmInfo alarmInfo;
-                parseRedisBaseData(strRetValue, alarmInfo);
-                parseRedisBBoxesData(strRetValue, alarmInfo);
-                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                if(isEventTimeVaild(alarmInfo.EventTime))
-                {
-                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
-                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                    continue;
-                }
-                pListAlarmInfo->push_back(alarmInfo);
+                FuncOrdinary* p = dynamic_cast<FuncOrdinary*>(*it);
+                delete p;
             }
-        }
-
-        /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
-        for(auto& alarmInfo : *pListAlarmInfo)
-        {
-            /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
-            pListRoomFaceInfo->addRoomFaceInfo(alarmInfo);
-        }
-        /* 计算人脸个数,并判断是否需要写入数据库 */
-        QDateTime now = QDateTime::currentDateTime();
-        for(auto it = pListRoomFaceInfo->listRoomFaceInfo.begin(); it != pListRoomFaceInfo->listRoomFaceInfo.end(); )
-        {
-            if(it->MaxNum < it->listPersonInfo.size())
+            else if((*it)->getApp() == AppFunction::APP_OnWork)
             {
-                it->MaxNum = it->listPersonInfo.size();
+                /* 人员在岗检测 */
             }
-            if(it->MinNum > it->listPersonInfo.size())
+            else if((*it)->getApp() == AppFunction::APP_Illegal)
             {
-                it->MinNum = it->listPersonInfo.size();
+                /* 非法入侵 */
             }
-            /* 判断是否需要写入数据库,超过设置的时间就写入,默认是600秒 */
-            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GConfig.AppUpdateOnWorkTimeInterval)
+            else if((*it)->getApp() == AppFunction::APP_Regional)
             {
-                /* 写入数据库 */
-                if(toEQMDataBase->insertOnWorkInfo(*it))
-                {
-                    SPDLOG_LOGGER_INFO(m_logger, "ChannelID:{}, RoomID:{}, 在岗信息写入数据库成功, StartTime", it->ChannelID, it->RoomID, it->StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-                    /* 删除这条信息 */
-                    it = pListRoomFaceInfo->listRoomFaceInfo.erase(it);
-                    continue;
-                }
+                /* 区域人员检测 */
             }
+            it = m_listFuncBase.erase(it);
+        }else {
             ++it;
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
     }
-    GThreadInfo.setThreadState(pRFAInfo.get(), RunTimeState::RUN_STATE_STOP);
-    SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
 }
 
 
+
+
+/**
+ * @brief 人员在岗识别线程,这个功能主要是给客户端提供实时的人脸识别信息
+ *        1、这个写入tWorkOnInfo表格,十分钟写一次
+ *        2、理论上这里需要实时更新数据库,但是实际上时每十分钟写入一次数据
+ *        3、这个线程也会进行在岗离岗的识别报警
+ * 
+ * @param RFAInfo 传入房间ID和算法ID
+ */
+// void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
+// {
+//     SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
+//     /* 创建读取Redis的实例 */
+//     std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
+//     /* 创建写入数据库实例 */
+//     std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
+//     /* 局部变量 */
+//     std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
+//     *pRFAInfo = *RFAInfo;
+
+//     /* 保存每个摄像机的报警信息 */
+//     std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
+//     /* 保存人脸信息的数据 */
+//     std::shared_ptr<ListRoomFaceInfo> pListRoomFaceInfo = std::make_shared<ListRoomFaceInfo>();
+    
+//     while (m_threadRunning)
+//     {
+//         /* 更新线程信息 */
+//         GThreadInfo.updateFuncInfo(pRFAInfo.get());
+//         if(pRFAInfo->appFunction == AppFunction::APP_NONE)
+//         {
+//             break;
+//         }
+
+//         /* 读取Redis数据 */
+//         pListAlarmInfo->clear();
+//         for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
+//         {
+//             for(const auto& it : RoomInfo.mapCameraAction)
+//             {
+//                 std::string strKey = std::to_string(it.first) + ":" + it.second;
+//                 std::string strRetValue;
+//                 if(!fromRedis->getRedisString(strKey, strRetValue))
+//                 {
+//                     SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
+//                     continue;
+//                 }
+//                 /* 解析数据 */
+//                 AlarmInfo alarmInfo;
+//                 parseRedisBaseData(strRetValue, alarmInfo);
+//                 parseRedisBBoxesData(strRetValue, alarmInfo);
+//                 /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+//                 if(isEventTimeVaild(alarmInfo.EventTime))
+//                 {
+//                     SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
+//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
+//                     continue;
+//                 }
+//                 pListAlarmInfo->push_back(alarmInfo);
+//             }
+//         }
+
+//         /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
+//         for(auto& alarmInfo : *pListAlarmInfo)
+//         {
+//             /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
+//             pListRoomFaceInfo->addRoomFaceInfo(alarmInfo);
+//         }
+//         /* 计算人脸个数,并判断是否需要写入数据库 */
+//         QDateTime now = QDateTime::currentDateTime();
+//         for(auto it = pListRoomFaceInfo->listRoomFaceInfo.begin(); it != pListRoomFaceInfo->listRoomFaceInfo.end(); )
+//         {
+//             if(it->MaxNum < it->listPersonInfo.size())
+//             {
+//                 it->MaxNum = it->listPersonInfo.size();
+//             }
+//             if(it->MinNum > it->listPersonInfo.size())
+//             {
+//                 it->MinNum = it->listPersonInfo.size();
+//             }
+//             /* 判断是否需要写入数据库,超过设置的时间就写入,默认是600秒 */
+//             if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GConfig.AppUpdateOnWorkTimeInterval_Time)
+//             {
+//                 /* 写入数据库 */
+//                 if(toEQMDataBase->insertOnWorkInfo(*it))
+//                 {
+//                     SPDLOG_LOGGER_INFO(m_logger, "ChannelID:{}, RoomID:{}, 在岗信息写入数据库成功, StartTime", it->ChannelID, it->RoomID, it->StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+//                     /* 删除这条信息 */
+//                     it = pListRoomFaceInfo->listRoomFaceInfo.erase(it);
+//                     continue;
+//                 }
+//             }
+//             ++it;
+//         }
+//         std::this_thread::sleep_for(std::chrono::milliseconds(GConfig.ThreadSleepMS));
+//     }
+//     GThreadInfo.setThreadState(pRFAInfo.get(), RunTimeState::RUN_STATE_STOP);
+//     SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
+// }
+
+
 /**
  * @brief 区域非法入侵检测
             1、野猫、宠物识别:报警判断条件:机房内出现摄像头的宠物识别算法输出报警结果时,记为报警行为,直接
@@ -1014,28 +1063,28 @@ void SPAServer::threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo)
 
 
 /* 将该算法对应的摄像机放入摄像机列表 */
-bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID)
-{
-    for(const auto& rci : listRC)
-    {
-        if(rci.RoomID == pRAInfo->RoomID)
-        {
-            /* 这个摄像机在这个房间内,再判断这个摄像机有没有这个算法 */
-            for(const auto& camID : rci.listCameraID)
-            {
-                for(const auto& cai : mapCameraActionID)
-                {
-                    if(camID == cai.first)
-                    {
-                        /* 再判断这个摄像机的算法是否是当前需要的 */
-                        if(cai.second == pRAInfo->ActionID)
-                        {
-                            pRAInfo->listCameraID.push_back(camID);
-                        }
-                    }
-                }
-            }
-        }
-    }
-    return true;
-}
+// bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID)
+// {
+//     for(const auto& rci : listRC)
+//     {
+//         if(rci.RoomID == pRAInfo->RoomID)
+//         {
+//             /* 这个摄像机在这个房间内,再判断这个摄像机有没有这个算法 */
+//             for(const auto& camID : rci.listCameraID)
+//             {
+//                 for(const auto& cai : mapCameraActionID)
+//                 {
+//                     if(camID == cai.first)
+//                     {
+//                         /* 再判断这个摄像机的算法是否是当前需要的 */
+//                         if(cai.second == pRAInfo->ActionID)
+//                         {
+//                             pRAInfo->listCameraID.push_back(camID);
+//                         }
+//                     }
+//                 }
+//             }
+//         }
+//     }
+//     return true;
+// }

+ 19 - 6
SecurePlayAuxServer/SPAServer.h

@@ -5,6 +5,8 @@
 #include "FromRedis.h"
 #include "ToEQMDataBase.h"
 
+class FuncBase;
+
 /**
  * 安播辅助提示系统服务类
  *      写入EQM数据库的报警逻辑
@@ -20,6 +22,10 @@ public:
     void startServer();
 
 private:
+    /*--------------------------------------------------------------------------------
+     * 从基础平台获取算法信息和设备信息功能线程和所需要的函数,这里更新维护EQM数据库的tAction、
+     * tCameraInfo、tActionCamera等表格
+     *-------------------------------------------------------------------------------*/
     /* 从基础平台获取算法信息和设备信息的线程函数 */
     void threadFromSuperBrain();
     /* 处理算法信息,返回值为true,说明有改变,需要重新读取 */
@@ -34,21 +40,25 @@ private:
     /* 从Redis获取数据线程函数,这个是摄像机线程(注意,这个函数未被使用,不从这里获取Redis数据) */
     void threadFromRedis(const CameraThreadInfo& info);
 
-    /* 判断时间是否长时间没有更新 */
-    bool isEventTimeVaild(const std::string& strTime);
-
+    /*--------------------------------------------------------------------------------
+     * 分派任务的线程,这里是根据房间和摄像机的关联信息,给任务创建不同的功能线程
+     *-------------------------------------------------------------------------------*/
     /* 分派任务的线程 */
-    void threadRoomCamera();
+    void threadDistribution();
+    /* 创建任务实例的函数 */
+    FuncBase* createFuncInstance(FuncActionInfo& info);
+    /* 清理没有在运行的线程实例 */
+    void clearNoneFuncActionInfo();
     
     /* 人员在岗识别线程,应该是人脸识别线程,这个需要房间内多个摄像机共同识别 */
-    void threadActPersonWork(FuncActionInfo* RFAInfo);
+    // void threadActPersonWork(FuncActionInfo* RFAInfo);
     /* 非法入侵检测 */
     void threadActIllegalInvasion(FuncActionInfo* RFAInfo);
     /* 区域人员检测(人员计数),检测这个区域内的人数,不能少于多少人,不能多余多少人 */
     void threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo);
 
     /* 将该算法对应的摄像机放入摄像机列表 */
-    bool insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID);
+    // bool insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID);
 
 
 private:
@@ -69,6 +79,9 @@ private:
     /* 设备和算法关联信息,这里存储着已经删除的设备对应的算法信息,将在这一轮循环中删除 */
     std::list<int> m_listDevIDDelete;
 
+    /* 线程功能类实例列表 */
+    std::list<FuncBase*> m_listFuncBase;
+
 };
 
 #endif /* SPASERVER_H */

+ 260 - 142
SecurePlayAuxServer/communication/ToEQMDataBase.cpp

@@ -1,9 +1,8 @@
 #include "ToEQMDataBase.h"
 
 #include <QJsonDocument>
-#include <QJsonObject>
-#include <QVector>
 #include <QString>
+#include <QUuid>
 
 ToEQMDataBase::ToEQMDataBase()
 {
@@ -64,7 +63,7 @@ bool ToEQMDataBase::initWebApi(const QString& url, const QString& serverIP, cons
         SPDLOG_LOGGER_ERROR(m_logger,"Login failed:{}, error info:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
         return false;
     }
-    SPDLOG_LOGGER_TRACE(m_logger,"Login sucess!");
+    SPDLOG_LOGGER_INFO(m_logger,"Login WebAPI sucess!");
 
     return true;
 }
@@ -103,25 +102,29 @@ bool ToEQMDataBase::writeAlgorithmInfo(std::vector<AlgorithmInfo>& vecInfo)
     /* 循环写入数据 */
     try
     {
+        nJson json0 = nJson::array();
         for(const auto& it : vecInfo)
         {
-            QString retStr;
             /* 操作名称,现在一次性将设备位置和线条信息都下载下来 */
-            nJson json0;
-            json0["opName"] = "SPSS_InsertToAction";
             nJson json1;
-            json1["actionID"] = it.ActionID;                    /* 算法ID */
-            json1["actionName"] = it.ActionName;                /* 算法名称 */
-            json1["actionTaskID"] = it.ActionTaskID;            /* 算法类型 */
-            json0["paramList"] = json1;
-            QString strCmd = QString::fromStdString(json0.dump());
-            int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, retStr);
-            if(ret < 0)
-            {
-                SPDLOG_LOGGER_DEBUG(m_logger,"写入tAction失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-            }
-            SPDLOG_LOGGER_DEBUG(m_logger,"写入一条算法 {} 到 tAction成功!", it.ActionID);
+            json1["opName"] = "SPSS_InsertToAction";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
+            json2["actionID"] = it.ActionID;                    /* 算法ID */
+            json2["actionName"] = it.ActionName;                /* 算法名称 */
+            json2["actionTaskID"] = it.ActionTaskID;            /* 算法类型 */
+            json1["paramList"] = json2;
+
+            json0.push_back(json1);
         }
+        QString retStr;
+        QString strCmd = QString::fromStdString(json0.dump());
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, retStr);
+        if(ret < 0)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger,"写入tAction失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        }
+
     }
     catch (const nJson::parse_error& e) {
         SPDLOG_LOGGER_ERROR(m_logger,"创建 算法JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
@@ -148,21 +151,41 @@ bool ToEQMDataBase::deleteAlgorithmInfo(std::vector<AlgorithmInfo>& vecDeleteInf
         return false;
     }
 
-    for(const auto& it : vecDeleteInfo)
+    try
     {
-        nJson json0;
-        json0["opName"] = "SPSS_DeleteFromAction";
-        nJson json1;
-        json1["actionID"] = it.ActionID;
-        json0["paramList"] = json1;
+        nJson json0 = nJson::array();
+
+        for(const auto& it : vecDeleteInfo)
+        {
+            nJson json1;
+            json0["opName"] = "SPSS_DeleteFromAction";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
+            json2["actionID"] = it.ActionID;
+            json0["paramList"] = json2;
+
+            json0.push_back(json1);
+        }
         QString strCmd = QString::fromStdString(json0.dump());
         QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Delete, strCmd, strRet);
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
         if(ret < 0)
         {
-            SPDLOG_LOGGER_DEBUG(m_logger,"删除tAction失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_ERROR(m_logger,"删除tAction失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
         }
-        SPDLOG_LOGGER_DEBUG(m_logger,"从tAction 删除算法 {} 成功!", it.ActionID);
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除算法的JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch (const nJson::type_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除算法的JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除算法的JSON 数据失败");
+        return false;
     }
 
 
@@ -243,56 +266,66 @@ bool ToEQMDataBase::insertDeviceInfo(std::vector<DeviceInfo>& vecInfo)
     bool isSuccess = true;
     try
     {
+        nJson json0 = nJson::array();
         for(const auto& it : vecInfo)
         {
-            nJson json0;
-            json0["opName"] = "SPSS_InsertToCamerInfo";
             nJson json1;
+            json1["opName"] = "SPSS_InsertToCamerInfo";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
             /* 这里不知道是不是“?”运算符的等级是不是不够,不加括号会报错 */
-            json1["camerID"] = it.DeviceID;
-            json1["camerName"] =  it.DeviceName;
-            json1["camerIP"] = it.DeviceIP;
-            json1["camerPort"] = it.DevicePort;
-            json1["camerUser"] = it.UserAccount;
-            json1["camerPwd"] = it.UserPassword;
-            json1["camerType"] = it.DeviceType;
-            json1["camerSerial"] = it.DeviceSerial;
-            json1["camerChannel"] = nullptr;
-            json1["camerUrl"] = nullptr;
-
-            json0["paramList"] = json1;
-            QString strCmd = QString::fromStdString(json0.dump());
-            QString strRet;
-            auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
-            if(ret < 0)
-            {
-                SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-                isSuccess = false;
-            }
-            SPDLOG_LOGGER_DEBUG(m_logger,"插入ID {} 信息到 CamerInfo 成功!", it.DeviceID);
+            json2["camerID"] = it.DeviceID;
+            json2["camerName"] =  it.DeviceName;
+            json2["camerIP"] = it.DeviceIP;
+            json2["camerPort"] = it.DevicePort;
+            json2["camerUser"] = it.UserAccount;
+            json2["camerPwd"] = it.UserPassword;
+            json2["camerType"] = it.DeviceType;
+            json2["camerSerial"] = it.DeviceSerial;
+            json2["camerChannel"] = nullptr;
+            json2["camerUrl"] = nullptr;
+
+            json1["paramList"] = json2;
+            
+            json0.push_back(json1);
         }
-        /* 插入信息到tActionCamer表 */
-        for(const auto& it0 : vecInfo)
+        QString strCmd = QString::fromStdString(json0.dump());
+        QString strRet;
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_BatchTransAction, strCmd, strRet);
+        if(ret < 0)
         {
-            for(const auto& it1 : it0.vecAlgorithmInfo)
-            {
-                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)
-                {
-                    SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-                    isSuccess = false;
-                }
-                SPDLOG_LOGGER_DEBUG(m_logger,"插入DeviceID {} 和 ActionID {} 到 ActionCamer 成功!", it0.DeviceID, it1.ActionID);
-            }
+            SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            isSuccess = false;
         }
+        
+        // /* 插入信息到tActionCamer表 */
+        // json0.clear();
+        // for(const auto& it0 : vecInfo)
+        // {
+        //     for(const auto& it1 : it0.vecAlgorithmInfo)
+        //     {
+        //         nJson json1;
+        //         json1["opName"] = "SPSS_InsertToActionCamer";
+        //         json1["Key"] = QUuid::createUuid().toString().toStdString();
+        //         nJson json2;
+        //         json2["actionID"] = it1.ActionID;
+        //         json2["camerID"] = it0.DeviceID;
+        //         json1["paramList"] = json1;
+                
+        //         json0.push_back(json1);
+        //     }
+        // }
+        // strCmd.clear();
+        // strRet.clear();
+        // ret = 0;
+        // strCmd = QString::fromStdString(json0.dump());
+        // ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+        // if(ret < 0)
+        // {
+        //     SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        //     isSuccess = false;
+        // }
+
     }
     catch (const nJson::parse_error& e) {
         SPDLOG_LOGGER_ERROR(m_logger,"创建 设备信息JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
@@ -324,34 +357,40 @@ bool ToEQMDataBase::updateDeviceInfo(std::vector<DeviceInfo>& vecUpdateInfo)
         return false;
     }
     bool isSuccess = true;
-    try{
+    try
+    {
+        nJson json0 = nJson::array();
         for(const auto& it : vecUpdateInfo)
         {
-            nJson json0;
-            json0["opName"] = "SPSS_UpdateToCamerInfo";
             nJson json1;
-            json1["camerID"] = it.DeviceID;
-            json1["camerName"] =  it.DeviceName;
-            json1["camerIP"] = it.DeviceIP;
-            json1["camerPort"] = it.DevicePort;
-            json1["camerUser"] = it.UserAccount;
-            json1["camerPwd"] = it.UserPassword;
-            json1["camerType"] = it.DeviceType;
-            json1["camerSerial"] = it.DeviceSerial;
-            json1["camerChannel"] = nullptr;
-            json1["camerUrl"] = nullptr;
+            json1["opName"] = "SPSS_UpdateToCamerInfo";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+            nJson json2;
+            json2["camerID"] = it.DeviceID;
+            json2["camerName"] =  it.DeviceName;
+            json2["camerIP"] = it.DeviceIP;
+            json2["camerPort"] = it.DevicePort;
+            json2["camerUser"] = it.UserAccount;
+            json2["camerPwd"] = it.UserPassword;
+            json2["camerType"] = it.DeviceType;
+            json2["camerSerial"] = it.DeviceSerial;
+            json2["camerChannel"] = nullptr;
+            json2["camerUrl"] = nullptr;
+
+            json1["paramList"] = json2;
+            
+            json0.push_back(json1);
+        }
 
-            json0["paramList"] = json1;
-            QString strCmd = QString::fromStdString(json0.dump());
-            QString strRet;
-            auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strCmd, strRet);
-            if(ret < 0)
-            {
-                SPDLOG_LOGGER_DEBUG(m_logger,"更新设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-                isSuccess = false;
-            }
-            SPDLOG_LOGGER_DEBUG(m_logger,"更新ID {} 信息到 CamerInfo 成功!", it.DeviceID);
+        QString strCmd = QString::fromStdString(json0.dump());
+        QString strRet;
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strCmd, strRet);
+        if(ret < 0)
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger,"更新设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            isSuccess = false;
         }
+
     }
     catch (const nJson::parse_error& e) {
         SPDLOG_LOGGER_ERROR(m_logger,"创建 更新设备信息JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
@@ -381,26 +420,46 @@ bool ToEQMDataBase::deleteDeviceInfo(std::vector<DeviceInfo>& vecDeleteInfo)
     }
     if(vecDeleteInfo.empty())
     {
-        return false;
+        return true;
     }
     bool isSuccess = true;
 
-    for(const auto& it : vecDeleteInfo)
+    try
     {
-        nJson json0;
-        json0["opName"] = "SPSS_DeleteFromCamerInfo";
-        nJson json1;
-        json1["camerID"] = it.DeviceID;
-        json0["paramList"] = json1;
+        nJson json0 = nJson::array();
+        for(const auto& it : vecDeleteInfo)
+        {
+            nJson json1;
+            json1["opName"] = "SPSS_DeleteFromCamerInfo";
+            json1["Key"] = QUuid::createUuid().toString().toStdString();
+
+            nJson json2;
+            json2["camerID"] = it.DeviceID;
+            json1["paramList"] = json1;
+            
+            json0.push_back(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,"删除设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            SPDLOG_LOGGER_DEBUG(m_logger,"删除tCamerinfo设备信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
             isSuccess = false;
         }
-        SPDLOG_LOGGER_DEBUG(m_logger,"删除数据 {} 到 CamerInfo 成功!", it.DeviceID);
+
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除设备信息JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch (const nJson::type_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除设备信息JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...) {
+        SPDLOG_LOGGER_ERROR(m_logger,"创建 删除设备信息JSON 数据失败");
+        return false;
     }
 
     return isSuccess;
@@ -474,6 +533,23 @@ bool ToEQMDataBase::getDeviceInfo(std::vector<DeviceInfo>& vecInfo)
     return true;
 }
 
+/* 获取通道信息 */
+bool ToEQMDataBase::getChannelInfo(std::map<int, std::string>& mapChannelName)
+{
+    if(m_httpApi == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
+        return false;
+    }
+    
+}
+
+/* 获取摄像机信息 */
+bool ToEQMDataBase::getCameraInfo(std::map<int, std::string>& mapCameraName)
+{
+
+}
+
 /* 插入设备和算法关联信息 */
 bool ToEQMDataBase::insertDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo)
 {
@@ -483,27 +559,44 @@ bool ToEQMDataBase::insertDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo)
         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"] = json1;
+                
+                json0.push_back(json1);
             }
-            SPDLOG_LOGGER_DEBUG(m_logger,"插入DeviceID {} 和 ActionID {} 到 ActionCamer 成功!", it0.DeviceID, it1.ActionID);
         }
+        QString strRet;
+        QString strCmd = QString::fromStdString(json0.dump());
+        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+        if(ret < 0)
+        {
+            SPDLOG_LOGGER_DEBUG(m_logger,"插入设备信息到tActionCamer失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+    }
+    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 true;
@@ -773,7 +866,7 @@ bool ToEQMDataBase::getActionInfo(ListActionInfo& listInfo)
             info.CameraID = it["camerId"].is_null() ? -1 : it["camerId"].get<int>();
             info.ActionID = it["actionId"].is_null() ? "" : it["actionId"].get<std::string>();
             info.RoomID = it["roomId"].is_null() ? -1 : it["roomId"].get<int>();
-            info.ChannelID = it["chnid"].is_null() ? -1 : it["chnid"].get<int>();
+            info.ChannelID = it["chnId"].is_null() ? -1 : it["chnId"].get<int>();
             info.RoomType = it["rtype"].is_null() ? -1 : it["rtype"].get<int>();
             info.strRoomName = it["rname"].is_null() ? "" : it["rname"].get<std::string>();
             listInfo.insertActionInfo(&info);
@@ -1031,11 +1124,16 @@ bool ToEQMDataBase::getPersonCountRuleInfo(std::vector<PersonCountRuleInfo>& vec
         SPDLOG_LOGGER_ERROR(m_logger,"解析AlarmRule数据失败:{}, 错误ID:{}",e.what(), e.id);
         return false;
     }
+    catch(...)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"解析AlarmRule数据失败");
+        return false;
+    }
 
     return true;
 }
 
-/* 获取报警时段,也同时获取报警的应用信息 */
+/* 获取报警时段,也同时获取报警的应用信息,tPeriod表 */
 bool ToEQMDataBase::getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo)
 {
     nJson json0;
@@ -1076,12 +1174,17 @@ bool ToEQMDataBase::getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo)
         }
     } 
     catch (const nJson::parse_error& e) {
-        SPDLOG_LOGGER_ERROR(m_logger,"解析AlarmApp数据失败:{}, 错误ID:{}",e.what(), e.id);
+        SPDLOG_LOGGER_ERROR(m_logger,"解析tPeriod数据失败:{}, 错误ID:{}",e.what(), e.id);
         return false;
     }
     catch(const nJson::type_error& e)
     {
-        SPDLOG_LOGGER_ERROR(m_logger,"解析AlarmApp数据失败:{}, 错误ID:{}",e.what(), e.id);
+        SPDLOG_LOGGER_ERROR(m_logger,"解析tPeriod数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"解析tPeriod数据失败");
         return false;
     }
 
@@ -1089,7 +1192,7 @@ bool ToEQMDataBase::getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo)
 }
 
 
-/* 写入在岗信息 */
+/* 写入在岗信息 tWorkOnInfo */
 bool ToEQMDataBase::insertOnWorkInfo(const RoomFaceInfo& onWorkInfo)
 {
     if(m_httpApi == nullptr)
@@ -1113,31 +1216,46 @@ bool ToEQMDataBase::insertOnWorkInfo(const RoomFaceInfo& onWorkInfo)
     strFaceID = strFaceID.substr(0, strFaceID.size() - 1);
     strFaceName = strFaceName.substr(0, strFaceName.size() - 1);
 
+    try
+    {
+        nJson json0;
+        json0["opName"] = "SPSS_InsertToOnWork";
+        nJson json1;
+        json1["nChID"] = onWorkInfo.ChannelID;
+        json1["CamerId"] = onWorkInfo.CameraID;
+        json1["FaceIdList"] = strFaceID;
+        json1["FaceNameList"] = strFaceName;
+        json1["StartTime"] = onWorkInfo.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
+        json1["EndTime"] = onWorkInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
+        json1["MaxNumber"] = onWorkInfo.MaxNum;
+        json1["MinNumber"] = onWorkInfo.MinNum;
 
+        json0["paramList"] = json1;
 
-    nJson json0;
-    json0["opName"] = "SPSS_InsertToOnWork";
-    nJson json1;
-    json1["nChID"] = onWorkInfo.ChannelID;
-    json1["CamerId"] = onWorkInfo.CameraID;
-    json1["FaceIdList"] = strFaceID;
-    json1["FaceNameList"] = strFaceName;
-    json1["StartTime"] = onWorkInfo.StartTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
-    json1["EndTime"] = onWorkInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss").toStdString();
-    json1["MaxNumber"] = onWorkInfo.MaxNum;
-    json1["MinNumber"] = onWorkInfo.MinNum;
-
-    json0["paramList"] = json1;
-
-    QString strCmd = QString::fromStdString(json0.dump());
-    QString strRet;
-    auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
-    if(ret < 0)
+        QString strCmd = QString::fromStdString(json0.dump());
+        QString strRet;
+        auto ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+        if(ret < 0)
+        {
+            SPDLOG_LOGGER_WARN(m_logger,"插入 tWorkOnInfo 失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+            return false;
+        }
+        // SPDLOG_LOGGER_DEBUG(m_logger,"插入在岗信息成功!");
+    }
+    catch (const nJson::parse_error& e) {
+        SPDLOG_LOGGER_ERROR(m_logger,"生成 tWorkOnInfo JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(const nJson::type_error& e)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"生成 tWorkOnInfo JSON 数据失败:{}, 错误ID:{}",e.what(), e.id);
+        return false;
+    }
+    catch(...)
     {
-        SPDLOG_LOGGER_WARN(m_logger,"插入在岗信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        SPDLOG_LOGGER_ERROR(m_logger,"生成 tWorkOnInfo JSON 数据失败");
         return false;
     }
-    SPDLOG_LOGGER_DEBUG(m_logger,"插入在岗信息成功!");
 
     return true;
 }

+ 5 - 0
SecurePlayAuxServer/communication/ToEQMDataBase.h

@@ -29,6 +29,11 @@ public:
     bool deleteDeviceInfo(std::vector<DeviceInfo>& vecDeleteInfo);
     /* 从EQM获取CamerInfo信息 */
     bool getDeviceInfo(std::vector<DeviceInfo>& vecInfo);
+
+    /* 获取通道信息 */
+    bool getChannelInfo(std::map<int, std::string>& mapChannelName);
+    /* 获取摄像机信息 */
+    bool getCameraInfo(std::map<int, std::string>& mapCameraName);
     
     /* 插入设备和算法关联信息 */
     bool insertDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo);

+ 69 - 4
SecurePlayAuxServer/main.cpp

@@ -7,12 +7,12 @@
 #include "ThreadPool/ThreadPool.h"
 #include <QCoreApplication>
 
-#include <QString>
-#include "RingQueue.hpp"
 
-RingQueue<QString> g_queue(10);
+// #include "RingQueue.hpp"
 
 
+void test1();
+
 
 int main(int argc, char* argv[])
 {
@@ -25,7 +25,7 @@ int main(int argc, char* argv[])
         SPDLOG_ERROR("main logger is nullptr");
         return -1;
     }
-    SPDLOG_LOGGER_INFO(logger, "★  ★  ★  ★  ★  ☆  SecurePlayAuxServer  ☆  ★  ★  ★  ★  ★");
+    SPDLOG_LOGGER_INFO(logger, "★  ★  ★  ★  ★  ★  ☆  ☆  SecurePlayAuxServer  ☆  ☆  ★  ★  ★  ★  ★  ★");
     /* 设置线程池最大线程个数 */
     CPPTP.setThreadMaxNum(256);
 
@@ -33,6 +33,71 @@ int main(int argc, char* argv[])
     // server.startServer();
 
     // return app.exec();
+
+    // test1();
+}
+
+
+struct Test
+{
+    Test() {
+        SPDLOG_INFO("构造函数, t:{}", t);
+    }
+    Test(const Test& o) {
+        t = o.t;
+        SPDLOG_INFO("拷贝构造函数, t:{}", t);
+    }
+    Test& operator=(const Test& o) {
+        t = o.t;
+        SPDLOG_INFO("赋值构造函数, t:{}", t);
+        return *this;
+    }
+
+    ~Test() {
+        SPDLOG_INFO("析构函数");
+    }
+    int t = 0;
+};
+
+Test& test2();
+Test test3();
+std::list<Test> listTest;
+void test1()
+{
+    Test t;
+    listTest.push_back(t);
+    SPDLOG_INFO("--------------------------");
+    SPDLOG_INFO("t:{}", t.t);
+    auto it = listTest.front();
+    it.t = 1;
+    auto it1 = listTest.front();
+    SPDLOG_INFO("it:{}", it1.t);
+    SPDLOG_INFO("--------------------------");
+    auto& it2 = listTest.front();
+    it2.t = 2;
+    SPDLOG_INFO("it2:{}", listTest.front().t);
+    SPDLOG_INFO("--------------------------");
+    auto& it3 = test2();
+    SPDLOG_INFO("it3:{}", it3.t);
+    SPDLOG_INFO("--------------------------");
+    auto it4 = test3();
+    SPDLOG_INFO("it4:{}", it4.t);
+}
+
+Test& test2()
+{
+    Test t;
+    t.t = 10;
+    listTest.push_front(t);
+    return listTest.front();
+}
+
+Test test3()
+{
+    Test t;
+    t.t = 10;
+    listTest.push_front(t);
+    return listTest.front();
 }