Explorar o código

V0.5.5
1、测试完成了区域人员检测和玩手机检测功能

Apple hai 1 mes
pai
achega
b4aa3765ae
Modificáronse 27 ficheiros con 890 adicións e 572 borrados
  1. 1 1
      SQL/SecurePlay.sqlbook
  2. 46 8
      SecurePlayAuxServer/Application/FuncBase.cpp
  3. 5 2
      SecurePlayAuxServer/Application/FuncBase.h
  4. 101 69
      SecurePlayAuxServer/Application/FuncIllegalInvasion.cpp
  5. 7 2
      SecurePlayAuxServer/Application/FuncIllegalInvasion.h
  6. 231 145
      SecurePlayAuxServer/Application/FuncOnAndOffWork.cpp
  7. 18 12
      SecurePlayAuxServer/Application/FuncOnAndOffWork.h
  8. 102 80
      SecurePlayAuxServer/Application/FuncOrdinary.cpp
  9. 9 5
      SecurePlayAuxServer/Application/FuncOrdinary.h
  10. 64 41
      SecurePlayAuxServer/Application/FuncPersonOnWork.cpp
  11. 7 6
      SecurePlayAuxServer/Application/FuncPersonOnWork.h
  12. 47 50
      SecurePlayAuxServer/Application/FuncRegionalPerson.cpp
  13. 4 1
      SecurePlayAuxServer/Application/FuncRegionalPerson.h
  14. 24 16
      SecurePlayAuxServer/GlobalInfo/GlobalConfig.cpp
  15. 37 14
      SecurePlayAuxServer/GlobalInfo/GlobalConfig.h
  16. 18 18
      SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.cpp
  17. 2 2
      SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.h
  18. 4 0
      SecurePlayAuxServer/GlobalInfo/GlobalVariable.cpp
  19. 4 3
      SecurePlayAuxServer/GlobalInfo/GlobalVariable.h
  20. 19 19
      SecurePlayAuxServer/GlobalInfo/UniversalFunc.cpp
  21. 6 6
      SecurePlayAuxServer/SPAServer.cpp
  22. 1 1
      SecurePlayAuxServer/communication/FromRedis.cpp
  23. 97 70
      SecurePlayAuxServer/communication/FromWebAPI.cpp
  24. 1 1
      SecurePlayAuxServer/communication/FromWebAPI.h
  25. 16 0
      jsons/人员计数.json
  26. 16 0
      jsons/玩手机识别.json
  27. 3 0
      存在的问题

+ 1 - 1
SQL/SecurePlay.sqlbook

@@ -101,7 +101,7 @@ VALUES (:roomID, :camerID);
 SELECT *
 FROM "tAlarmInfo";
 
-#倒显示报警信息
+#倒显示报警信息
 SELECT *
 FROM "tAlarmInfo"
 ORDER BY "PKID" DESC;

+ 46 - 8
SecurePlayAuxServer/Application/FuncBase.cpp

@@ -122,21 +122,51 @@ bool FuncBase::initDataInterface()
     return true;
 }
 
-
-/* 判断是否在检测时间内 */
-bool FuncBase::isInDetectTime(const QDateTime& start, const QDateTime& end)
+/* 读取Redis数据 */
+void FuncBase::readRedisData(ListAlarmInfo& listAlarmInfo)
 {
-    QDateTime now = QDateTime::currentDateTime();
-    if(start.isValid() && end.isValid())
+    /* 清空报警信息 */
+    listAlarmInfo.clearAlarmInfo();
+
+    for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
     {
-        if(now >= start && now <= end)
+        for(const auto& it : roomInfo.mapCameraAction)
         {
-            return true;
+            for(const auto& act : it.second)
+            {
+                std::string strKey = std::to_string(it.first) + ":" + act;
+                std::string strRetValue;
+                if(!m_fromRedis->getRedisString(strKey, strRetValue))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey);
+                    continue;
+                }
+
+                /* 解析数据 */
+                AlarmInfo newAlarmInfo;
+                newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+                newAlarmInfo.RoomID = roomInfo.RoomID;
+                newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+                newAlarmInfo.ActionID = act;
+
+                parseRedisBaseData(strRetValue, newAlarmInfo);
+                parseOtherDataPersonCount(strRetValue, newAlarmInfo);
+                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+                if(!isEventTimeVaild(newAlarmInfo.EventTime))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
+                            m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
+                    continue;
+                }
+                listAlarmInfo.addAlarmInfo(newAlarmInfo);
+                printRawDataInfo(roomInfo, strKey, newAlarmInfo);
+            }
         }
     }
-    return false;
 }
 
+
+
 /* 更新检测时间范围,一定时间更新一次,不是每次都更新 */
 bool FuncBase::updateDetectTime(DetectPeriodInfo& periodInfo)
 {
@@ -235,3 +265,11 @@ bool FuncBase::isEventTimeVaild(const QDateTime& eventTime)
     return true;
 }
 
+/* 打印一些原始数据信息 */
+void FuncBase::printRawDataInfo(const RoomCamActInfo& roomInfo, const std::string& strKey, const AlarmInfo& alarmInfo)
+{
+    SPDLOG_LOGGER_DEBUG(m_logger, "{:<40} 报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
+        m_baseLog, strKey, roomInfo.RoomID, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+        alarmInfo.listBbox.size(), alarmInfo.listPersonInfo.size());
+}
+

+ 5 - 2
SecurePlayAuxServer/Application/FuncBase.h

@@ -40,8 +40,8 @@ protected:
     /* 初始化数据接口 */
     bool initDataInterface();
 
-    /* 判断是否在检测时间内,不检测日期,只检测时间 */
-    bool isInDetectTime(const QDateTime& start, const QDateTime& end);
+    /* 读取Redis数据 */
+    void readRedisData(ListAlarmInfo& listAlarm);
 
     /* 更新检测时间范围,一定时间更新一次,不是每次都更新 */
     inline bool updateDetectTime(DetectPeriodInfo& periodInfo);
@@ -50,6 +50,9 @@ protected:
 
     /* 判断报警数据有效时间 */
     bool isEventTimeVaild(const QDateTime& eventTime);
+
+    /* 打印一些原始数据信息 */
+    void printRawDataInfo(const RoomCamActInfo& roomInfo, const std::string& strKey, const AlarmInfo& alarmInfo);
     
 
 protected:

+ 101 - 69
SecurePlayAuxServer/Application/FuncIllegalInvasion.cpp

@@ -15,7 +15,7 @@ RoomIllegalInvasionInfo::RoomIllegalInvasionInfo(const RoomIllegalInvasionInfo&
     RoomType = o.RoomType;
     numMaxFace = o.numMaxFace;
     numMaxPerson = o.numMaxPerson;
-    strBoxList = o.strBoxList;
+    listBBox = o.listBBox;
     strMessage = o.strMessage;
     strImage = o.strImage;
     CameraID = o.CameraID;
@@ -28,7 +28,7 @@ RoomIllegalInvasionInfo& RoomIllegalInvasionInfo::operator=(const RoomIllegalInv
         RoomType = o.RoomType;
         numMaxFace = o.numMaxFace;
         numMaxPerson = o.numMaxPerson;
-        strBoxList = o.strBoxList;
+        listBBox = o.listBBox;
         strMessage = o.strMessage;
         strImage = o.strImage;
         CameraID = o.CameraID;
@@ -170,17 +170,11 @@ FuncIllegalInvasion::FuncIllegalInvasion()
         SPDLOG_ERROR("SPAServer logger is nullptr");
         return;
     }
-    m_pListAlarm = std::make_shared<std::list<AlarmInfo>>();
     m_pListIllInfo = std::make_shared<ListIllegalInvasionInfo>();
 }
 
 FuncIllegalInvasion::~FuncIllegalInvasion()
 {
-    if(m_pListAlarm != nullptr)
-    {
-        m_pListAlarm.reset();
-        m_pListAlarm = nullptr;
-    }
     if(m_pListIllInfo != nullptr)
     {
         m_pListIllInfo.reset();
@@ -209,6 +203,8 @@ void FuncIllegalInvasion::task()
 
     while (GThreadInfo.getRunning())
     {   
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
+
         /* 更新线程信息 */
         GThreadInfo.updateFuncInfo(m_funcThreadInfo);
         if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
@@ -217,52 +213,23 @@ void FuncIllegalInvasion::task()
         }
 
         /* 判断是否在检测时间段内 */
-        if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
+        if(!isInDetectTime(m_periodInfo))
         {
-            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
         /* 更新算法ActionID */
         {
             GVariable.mutexRW.lockForRead();
-            strFaceActionID = GVariable.ActFaceIdentify;
-            strCountActionID = GVariable.ActPersonCount;
+            strFaceActionID = GVariable.ActFaceIdentify();
+            strCountActionID = GVariable.ActPersonCount();
             GVariable.mutexRW.unlock();
         }
 
-        /* 读取Redis数据 */
-        m_pListAlarm->clear();
-        for(const auto& RoomInfo : m_funcThreadInfo.listRoomCamActInfo)
-        {
-            for(const auto& it : RoomInfo.mapCameraAction)
-            {
-                for(const auto& act : it.second)
-                {
-                    std::string strKey = std::to_string(it.first) + ":" + act;
-                    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(100));
-                        continue;
-                    }
-                    /* 解析数据 */
-                    AlarmInfo alarmInfo;
-                    // parseRedisData(strRetValue, alarmInfo);
-                    parseRedisBaseData(strRetValue, alarmInfo);
-                    parseRedisBBoxesData(strRetValue, alarmInfo);
-                    /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                    if(isEventTimeVaild(alarmInfo.EventTime))
-                    {
-                        SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                        continue;
-                    }
-                    m_pListAlarm->push_back(alarmInfo);
-                }
-            }
-        }
+        /* -----------------------------------------------------------------------
+         * 读取Redis数据
+         * ----------------------------------------------------------------------- */
+        readRedisData(m_listSrcAlarm);
 
         /* 找出房间的个数,按照房间进行判断 */
         ListRoomIll listRoomIll;
@@ -271,36 +238,42 @@ void FuncIllegalInvasion::task()
             listRoomIll.addRoom(it.RoomID, it.RoomType);
         }
 
+
+        /* -----------------------------------------------------------------------
+         * 处理读取到的数据
+         * ----------------------------------------------------------------------- */
+
         /* 根据房间解析人脸识别的非法入侵,检测到了非法人脸,就可以直接报警了 */
         for(auto& room : listRoomIll.getData())
         {
-            for(const auto& alarm : *m_pListAlarm)
+            /* 对获取到的数据挨个判断 */
+            for(const auto& alarm : m_listSrcAlarm.listAlarmInfo)
             {
-                if(room.RoomID != alarm.RoomID)
+                if(room.RoomID != alarm->RoomID)
                 {
                     continue;
                 }
                 /* 统计这个房间内《人脸算法》检测到的最大人员数 */
-                if(alarm.ActionID == strFaceActionID)
+                if(alarm->ActionID == strFaceActionID)
                 {
-                    if(alarm.listPersonInfo.size() > room.numMaxFace)
+                    if(alarm->listPersonInfo.size() > room.numMaxFace)
                     {
-                        room.numMaxFace = alarm.listPersonInfo.size();
-                        room.strBoxList = alarm.listBbox;
-                        room.listPersonInfo = alarm.listPersonInfo;
+                        room.numMaxFace = alarm->listPersonInfo.size();
+                        room.listBBox = alarm->listBbox;
+                        room.listPersonInfo = alarm->listPersonInfo;
                     }
                 }
 
                 /* 判断有没有非法入侵人员 */
-                if(isAlarm(alarm.listPersonInfo))
+                if(isAlarm(alarm->listPersonInfo))
                 {
                     room.isAlarm = true;
                     room.strMessage = "人员非法入侵(未知人员)";
-                    if( !alarm.ImageInfo.empty() )
+                    if( !alarm->ImageInfo.empty() )
                     {
-                        room.strImage = alarm.ImageInfo;
+                        room.strImage = alarm->ImageInfo;
                     }
-                    room.CameraID = alarm.DeviceID;
+                    room.CameraID = alarm->DeviceID;
                 }
             }
             
@@ -311,28 +284,29 @@ void FuncIllegalInvasion::task()
         {
             if(room.isAlarm)
             {
+                /* 上面的人脸识别算法已经识别到非法入侵了 */
                 continue;
             }
             /* 这个房间的人脸算法没有识别到非法入侵 */
-            for(const auto& alarm : *m_pListAlarm)
+            for(const auto& alarm : m_listSrcAlarm.listAlarmInfo)
             {
-                if(room.RoomID != alarm.RoomID)
+                if(room.RoomID != alarm->RoomID)
                 {
                     continue;
                 }
                 /* 人员计数 */
-                if(alarm.ActionID == strCountActionID)
+                if(alarm->ActionID == strCountActionID)
                 {
                     /* 统计这个房间内《人员计数算法》检测到的最大人员数 */
-                    if(alarm.listPersonInfo.size() > room.numMaxPerson)
+                    if(alarm->listBbox.size() > room.numMaxPerson)
                     {
-                        room.numMaxPerson = alarm.listPersonInfo.size();
-                        room.strBoxList = alarm.listBbox;
-                        if(!alarm.ImageInfo.empty())
+                        room.numMaxPerson = alarm->listBbox.size();
+                        room.listBBox = alarm->listBbox;
+                        if(!alarm->ImageInfo.empty())
                         {
-                            room.strImage = alarm.ImageInfo;
+                            room.strImage = alarm->ImageInfo;
                         }
-                        room.CameraID = alarm.DeviceID;
+                        room.CameraID = alarm->DeviceID;
                     }
                 }
             }
@@ -347,9 +321,9 @@ void FuncIllegalInvasion::task()
         /* 将非法入侵的信息存储到数组缓存中,等待报警结束后判断是否需要写入EQM数据库 */
         for(auto& room : listRoomIll.getData())
         {
-            auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType);
             if(room.isAlarm)
             {
+                auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType);
                 /* 正在报警,检查缓存中是否有这个报警信息 */
                 if(pIll == nullptr)
                 {
@@ -366,6 +340,12 @@ void FuncIllegalInvasion::task()
             }
             else 
             {
+                auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType);
+                if(pIll == nullptr)
+                {
+                    /* 没有报警,继续下一个房间 */
+                    continue;
+                }
                 /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */
                 QDateTime currTime = QDateTime::currentDateTime();
                 int secs = currTime.toSecsSinceEpoch() - pIll->FirstTime.toSecsSinceEpoch();
@@ -377,14 +357,14 @@ void FuncIllegalInvasion::task()
                         AlarmInfo ai;
                         ai.ChannelID = m_funcThreadInfo.ChannelID;
                         ai.RoomID = pIll->RoomID;
-                        ai.ActionID = GVariable.ActPersonCount;
+                        ai.ActionID = GVariable.ActPersonCount();
                         ai.ActionDes = pIll->strActionDec;
                         ai.ImageInfo = pIll->strImageInfo;
                         ai.StartTime = pIll->FirstTime;
                         ai.EndTime = currTime;
                         ai.EventTime = pIll->FirstTime;
                         ai.listPersonInfo = room.listPersonInfo;
-                        ai.listBbox = room.strBoxList;
+                        ai.listBbox = room.listBBox;
                         bool insertRet  = m_fromWebAPI->insertAlarmInfo(ai);
                         if(insertRet)
                         {
@@ -395,18 +375,70 @@ void FuncIllegalInvasion::task()
                     }
                     else {
                         SPDLOG_LOGGER_WARN(m_logger, "× 取消新增报警信息,因为没有图片,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸",
-                            pIll->ChannelID, pIll->RoomID, pIll->CameraID, pIll->strActionDec, pIll->strImageInfo, room.strBoxList.size(), room.listPersonInfo.size());
+                            pIll->ChannelID, pIll->RoomID, pIll->CameraID, pIll->strActionDec, pIll->strImageInfo, room.listBBox.size(), room.listPersonInfo.size());
                     }
                     /* 删除这个非法入侵信息 */
                     m_pListIllInfo->deleteIllInfo(*pIll);
                 }
             }
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
+
     }
 
+    m_listSrcAlarm.clearAlarmInfo();
 }
 
 
+/* 读取Redis数据 */
+// void FuncIllegalInvasion::readRedisData()
+// {
+//     m_listSrcAlarm.clearAlarmInfo();
+//     /* 读取Redis数据 */
+//     for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
+//     {
+//         for(const auto& cam : roomInfo.mapCameraAction)
+//         {
+//             for(const auto act : cam.second)
+//             {
+//                 /* 读取Redis数据 */
+//                 std::string strKey = std::to_string(cam.first) + ":" + act;
+//                 std::string strRetValue;
+//                 // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
+//                 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 newAlarmInfo;
+//                 newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+//                 newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+//                 newAlarmInfo.RoomID = roomInfo.RoomID;
+//                 newAlarmInfo.DeviceID = cam.first;
+//                 newAlarmInfo.ActionID = act;
+                
+
+//                 parseRedisBaseData(strRetValue, newAlarmInfo);
+//                 parseRedisBBoxesData(strRetValue, newAlarmInfo);
+//                 /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+//                 if(!isEventTimeVaild(newAlarmInfo.EventTime))
+//                 {
+//                     /* 事件时间超过600秒,可能是超脑挂了 */
+//                     SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
+//                     continue;
+//                 }
+//                 m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
+//                 SPDLOG_LOGGER_DEBUG(m_logger, "报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
+//                                     strKey, roomInfo.RoomID, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+//                                     newAlarmInfo.listBbox.size(), newAlarmInfo.listPersonInfo.size());
+//             }
+//         }
+//     }
+// }
+
+
 
 

+ 7 - 2
SecurePlayAuxServer/Application/FuncIllegalInvasion.h

@@ -33,7 +33,7 @@ struct RoomIllegalInvasionInfo
     int numMaxFace = 0;                     /* 最大人脸数 */
     int numMaxPerson = 0;                   /* 最大人员数 */
     int CameraID = 0;                       /* 摄像机ID,这个存储的是使用的哪个报警信息的ID */
-    std::list<std::string> strBoxList;      /* box */
+    std::list<std::string> listBBox;        /* box */
     std::string strMessage;                 /* 报警信息字符串 */
     std::string strImage;                   /* 报警图片 */
     std::list<PersonInfo> listPersonInfo;  /* 人员信息 */
@@ -119,9 +119,14 @@ protected:
     /* 线程功能 */
     void task() override;
 
+private:
+    /* 读取Redis数据 */
+    // void readRedisData();
+
 private:
     /* 保存每个摄像机的报警信息 */
-    std::shared_ptr<std::list<AlarmInfo>> m_pListAlarm = nullptr;
+    ListAlarmInfo m_listSrcAlarm;              /* 房间和算法ID关联列表 */
+    // std::shared_ptr<std::list<AlarmInfo>> m_pListAlarm = nullptr;
     /* 保存非法入侵的信息 */
     std::shared_ptr<ListIllegalInvasionInfo> m_pListIllInfo = nullptr;
 

+ 231 - 145
SecurePlayAuxServer/Application/FuncOnAndOffJob.cpp → SecurePlayAuxServer/Application/FuncOnAndOffWork.cpp

@@ -1,4 +1,4 @@
-#include "FuncOnAndOffJob.h"
+#include "FuncOnAndOffWork.h"
 #include "GlobalVariable.h"
 #include "GlobalConfig.h"
 #include "UniversalFunc.h"
@@ -234,32 +234,30 @@ bool RoomOnWorkInfo::isLeaveTimeExist(const QDateTime& time)
 
 
 
-FuncOnAndOffJob::FuncOnAndOffJob()
+FuncOnAndOffWork::FuncOnAndOffWork()
 {
-    m_pListAlarm = new ListAlarmInfo();
     m_logger = spdlog::get("SPAServer");
     if(m_logger == nullptr)
     {
-        SPDLOG_ERROR("FuncOnAndOffJob logger is nullptr");
+        SPDLOG_ERROR("FuncOnAndOffWork logger is nullptr");
         return;
     }
 
 }
 
-FuncOnAndOffJob::~FuncOnAndOffJob()
+FuncOnAndOffWork::~FuncOnAndOffWork()
 {
-    if(m_pListAlarm != nullptr)
-    {
-        delete m_pListAlarm;
-        m_pListAlarm = nullptr;
-    }
+    
 }
 
 
-void FuncOnAndOffJob::task()
+void FuncOnAndOffWork::task()
 {
     while(GThreadInfo.getRunning())
     {
+        /* 休眠一段时间 */
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
+        
         /* 判断是否需要退出 */
         if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
         {
@@ -267,162 +265,198 @@ void FuncOnAndOffJob::task()
         }
 
         /* 判断是否在检测时间段内 */
-        if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
+        if(!isInDetectTime(m_periodInfo))
         {
-            /* 休眠一段时间 */
-            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
-        /* 先获取所有的直播间,这里不需要读取所有的房间数据
-         * 理论上一个频率只有一个直播间 */
-        std::map<int, RoomCamActInfo> mapRoomCamActInfo;
-        for(auto& it : m_funcThreadInfo.listRoomCamActInfo)
+        
+        /* -----------------------------------------------------------------------
+         * 读取Redis数据(读取全部的数据,后面根据不同情况自己处理)
+         * ----------------------------------------------------------------------- */
+        readRedisData(m_listSrcAlarm);
+
+        /* -----------------------------------------------------------------------
+         * 处理数据 
+         * ----------------------------------------------------------------------- */
+        
+        /* 记录人员在岗情况 */
+        recordPersonOnWork();
+        /* 处理直播间在岗离岗报警情况 */
+        processRoomOnWorkAlarm();
+        
+    }
+
+    /* 清空数据 */
+    for(auto& it : m_mapRoomOnWorkInfo)
+    {
+        delete it.second;
+    }
+    m_mapRoomOnWorkInfo.clear();
+
+    m_listSrcAlarm.clearAlarmInfo();
+
+}
+
+
+/* 记录在岗离岗情况 */
+void FuncOnAndOffWork::recordPersonOnWork()
+{
+    /* -----------------------------------------------------------------------
+     * 处理数据 
+     * ----------------------------------------------------------------------- */
+    /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
+    for(auto& alarmInfo : m_listSrcAlarm.listAlarmInfo)
+    {
+        /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
+        m_pListRoomFace->addRoomFaceInfo(*alarmInfo);
+    }
+    /* 计算人脸个数,每个房间逐个对比 */
+    m_nowTime = 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();
+        }
+        /* 判断是否需要写入数据库,一定时间写入一次,默认是10分钟写一次 */
+        if(m_nowTime.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GVariable.AppUpdateOnWorkTimeInterval_Time)
         {
-            /* 判断是不是直播间 */
-            if(it.RoomType == Enum_RoomType::ROOM_LIVE)
+            /* 写入数据库 */
+            if(m_fromWebAPI->insertOnWorkInfo(*it))
             {
-                mapRoomCamActInfo.insert(std::make_pair(it.RoomID, 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;
+            }else {
+                SPDLOG_LOGGER_ERROR(m_logger, "写入数据库tWorkOnInfo失败");
             }
         }
+        ++it;
+    }
+}
 
-        /* 获取当前频率的在岗离岗信息,在表格“tChannel”中 */
-        if(!getCurrentFrequencyInfo(m_funcThreadInfo.ChannelID, m_nowChnDetecRule))
+/* 处理房间人员在岗离岗报警信息(这里只有直播间的在岗离岗报警) */
+void FuncOnAndOffWork::processRoomOnWorkAlarm()
+{
+    /* 先获取所有的直播间,这里不需要读取所有的房间数据
+     * 理论上一个频率只有一个直播间 */
+    std::map<int, RoomCamActInfo> mapRoomCamActInfo;
+    for(auto& it : m_funcThreadInfo.listRoomCamActInfo)
+    {
+        /* 判断是不是直播间 */
+        if(it.RoomType == Enum_RoomType::ROOM_LIVE)
         {
-            SPDLOG_LOGGER_ERROR(m_logger, "获取当前频率信息失败, ChannelID:{}", m_funcThreadInfo.ChannelID);
-            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
-            continue;
+            mapRoomCamActInfo.insert(std::make_pair(it.RoomID, it));
         }
+    }
 
-
-        /* 读取Redis数据 */
-        for(const auto& RoomInfo : mapRoomCamActInfo)
+    /* 获取当前频率的在岗离岗信息,在表格“tChannel”中 */
+    if(!getCurrentFrequencyInfo(m_funcThreadInfo.ChannelID, m_nowChnDetecRule))
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "{} 获取在岗离岗信息失败", m_baseLog);
+        return;
+    }
+    /* 获取当前时间 */
+    m_nowTime = QDateTime::currentDateTime();
+    /* 创建本轮的临时变量 */
+    m_nowRoomOnWorkInfo.clear();
+    /* 对所有房间挨个判断 */
+    for(auto& roomInfo : mapRoomCamActInfo)
+    {
+        bool bHasPeople = false;
+        bool bOnWork = false;
+        m_strBaseInfo = fmt::format("频道[{}][{}], 房间[{}][{}]:", m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName, roomInfo.second.RoomID, roomInfo.second.strRoomName);
+        /* 先使用人员计数判断直播间有没有人,如果直播间有人,再使用人脸识别算法判断是否是认识的人(是认识的人才会被识别到) */
+        for(auto& alarm : m_listSrcAlarm.listAlarmInfo)
         {
-            /* it是摄像机信息,it.first是摄像机ID */
-            for(const auto& it : RoomInfo.second.mapCameraAction)
+            if(alarm->RoomID == roomInfo.first)
             {
-                for(const auto& act : it.second)
+                if(alarm->ActionID == GVariable.ActPersonCount())
                 {
-                    std::string strKey = std::to_string(it.first) + ":" + act;
-                    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(100));
-                        continue;
-                    }
-                    /* 解析数据 */
-                    AlarmInfo alarmInfo;
-                    parseRedisBaseData(strRetValue, alarmInfo);
-                    parseRedisBBoxesData(strRetValue, alarmInfo);
-                    /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                    if(isEventTimeVaild(alarmInfo.EventTime))
+                    if(alarm->listBbox.size() > 0)
                     {
-                        SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                        continue;
+                        bHasPeople = true;
+                        break;
                     }
-                    m_pListAlarm->addAlarmInfo(alarmInfo);
                 }
             }
         }
-
-        /* 获取当前时间 */
-        m_curTime = QDateTime::currentDateTime();
-        /* 创建本轮的临时变量 */
-        m_nowRoomOnWorkInfo.clear();
-        /* 对所有房间挨个判断 */
-        for(auto& roomInfo : mapRoomCamActInfo)
+        
+        /* 如果有人,记录可以识别到的人员信息,记录在岗时间 */
+        if(bHasPeople)
         {
-            bool bHasPeople = false;
-            bool bOnWork = false;
-            m_strBaseInfo = fmt::format("频道[{}][{}], 房间[{}][{}]:", m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName, roomInfo.second.RoomID, roomInfo.second.strRoomName);
-            /* 先使用人员计数判断直播间有没有人,如果直播间有人,再使用人脸识别算法判断是否是认识的人(是认识的人才会被识别到) */
-            for(auto& alarm : m_pListAlarm->listAlarmInfo)
+            for(auto& alarm : m_listSrcAlarm.listAlarmInfo)
             {
                 if(alarm->RoomID == roomInfo.first)
                 {
-                    if(alarm->ActionID == GVariable.ActPersonCount)
+                    if(alarm->ActionID == GVariable.ActFaceIdentify())
                     {
-                        if(alarm->listBbox.size() > 0)
+                        if(alarm->listPersonInfo.size() > 0)
                         {
-                            bHasPeople = true;
-                            break;
+                            bOnWork = true;
+                            /* 记录人员信息 */
+                            m_nowRoomOnWorkInfo.addPersonInfo(alarm->listPersonInfo);
+                            /* 更新在岗时间 */
+                            m_nowRoomOnWorkInfo.updateOnWorkTime(m_nowTime);
                         }
                     }
                 }
             }
-            
-            /* 如果有人,记录可以识别到的人员信息,记录在岗时间 */
-            if(bHasPeople)
-            {
-                for(auto& alarm : m_pListAlarm->listAlarmInfo)
-                {
-                    if(alarm->RoomID == roomInfo.first)
-                    {
-                        if(alarm->ActionID == GVariable.ActFaceIdentify)
-                        {
-                            if(alarm->listPersonInfo.size() > 0)
-                            {
-                                bOnWork = true;
-                                /* 记录人员信息 */
-                                m_nowRoomOnWorkInfo.addPersonInfo(alarm->listPersonInfo);
-                                /* 更新在岗时间 */
-                                m_nowRoomOnWorkInfo.updateOnWorkTime(m_curTime);
-                            }
-                        }
-                    }
-                }
-            }
-
-            /* 查找这个房间对应的房间信息 */
-            RoomOnWorkInfo* pRoomOnWorkInfo = nullptr;
-            auto it0 = m_mapRoomOnWorkInfo.find(roomInfo.first);
-            if(it0 != m_mapRoomOnWorkInfo.end())
-            {
-                pRoomOnWorkInfo = it0->second;
-            }
-            else
-            {
-                /* 没找到,就创建一个 */
-                pRoomOnWorkInfo = new RoomOnWorkInfo();
-                pRoomOnWorkInfo->bOnWork = bOnWork;
-                pRoomOnWorkInfo->ChannelID = m_funcThreadInfo.ChannelID;
-                pRoomOnWorkInfo->RoomID = roomInfo.first;
-                pRoomOnWorkInfo->RoomID = roomInfo.second.RoomID;
-                pRoomOnWorkInfo->RoomType = roomInfo.second.RoomType;
-                pRoomOnWorkInfo->StartTime = m_curTime;
-                pRoomOnWorkInfo->strImagePath = m_nowRoomOnWorkInfo.strImagePath;
-                pRoomOnWorkInfo->listPersonInfo = m_nowRoomOnWorkInfo.listPersonInfo;
-
-                m_mapRoomOnWorkInfo.insert(std::make_pair(roomInfo.first, pRoomOnWorkInfo));
-            }
-            if(pRoomOnWorkInfo == nullptr)
-            {
-                SPDLOG_LOGGER_ERROR(m_logger, "创建房间在岗信息失败,频率ID:{},房间ID:{}", m_funcThreadInfo.ChannelID, roomInfo.first);
-                continue;
-            }
-
-            /* 处理此次在岗和离岗 */
-            if(bOnWork)
-            {
-                /* 在岗 */
-                onWorkProcess(pRoomOnWorkInfo, roomInfo);
-            } else 
-            {
-                /* 离岗 */
-                offWorkProcess(pRoomOnWorkInfo, roomInfo);
-            }
-
+        }
+        /* 查找这个房间对应的房间信息 */
+        RoomOnWorkInfo* pRoomOnWorkInfo = nullptr;
+        auto it0 = m_mapRoomOnWorkInfo.find(roomInfo.first);
+        if(it0 != m_mapRoomOnWorkInfo.end())
+        {
+            pRoomOnWorkInfo = it0->second;
+        }
+        else
+        {
+            /* 没找到,就创建一个 */
+            pRoomOnWorkInfo = new RoomOnWorkInfo();
+            pRoomOnWorkInfo->bOnWork = bOnWork;
+            pRoomOnWorkInfo->ChannelID = m_funcThreadInfo.ChannelID;
+            pRoomOnWorkInfo->RoomID = roomInfo.first;
+            pRoomOnWorkInfo->RoomID = roomInfo.second.RoomID;
+            pRoomOnWorkInfo->RoomType = roomInfo.second.RoomType;
+            pRoomOnWorkInfo->StartTime = m_nowTime;
+            pRoomOnWorkInfo->strImagePath = m_nowRoomOnWorkInfo.strImagePath;
+            pRoomOnWorkInfo->listPersonInfo = m_nowRoomOnWorkInfo.listPersonInfo;
+            m_mapRoomOnWorkInfo.insert(std::make_pair(roomInfo.first, pRoomOnWorkInfo));
+        }
+        if(pRoomOnWorkInfo == nullptr)
+        {
+            SPDLOG_LOGGER_ERROR(m_logger, "{} 创建房间在岗信息失败, 房间: {}", m_baseLog, roomInfo.second.strRoomName);
+            continue;
+        }
+        /* 处理此次在岗和离岗 */
+        if(bOnWork)
+        {
+            /* 在岗 */
+            onWorkProcess(pRoomOnWorkInfo, roomInfo);
+        } else 
+        {
+            /* 离岗 */
+            offWorkProcess(pRoomOnWorkInfo, roomInfo);
         }
     }
-
 }
 
 
 
+
 /* 获取当前频率信息 */
-bool FuncOnAndOffJob::getCurrentFrequencyInfo(const int ChannelID, DecCondition& info)
+bool FuncOnAndOffWork::getCurrentFrequencyInfo(const int ChannelID, DecCondition& info)
 {
     auto str = m_fromWebAPI->getChannelInfo(ChannelID);
     if(str == "")
@@ -472,7 +506,7 @@ bool FuncOnAndOffJob::getCurrentFrequencyInfo(const int ChannelID, DecCondition&
  * @param pRoomOnWorkInfo 这个是内存中的记录,是历史记录
  * @param roomInfo 
  */
-void FuncOnAndOffJob::onWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo)
+void FuncOnAndOffWork::onWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo)
 {
     /* 判断上次是否在岗,上次是离岗,结束离岗报警 */
     if(pRoomOnWorkInfo->bOnWork == false)
@@ -483,15 +517,15 @@ void FuncOnAndOffJob::onWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<c
         {
             SPDLOG_LOGGER_INFO(m_logger, "·人员报警结束,{}", m_strBaseInfo);
             /* 结束报警,写入数据库 */
-            m_fromWebAPI->endAlarmInfoByPKID(pRoomOnWorkInfo->PKID, m_curTime);
+            m_fromWebAPI->endAlarmInfoByPKID(pRoomOnWorkInfo->PKID, m_nowTime);
             /* 删除离岗记录,重新开始 */
             pRoomOnWorkInfo->PKID = 0;
             pRoomOnWorkInfo->listLeaveTime.clear();
-            pRoomOnWorkInfo->StartTime = m_curTime;
+            pRoomOnWorkInfo->StartTime = m_nowTime;
         }else 
         {
             /* 没有写入数据库 */
-            SPDLOG_LOGGER_INFO(m_logger, "·{}人员离岗报警结束,结束时间:{}", m_strBaseInfo, m_curTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+            SPDLOG_LOGGER_INFO(m_logger, "·{}人员离岗报警结束,结束时间:{}", m_strBaseInfo, m_nowTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
         }
     }
     pRoomOnWorkInfo->bOnWork = true;
@@ -574,7 +608,7 @@ void FuncOnAndOffJob::onWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<c
         }else 
         {
             /* 人员信息没有变化,更新在岗时间 */
-            pRoomOnWorkInfo->updateOnWorkTime(m_curTime);
+            pRoomOnWorkInfo->updateOnWorkTime(m_nowTime);
             SPDLOG_LOGGER_DEBUG(m_logger, "人员信息没有变化,更新在岗时间: {}", m_nowRoomOnWorkInfo.getLastOnWorkTimeString());
         }
 
@@ -596,7 +630,7 @@ void FuncOnAndOffJob::onWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<c
  * @param pRoomOnWorkInfo 
  * @param roomInfo 
  */
-void FuncOnAndOffJob::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo)
+void FuncOnAndOffWork::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo)
 {
     if(true == pRoomOnWorkInfo->bOnWork)
     {
@@ -608,16 +642,16 @@ void FuncOnAndOffJob::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<
         {
             SPDLOG_LOGGER_INFO(m_logger, "人员在岗结束(PKID:{}),离岗开始,{}", pRoomOnWorkInfo->PKID, m_strBaseInfo);
             /* 更新数据库,结束在岗 */
-            m_fromWebAPI->endAlarmInfoByPKID(pRoomOnWorkInfo->PKID, m_curTime);
+            m_fromWebAPI->endAlarmInfoByPKID(pRoomOnWorkInfo->PKID, m_nowTime);
             pRoomOnWorkInfo->PKID = 0;
-            pRoomOnWorkInfo->StartTime = m_curTime;
+            pRoomOnWorkInfo->StartTime = m_nowTime;
         }else 
         {
             /* 没有写入数据库 */
             SPDLOG_LOGGER_INFO(m_logger, "人员在岗结束,离岗开始,{}", m_strBaseInfo);
         }
 
-        pRoomOnWorkInfo->addOneLeaveTime(m_curTime, m_nowChnDetecRule.leaveTimeMaxNum);
+        pRoomOnWorkInfo->addOneLeaveTime(m_nowTime, m_nowChnDetecRule.leaveTimeMaxNum);
         auto strLeaveTime = pRoomOnWorkInfo->getLeaveTimeString();
         if(strLeaveTime != "")
         {
@@ -638,7 +672,7 @@ void FuncOnAndOffJob::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<
         /* 没有写入数据库,现在写入 */
         
         /* 判断单次离岗超时,计算时间差,leaveOneTime设置为0表示不启用检测 */
-        int nLeaveTime = pRoomOnWorkInfo->StartTime.secsTo(m_curTime);
+        int nLeaveTime = pRoomOnWorkInfo->StartTime.secsTo(m_nowTime);
         if(nLeaveTime > m_nowChnDetecRule.leaveOneTime && m_nowChnDetecRule.leaveOneTime > 0)
         {
             AlarmInfo alarmInfo;
@@ -693,7 +727,7 @@ void FuncOnAndOffJob::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<
             (m_nowChnDetecRule.leaveNumOnTime > 0) && (m_nowChnDetecRule.leaveTimeMaxNum > 0))
         {
             /* 计算距离第一次离岗时间长度 */
-            int nLeaveTime = pRoomOnWorkInfo->listLeaveTime.front().secsTo(m_curTime);
+            int nLeaveTime = pRoomOnWorkInfo->listLeaveTime.front().secsTo(m_nowTime);
             if(nLeaveTime <= m_nowChnDetecRule.leaveOneTime)
             {
                 AlarmInfo alarmInfo;
@@ -751,12 +785,12 @@ void FuncOnAndOffJob::offWorkProcess(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<
 
 
 /* 删除离岗人员和未知人员信息 */
-void FuncOnAndOffJob::deleteNoWorkPerson(std::list<PersonInfo>& listPersonInfo)
+void FuncOnAndOffWork::deleteNoWorkPerson(std::list<PersonInfo>& listPersonInfo)
 {
     /* 删除离岗人员 */
     for(auto it = listPersonInfo.begin(); it != listPersonInfo.end();)
     {
-        if((it->lastOnWork < m_curTime) || it->PersonID == "-1" || it->PersonID == "-2")
+        if((it->lastOnWork < m_nowTime) || it->PersonID == "-1" || it->PersonID == "-2")
         {
             it = listPersonInfo.erase(it);
         } else 
@@ -768,7 +802,7 @@ void FuncOnAndOffJob::deleteNoWorkPerson(std::list<PersonInfo>& listPersonInfo)
 }
 
 /* 获取当前直播间的摄像机名称列表 */
-std::list<std::string> FuncOnAndOffJob::getCameraNameList(const std::map<int, std::list<std::string>>& mapCameraAction)
+std::list<std::string> FuncOnAndOffWork::getCameraNameList(const std::map<int, std::list<std::string>>& mapCameraAction)
 {
     std::list<std::string> listCameraName;
     for(const auto& it : mapCameraAction)
@@ -780,7 +814,7 @@ std::list<std::string> FuncOnAndOffJob::getCameraNameList(const std::map<int, st
 
 
 /* 创建报警记录 */
-// void FuncOnAndOffJob::createAlarmInfo(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo, std::string actionDes, AlarmInfo& alarmInfo)
+// void FuncOnAndOffWork::createAlarmInfo(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo, std::string actionDes, AlarmInfo& alarmInfo)
 // {
 //     if(pRoomOnWorkInfo == nullptr)
 //     {
@@ -805,3 +839,55 @@ std::list<std::string> FuncOnAndOffJob::getCameraNameList(const std::map<int, st
 // }
 
 
+/* 读取Redis数据 */
+// void FuncOnAndOffWork::readRedisData()
+// {
+//     m_listSrcAlarm.clearAlarmInfo();
+//     /* 读取Redis数据 */
+//     for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
+//     {
+//         for(const auto& cam : roomInfo.mapCameraAction)
+//         {
+//             for(const auto act : cam.second)
+//             {
+//                 /* 读取Redis数据 */
+//                 std::string strKey = std::to_string(cam.first) + ":" + act;
+//                 std::string strRetValue;
+//                 // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
+//                 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 newAlarmInfo;
+//                 newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+//                 newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+//                 newAlarmInfo.RoomID = roomInfo.RoomID;
+//                 newAlarmInfo.DeviceID = cam.first;
+//                 newAlarmInfo.ActionID = act;
+                
+
+//                 parseRedisBaseData(strRetValue, newAlarmInfo);
+//                 parseRedisBBoxesData(strRetValue, newAlarmInfo);
+//                 /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+//                 if(!isEventTimeVaild(newAlarmInfo.EventTime))
+//                 {
+//                     /* 事件时间超过600秒,可能是超脑挂了 */
+//                     SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
+//                     continue;
+//                 }
+//                 m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
+//                 SPDLOG_LOGGER_DEBUG(m_logger, "报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
+//                                     strKey, roomInfo.RoomID, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+//                                     newAlarmInfo.listBbox.size(), newAlarmInfo.listPersonInfo.size());
+//             }
+//         }
+//     }
+// }
+
+
+

+ 18 - 12
SecurePlayAuxServer/Application/FuncOnAndOffJob.h → SecurePlayAuxServer/Application/FuncOnAndOffWork.h

@@ -1,5 +1,5 @@
-#ifndef FUNCONANDOFFJOB_H
-#define FUNCONANDOFFJOB_H
+#ifndef FUNCONANDOFFWORK_H
+#define FUNCONANDOFFWORK_H
 
 #include "FuncBase.h"
 
@@ -76,17 +76,22 @@ struct DecCondition
 
 
 
-class FuncOnAndOffJob : public FuncBase
+class FuncOnAndOffWork : public FuncBase
 {
 public:
-    FuncOnAndOffJob();
-    ~FuncOnAndOffJob();
+    FuncOnAndOffWork();
+    ~FuncOnAndOffWork();
 
 
 protected:
     void task() override;
 
 private:
+    /* 记录人员在岗情况 */
+    void recordPersonOnWork();
+    /* 处理房间人员在岗离岗报警信息(这里只有直播间的在岗离岗报警) */
+    void processRoomOnWorkAlarm();
+
     /* 获取当前频率信息 */
     bool getCurrentFrequencyInfo(const int ChannelID, DecCondition& info);
     /* 人员在岗情况 */
@@ -100,20 +105,21 @@ private:
     std::list<std::string> getCameraNameList(const std::map<int, std::list<std::string>>& mapCameraAction);
     /* 创建报警记录 */
     // void createAlarmInfo(RoomOnWorkInfo* pRoomOnWorkInfo, std::pair<const int, RoomCamActInfo>& roomInfo, std::string actionDes, AlarmInfo& alarmInfo);
-
+    /* 获取Redis数据 */
+    // void readRedisData();
+    
 
 private:
-    ListAlarmInfo* m_pListAlarm = nullptr;                  /* 报警信息 */
-    // std::map<int, ListAlarmInfo*> m_mapRoomPersonCount;     /* 人员计数返回的信息,int是房间ID号 */
-    // std::map<int, ListAlarmInfo*> m_mapRoomFaceInfo;        /* 人脸识别返回的信息,int是房间ID号 */
-    std::map<int, RoomOnWorkInfo*> m_mapRoomOnWorkInfo;      /* 房间在岗信息 */
+    ListAlarmInfo m_listSrcAlarm;                           /* 源报警信息 */
+    std::map<int, RoomOnWorkInfo*> m_mapRoomOnWorkInfo;     /* 房间在岗信息 */
+    
+    ListRoomFaceInfo* m_pListRoomFace = nullptr;            /* 人脸信息列表 */
 
     DecCondition m_nowChnDetecRule;                         /* 当前频率的在岗离岗的检测规则 */
     RoomOnWorkInfo m_nowRoomOnWorkInfo;                     /* 当前房间在岗信息 */
     std::string m_strBaseInfo;                              /* 基础信息,主要是频率ID和房间ID */
-    QDateTime m_curTime;                                    /* 当前时间 */
 };
 
 
 
-#endif /* FUNCONANDOFFJOB_H */
+#endif /* FUNCONANDOFFWORK_H */

+ 102 - 80
SecurePlayAuxServer/Application/FuncOrdinary.cpp

@@ -18,7 +18,8 @@ FuncOrdinary::FuncOrdinary()
 
 FuncOrdinary::~FuncOrdinary()
 {
-
+    m_listSrcAlarm.clearAlarmInfo();
+    m_listAlarmBuffer.clearAlarmInfo();
 }
 
 /* 任务线程 */
@@ -31,8 +32,6 @@ void FuncOrdinary::task()
     }
     /* 保存上次获取时间段的时间 */
     QDateTime lastTime = QDateTime::fromString("2025-05-07 00:00:00", "yyyy-MM-dd hh:mm:ss");
-    /* 创建临时的报警信息 */
-    std::list<AlarmInfo> listAlarmTemp;
 
     while (GThreadInfo.getRunning())
     {
@@ -45,7 +44,7 @@ void FuncOrdinary::task()
         if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
         {
             /* 退出线程 */
-            return;
+            break;
         }
 
         /* 判断是否在检测时间段内 */
@@ -56,88 +55,53 @@ void FuncOrdinary::task()
         // SPDLOG_LOGGER_DEBUG(m_logger, "{} 在检测时间段内", m_baseLog);
 
         /* ========================= 读取Redis数据 ========================= */
-        listAlarmTemp.clear();
-        /* 读取Redis数据 */
-        for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
-        {
-            for(const auto& cam : roomInfo.mapCameraAction)
-            {
-                for(const auto act : cam.second)
-                {
-                    /* 读取Redis数据 */
-                    std::string strKey = std::to_string(cam.first) + ":" + act;
-                    std::string strRetValue;
-                    // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
-                    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 newAlarmInfo;
-                    newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
-                    newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
-                    newAlarmInfo.RoomID = roomInfo.RoomID;
-                    newAlarmInfo.DeviceID = cam.first;
-                    newAlarmInfo.ActionID = act;
-                    
-
-                    parseRedisBaseData(strRetValue, newAlarmInfo);
-                    parseRedisBBoxesData(strRetValue, newAlarmInfo);
-                    /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                    if(!isEventTimeVaild(newAlarmInfo.EventTime))
-                    {
-                        /* 事件时间超过600秒,可能是超脑挂了 */
-                        SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                        continue;
-                    }
-                    listAlarmTemp.push_back(newAlarmInfo);
-                }
-            }
-        }
-        SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据成功, 报警数据数目: {}", m_listAlarm.listAlarmInfo.size());
+        readRedisData(m_listSrcAlarm);
+        // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据成功, 报警数据数目: {}", m_listAlarm.listAlarmInfo.size());
         
         // continue;
 
         /* ========================= 处理报警数据 ========================= */
 
-        for(auto newAlarm : listAlarmTemp)
+        for(auto newAlarm : m_listSrcAlarm.listAlarmInfo)
         {
             /* 找到该报警相关的房间信息 */
-            auto roomInfo = m_funcThreadInfo.findRoomInfo(newAlarm.RoomID);
+            auto roomInfo = m_funcThreadInfo.findRoomInfo(newAlarm->RoomID);
             if(roomInfo.RoomID == -1)
             {
-                SPDLOG_LOGGER_ERROR(m_logger, "{} 房间ID: {} 不存在", m_baseLog, newAlarm.RoomID);
+                SPDLOG_LOGGER_ERROR(m_logger, "{} 房间ID: {} 不存在", m_baseLog, newAlarm->RoomID);
                 continue;
             }
             /* 创建基础日志信息 */
-            std::string tmpBaseLog = fmt::format("{} 房间: {}, 摄像机ID: {}, 算法ID: {}", m_baseLog, roomInfo.strRoomName, newAlarm.DeviceID, newAlarm.ActionID);
+            std::string tmpBaseLog = fmt::format("{} 房间: {}, 摄像机ID: {}, 算法ID: {}", m_baseLog, roomInfo.strRoomName, newAlarm->DeviceID, newAlarm->ActionID);
             /* -------------------------------------------------------------------------------
             * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
             * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
             * 报警数据的结束时间,并清空pAlarmInfo 
             * ------------------------------------------------------------------------------- */
             /* 找出数组中与当前报警ID相同的的报警信息 */
-            auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarm);
+            auto pAlarmInfo = m_listAlarmBuffer.findAlarmInfo(*newAlarm);
             /* 没有找到报警记录,就新建一个 */
             if(pAlarmInfo == nullptr)
             {
+                /* 判断这条记录有没有报警,没有就不做任何处理 */
+                if(!newAlarm->Is_Alarm)
+                {
+                    // SPDLOG_LOGGER_TRACE(m_logger, "{}, 没有报警,直接跳过", tmpBaseLog);
+                    continue;
+                }
                 /* 新记录有报警,新建报警记录 */
-                if(newAlarm.Is_Alarm)
+                if(newAlarm->Is_Alarm)
                 {
-                    /* 图片不能是空,如果是空的,就不写入数据库 */
-                    if(!newAlarm.ImageInfo.empty())
+                    /* 图片不能是空,如果是空的,就不写入数据库,现在是先加入缓存中 */
+                    if(!newAlarm->ImageInfo.empty())
                     {
                         /* 违禁品检测,开始时间是事件时间 */
-                        newAlarm.StartTime = newAlarm.EventTime;
-                        newAlarm.EndTime = GVariable.nullTime;
+                        newAlarm->StartTime = newAlarm->EventTime;
+                        newAlarm->EndTime = GVariable.nullTime;
                         /* 保存新的报警记录 */
-                        newAlarm.Is_InsertEQM = false;
-                        m_listAlarm.addAlarmInfo(newAlarm);
-                        SPDLOG_LOGGER_DEBUG(m_logger, "{} 新的报警,加入到缓存中", tmpBaseLog);
+                        newAlarm->Is_InsertEQM = false;
+                        m_listAlarmBuffer.addAlarmInfo(*newAlarm);
+                        SPDLOG_LOGGER_INFO(m_logger, "{} 新的报警,加入到缓存中", tmpBaseLog);
                     }else 
                     {
                         SPDLOG_LOGGER_WARN(m_logger, "{}, 有报警区域, 但是没有图片信息", tmpBaseLog);
@@ -147,12 +111,12 @@ void FuncOrdinary::task()
             {
                 /* 已有报警记录 */
                 /* 更新图片信息 */
-                if(!newAlarm.ImageInfo.empty())
+                if(!newAlarm->ImageInfo.empty())
                 {
-                    pAlarmInfo->ImageInfo = newAlarm.ImageInfo;
+                    pAlarmInfo->ImageInfo = newAlarm->ImageInfo;
                 }
-                /* 判断是否还在报警中 */
-                if(newAlarm.Is_Alarm)
+                /* 判断这条记录有无报警 */
+                if(newAlarm->Is_Alarm)
                 {
                     /* 正在报警中,检查是否已经写入到数据库中 */
                     if(pAlarmInfo->Is_InsertEQM)
@@ -161,16 +125,18 @@ void FuncOrdinary::task()
                     }else 
                     {
                         /* 判断报警时长间隔是否足够 */
-                        if(!isAlarmTimeVaild(*pAlarmInfo))
+                        if(!isOutAlarmTimeVaild(*pAlarmInfo))
                         {
                             /* 不够报警时间,直接进行下一个循环 */
                             continue;
                         }
                         /* 写入到数据库 */
                         pAlarmInfo->Is_InsertEQM = false;
-                        if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo))
+                        int pkid = 0;
+                        if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo, pkid))
                         {
                             pAlarmInfo->Is_InsertEQM = true;
+                            pAlarmInfo->PKID = pkid;
                         }else {
                             SPDLOG_LOGGER_ERROR(m_logger, "{} 写入tAlarmInfo报警数据失败! ", tmpBaseLog);
                         }
@@ -179,28 +145,34 @@ void FuncOrdinary::task()
                     
                 } else 
                 {
-                    /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
-                    * 更新数据库结束时间,结束时间是此时电脑时间 */
-                    if(isAlarmTimeVaild(*pAlarmInfo))
+                    /* 报警结束,先判断有无写入数据库,已经写入,直接结束报警
+                     * 没有写入数据库,判断时长,如果小于设置的最小间隔,可能是误报警
+                     * 更新数据库结束时间,结束时间是此时电脑时间 */
+                    pAlarmInfo->EndTime = m_nowTime;
+                    /* 判断是否已经写入到数据库中 */
+                    if(pAlarmInfo->Is_InsertEQM)
                     {
-                        pAlarmInfo->EndTime = m_nowTime;
-                        /* 判断是否已经写入到数据库中 */
-                        if(pAlarmInfo->Is_InsertEQM)
+                        /* 已经写入到数据库中,更新结束时间 */
+                        m_fromWebAPI->endAlarmInfoByPKID(pAlarmInfo->PKID, m_nowTime);
+                    }else 
+                    {
+                        /* 判断报警时长间隔是否足够 */
+                        if(isOutAlarmTimeVaild(*pAlarmInfo))
                         {
-                            /* 已经写入到数据库中,更新结束时间 */
-                            m_fromWebAPI->updateAlarmEndTime(*pAlarmInfo);
-                        }else {
-                            /* 没有写入到数据库中,写入到数据库中 */
+                            /* 时长足够且没有写入到数据库中,写入到数据库中 */
                             m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
                         }
-                        SPDLOG_LOGGER_INFO(m_logger, "{}, 报警结束", tmpBaseLog);
                     }
-                    /* 删除这个报警信息 */
-                    m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
+                    SPDLOG_LOGGER_INFO(m_logger, "{} 报警结束", tmpBaseLog);
+                    /* 从缓存中删除这个报警信息 */
+                    m_listAlarmBuffer.deleteAlarmInfo(*pAlarmInfo);
                 }
             }
         }
     }
+
+    m_listSrcAlarm.clearAlarmInfo();
+    m_listAlarmBuffer.clearAlarmInfo();
 }
 
 /* old处理方法 */
@@ -326,7 +298,7 @@ void FuncOrdinary::oldTask()
 
 
 /* 判断报警时长是否符合不同应用的最小间隔 */
-bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
+bool FuncOrdinary::isOutAlarmTimeVaild(const AlarmInfo& info)
 {
     int alarmTime = 0;
     /* 违禁品物品 */
@@ -367,3 +339,53 @@ bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
     
     return true;
 }
+
+/* 读取Redis数据 */
+// void FuncOrdinary::readRedisData(std::list<AlarmInfo>& listAlarmTemp)
+// {
+//     listAlarmTemp.clear();
+//     /* 读取Redis数据 */
+//     for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
+//     {
+//         for(const auto& cam : roomInfo.mapCameraAction)
+//         {
+//             for(const auto act : cam.second)
+//             {
+//                 /* 读取Redis数据 */
+//                 std::string strKey = std::to_string(cam.first) + ":" + act;
+//                 std::string strRetValue;
+//                 // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
+//                 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 newAlarmInfo;
+//                 newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+//                 newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+//                 newAlarmInfo.RoomID = roomInfo.RoomID;
+//                 newAlarmInfo.DeviceID = cam.first;
+//                 newAlarmInfo.ActionID = act;
+                
+
+//                 parseRedisBaseData(strRetValue, newAlarmInfo);
+//                 parseRedisBBoxesData(strRetValue, newAlarmInfo);
+//                 /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+//                 if(!isEventTimeVaild(newAlarmInfo.EventTime))
+//                 {
+//                     /* 事件时间超过600秒,可能是超脑挂了 */
+//                     SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+//                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
+//                     continue;
+//                 }
+//                 listAlarmTemp.push_back(newAlarmInfo);
+                
+//                 printRawDataInfo(roomInfo, strKey, newAlarmInfo);
+//             }
+//         }
+//     }
+// }
+

+ 9 - 5
SecurePlayAuxServer/Application/FuncOrdinary.h

@@ -11,9 +11,9 @@ struct ListAlarmInfo;
             1、报警判断条件:机房内出现摄像头的违禁物品识别算法输出结果包含指定违规内容时,记为报警行为,直接
                 展示报警结果
             2、这里应该是不区分违禁物品是什么,只要有违禁物品就报警。如果一个违禁物品消失之前又出现了第二个违禁物品,
-                两个违禁物品都消失后,这次报警才会结束,也就是说,不会同时出现两个报警信息。
-            3、一有报警信息就写入到EQM数据库的tAlarmInfo表中,报警开始时间是EventTime
-            4、如果报警结束时间小于设置的最小间隔,就删除这条数据,超过这个时间,就更新结束时间
+                两个违禁物品都消失后,这次报警才会结束,也就是说,一个房间内不会同时出现两个报警信息。
+            3、有报警信息先写入到缓存中,报警持续超过设定的时间后再写入到EQM数据库的tAlarmInfo表中,报警开始时间是EventTime
+            4、如果报警结束时间小于设置的最小间隔,就从缓存中删除这条数据,超过这个时间,就更新结束时间
             5、报警信息要有图片,如果当前没有图片,就使用上一张图片
  * 
  * @param info 线程信息
@@ -33,10 +33,14 @@ protected:
 
 private:
     /* 判断报警时长是否符合不同应用的最小间隔 */
-    bool isAlarmTimeVaild(const AlarmInfo& info);
+    bool isOutAlarmTimeVaild(const AlarmInfo& info);
+
+    /* 读取Redis数据 */
+    // void readRedisData(std::list<AlarmInfo>& listAlarmTemp);
 
 private:
-    ListAlarmInfo m_listAlarm;                  /* 报警列表 */
+    ListAlarmInfo m_listSrcAlarm;                   /* 原始的报警信息 */
+    ListAlarmInfo m_listAlarmBuffer;                /* 报警列表缓存 */
 };
 
 #endif // FuncOrdinary_H

+ 64 - 41
SecurePlayAuxServer/Application/FuncPersonOnWork.cpp

@@ -15,8 +15,6 @@ FuncPersonOnWork::FuncPersonOnWork()
         return;
     }
     /* 给变量分配内存 */
-    /* 保存每个摄像机的报警信息 */
-    m_pListAlarm = std::make_shared<std::list<AlarmInfo>>();
     /* 保存人脸信息的数据 */
     m_pListRoomFace = new ListRoomFaceInfo();
 }
@@ -40,6 +38,8 @@ void FuncPersonOnWork::task()
     
     while (GThreadInfo.getRunning())
     {   
+        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
+        
         /* 更新线程信息 */
         GThreadInfo.updateFuncInfo(m_funcThreadInfo);
         if( (m_funcThreadInfo.appFunction == AppFunction::APP_NONE) ||
@@ -49,56 +49,28 @@ void FuncPersonOnWork::task()
         }
         
         /* 判断是否在检测时间段内 */
-        if(!isInDetectTime(m_funcThreadInfo.StartTime, m_funcThreadInfo.EndTime))
+        if(!isInDetectTime(m_periodInfo))
         {
-            std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
             continue;
         }
 
         /* -----------------------------------------------------------------------
          * 读取Redis数据 
          * ----------------------------------------------------------------------- */
-        m_pListAlarm->clear();
-        for(const auto& RoomInfo : m_funcThreadInfo.listRoomCamActInfo)
-        {
-            for(const auto& it : RoomInfo.mapCameraAction)
-            {
-                for(const auto& act : it.second)
-                {
-                    /* 读取Redis数据 */
-                    std::string strKey = std::to_string(it.first) + ":" + act;
-                    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 = act;
-                    parseRedisBaseData(strRetValue, alarmInfo);
-                    parseRedisBBoxesData(strRetValue, alarmInfo);
-                    /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                    if(isEventTimeVaild(alarmInfo.EventTime))
-                    {
-                        SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
-                        std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                        continue;
-                    }
-                    m_pListAlarm->push_back(alarmInfo);
-                }
-            }
-        }
+        readRedisData();
 
+
+        /* -----------------------------------------------------------------------
+         * 处理数据 
+         * ----------------------------------------------------------------------- */
         /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
-        for(auto& alarmInfo : *m_pListAlarm)
+        for(auto& alarmInfo : m_listSrcAlarm.listAlarmInfo)
         {
             /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
-            m_pListRoomFace->addRoomFaceInfo(alarmInfo);
+            m_pListRoomFace->addRoomFaceInfo(*alarmInfo);
         }
         /* 计算人脸个数,每个房间逐个对比 */
-        QDateTime now = QDateTime::currentDateTime();
+        m_nowTime = QDateTime::currentDateTime();
         for(auto it = m_pListRoomFace->listRoomFaceInfo.begin(); it != m_pListRoomFace->listRoomFaceInfo.end(); )
         {
             /* m_pListRoomFace的数据不会删除,会和历史对比,这里的MaxNum和MinNum就是历史数据 */
@@ -111,7 +83,7 @@ void FuncPersonOnWork::task()
                 it->MinNum = it->listPersonInfo.size();
             }
             /* 判断是否需要写入数据库,一定时间写入一次,默认是10分钟写一次 */
-            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GVariable.AppUpdateOnWorkTimeInterval_Time)
+            if(m_nowTime.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > GVariable.AppUpdateOnWorkTimeInterval_Time)
             {
                 /* 写入数据库 */
                 if(m_fromWebAPI->insertOnWorkInfo(*it))
@@ -130,10 +102,61 @@ void FuncPersonOnWork::task()
             }
             ++it;
         }
-        std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
+        
     }
+    m_listSrcAlarm.clearAlarmInfo();
 
 }
 
 
+/* 读取Redis数据 */
+void FuncPersonOnWork::readRedisData()
+{
+    m_listSrcAlarm.clearAlarmInfo();
+    /* 读取Redis数据 */
+    for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
+    {
+        for(const auto& cam : roomInfo.mapCameraAction)
+        {
+            for(const auto act : cam.second)
+            {
+                /* 读取Redis数据 */
+                std::string strKey = std::to_string(cam.first) + ":" + act;
+                std::string strRetValue;
+                // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
+                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 newAlarmInfo;
+                newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+                newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+                newAlarmInfo.RoomID = roomInfo.RoomID;
+                newAlarmInfo.DeviceID = cam.first;
+                newAlarmInfo.ActionID = act;
+                
+
+                parseRedisBaseData(strRetValue, newAlarmInfo);
+                parseRedisBBoxesData(strRetValue, newAlarmInfo);
+                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+                if(!isEventTimeVaild(newAlarmInfo.EventTime))
+                {
+                    /* 事件时间超过600秒,可能是超脑挂了 */
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    continue;
+                }
+                m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
+                SPDLOG_LOGGER_DEBUG(m_logger, "报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
+                                    strKey, roomInfo.RoomID, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), 
+                                    newAlarmInfo.listBbox.size(), newAlarmInfo.listPersonInfo.size());
+            }
+        }
+    }
+}
+
 

+ 7 - 6
SecurePlayAuxServer/Application/FuncPersonOnWork.h

@@ -6,11 +6,9 @@
 
 
 /**
- * @brief 人员在岗识别线程
+ * @brief 人员在岗情况识别线程,目前这个功能已经合并到了 FuncOnAndOffWork 中
  *        1、这个写入tWorkOnInfo表格,十分钟写一次,记录这十分钟内的在岗离岗的人员信息,同时记录这十分钟房间内
  *           的人员数量最大值和最小值。
- *        2、
- *        3、这个线程也会进行在岗离岗的识别报警
  * 
  */
 
@@ -24,9 +22,12 @@ protected:
     void task() override;
 
 private:
-    ListAlarmInfo m_listAlarm;                  /* 报警列表 */
-    /* 保存每个摄像机的报警信息 */
-    std::shared_ptr<std::list<AlarmInfo>> m_pListAlarm = nullptr;
+    /* 读取Redis数据 */
+    void readRedisData();
+
+private:
+    /* 报警列表 */
+    ListAlarmInfo m_listSrcAlarm;
     /* 保存人脸信息的数据 */
     ListRoomFaceInfo* m_pListRoomFace = nullptr;
 

+ 47 - 50
SecurePlayAuxServer/Application/FuncRegionalPerson.cpp

@@ -166,21 +166,11 @@ FuncRegionalPersonCount::FuncRegionalPersonCount()
         SPDLOG_ERROR("SPAServer logger is nullptr");
         return;
     }
-    m_pListAlarm = new ListAlarmInfo();
-    if(m_pListAlarm == nullptr)
-    {
-        SPDLOG_ERROR("FuncRegionalPersonDetection m_pListAlarm is nullptr");
-        return;
-    }
 }
 
 FuncRegionalPersonCount::~FuncRegionalPersonCount()
 {
-    if(m_pListAlarm != nullptr)
-    {
-        delete m_pListAlarm;
-        m_pListAlarm = nullptr;
-    }
+    m_listSrcAlarm.clearAlarmInfo();
 }
 
 
@@ -247,46 +237,11 @@ void FuncRegionalPersonCount::task()
         /* -----------------------------------------------------------------------
          * 读取Redis数据 
          * ----------------------------------------------------------------------- */
-        m_pListAlarm->clearAlarmInfo();
-
-        for(const auto& RoomInfo : m_listRoomCamAct)
-        {
-            for(const auto& it : RoomInfo.mapCameraAction)
-            {
-                for(const auto& act : it.second)
-                {
-                    std::string strKey = std::to_string(it.first) + ":" + act;
-                    std::string strRetValue;
-                    if(!m_fromRedis->getRedisString(strKey, strRetValue))
-                    {
-                        SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey);
-                        continue;
-                    }
-
-                    /* 解析数据 */
-                    AlarmInfo alarmInfo;
-                    alarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
-                    alarmInfo.RoomID = RoomInfo.RoomID;
-                    alarmInfo.appFunction = m_funcThreadInfo.appFunction;
-                    alarmInfo.ActionID = act;
-
-                    parseRedisBaseData(strRetValue, alarmInfo);
-                    parseOtherDataPersonCount(strRetValue, alarmInfo);
-                    /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
-                    if(!isEventTimeVaild(alarmInfo.EventTime))
-                    {
-                        SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
-                                m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
-                        continue;
-                    }
-                    m_pListAlarm->addAlarmInfo(alarmInfo);
-                }
-            }
-        }
+        readRedisData();
 
 
         // SPDLOG_LOGGER_DEBUG(m_logger, "房间数目: {}, 报警条目数目: {}", m_listRoomCamAct.size(), m_pListAlarm->listAlarmInfo.size());
-        // SPDLOG_LOGGER_DEBUG(m_logger, "报警人数: {}", m_pListAlarm->listAlarmInfo.front()->listPersonInfo.size());
+        // SPDLOG_LOGGER_DEBUG(m_logger, "报警人数: {}", m_pListAlarm->listAlarmInfo.front()->listBbox.size());
 
         /************ 挨个房间检测人数,取出每个房间内人数的最大值 ************/
         for(const auto& RoomInfo : m_listRoomCamAct)
@@ -336,6 +291,48 @@ void FuncRegionalPersonCount::task()
 
 }
 
+/* 读取Redis数据 */
+void FuncRegionalPersonCount::readRedisData()
+{
+    m_listSrcAlarm.clearAlarmInfo();
+
+    for(const auto& roomInfo : m_listRoomCamAct)
+    {
+        for(const auto& it : roomInfo.mapCameraAction)
+        {
+            for(const auto& act : it.second)
+            {
+                std::string strKey = std::to_string(it.first) + ":" + act;
+                std::string strRetValue;
+                if(!m_fromRedis->getRedisString(strKey, strRetValue))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey);
+                    continue;
+                }
+
+                /* 解析数据 */
+                AlarmInfo newAlarmInfo;
+                newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
+                newAlarmInfo.RoomID = roomInfo.RoomID;
+                newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
+                newAlarmInfo.ActionID = act;
+
+                parseRedisBaseData(strRetValue, newAlarmInfo);
+                parseOtherDataPersonCount(strRetValue, newAlarmInfo);
+                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+                if(!isEventTimeVaild(newAlarmInfo.EventTime))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
+                            m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
+                    continue;
+                }
+                m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
+                printRawDataInfo(roomInfo, strKey, newAlarmInfo);
+            }
+        }
+    }
+}
+
 /* 获取该频率的人员计数规则 */
 bool FuncRegionalPersonCount::getPersonCountRuleInfo()
 {
@@ -425,12 +422,12 @@ void FuncRegionalPersonCount::autoEndAlarm()
 bool FuncRegionalPersonCount::getRoomMaxNum(int roomID, int& maxNum, std::string& strImagePath)
 {
     strImagePath.clear();
-    for(auto it : m_pListAlarm->listAlarmInfo)
+    for(auto it : m_listSrcAlarm.listAlarmInfo)
     {
         if(it->RoomID == roomID)
         {
             /* 取出最大人数 */
-            int num = it->listPersonInfo.size();
+            int num = it->listBbox.size();
             if(num > maxNum)
             {
                 maxNum = num;

+ 4 - 1
SecurePlayAuxServer/Application/FuncRegionalPerson.h

@@ -90,6 +90,7 @@ struct AlarmBuffer
                警行为,直接展示报警结果
             3、直播间+录播间报警:当前频率直播间人数+录播间人数大于或小于设定人数值时,记为报警行为,直接展示
                报警结果
+            4、人员数目是看的bBox中的方框数目,不是用的PersonList数目,老代码是这么做的
  * 
  */
 class FuncRegionalPersonCount : public FuncBase
@@ -102,6 +103,8 @@ protected:
     void task() override;
 
 private:
+    /* 读取Redis数据 */
+    void readRedisData();
     /* 获取该频率的人员计数规则 */
     bool getPersonCountRuleInfo();
     /* 更新房间列表 */
@@ -126,7 +129,7 @@ private:
     void clearAlarmBufferMap();
 
 private:
-    ListAlarmInfo* m_pListAlarm = nullptr;                      /* 报警信息 */
+    ListAlarmInfo m_listSrcAlarm;                               /* 报警信息 */
     std::list<RoomCamActInfo> m_listRoomCamAct;                 /* 房间和算法ID关联列表,这里存储的是直播间和导播间的房间信息 */
     PersonCountRuleInfo m_personCountRule;                      /* 人员计数规则 */
 

+ 24 - 16
SecurePlayAuxServer/GlobalInfo/GlobalConfig.cpp

@@ -11,10 +11,18 @@ GlobalVariable::GlobalVariable()
 {
     ThreadSleepMS = 1000;
 
-    ActFaceIdentify.clear();
-    ActPersonCount.clear();
-    ActContraband.clear();
-    ActPlayPhone.clear();
+    m_actFaceIdentify.clear();
+    m_actPersonCount.clear();
+    m_actContraband.clear();
+    m_actPlayPhone.clear();
+    m_actFatigueDetection.clear();
+    m_actSleep.clear();
+    m_actMouseDetect.clear();
+    m_actNoMask.clear();
+    m_actAllDown.clear();
+    m_actAnimalDetect.clear();
+    m_mapAction.clear();
+    
 }
 
 std::string GlobalVariable::getActionName(const std::string& actionID) 
@@ -179,16 +187,16 @@ bool GlobalConfig::readAlgorithmConfig(const QString& strConfigFile)
     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 */
+    GVariable.m_actFaceIdentify = settings.value("FaceIdentify", "").toString().toStdString();      /* 人脸识别算法ID */
+    GVariable.m_actPersonCount = settings.value("PersonCount", "").toString().toStdString();        /* 人员计数算法ID */
+    GVariable.m_actPlayPhone = settings.value("PlayPhone", "").toString().toStdString();            /* 玩手机算法ID */
+    GVariable.m_actContraband = settings.value("Contraband", "").toString().toStdString();          /* 违禁品算法ID */
     settings.endGroup();
 
-    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, "违禁品检测"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.m_actFaceIdentify, "人脸识别"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.m_actPersonCount, "人员计数"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.m_actPlayPhone, "玩手机识别"));
+    GVariable.m_mapAction.insert(std::make_pair(GVariable.m_actContraband, "违禁品检测"));
 
     return true;
 }
@@ -197,10 +205,10 @@ bool GlobalConfig::readAlgorithmConfig(const QString& strConfigFile)
 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);
+    SPDLOG_DEBUG("人脸识别算法ID:       {}", GVariable.ActFaceIdentify());
+    SPDLOG_DEBUG("人员计数算法ID:       {}", GVariable.ActPersonCount());
+    SPDLOG_DEBUG("玩手机算法ID:         {}", GVariable.ActPlayPhone());
+    SPDLOG_DEBUG("违禁品算法ID:         {}", GVariable.ActContraband());
 }
 
 

+ 37 - 14
SecurePlayAuxServer/GlobalInfo/GlobalConfig.h

@@ -45,29 +45,30 @@ public:
     int ThreadSleepMS;                      /* 任务线程休眠时间,单位是ms */
     const int CheckDeviceTime = 20;         /* 从超脑平台检测设备的时间间隔,单位是秒 */
 
-    /* 算法ID,通过这个识别从超脑平台获取到的算法,这个算法ID是全的,带有后缀的 */
+    
+
+    QReadWriteLock mutexRW;               /* 读写锁 */
+
     /* 人脸识别算法ID */
-    std::string ActFaceIdentify;
+    std::string ActFaceIdentify() { return m_actFaceIdentify; }
     /* 人员统计算法ID */
-    std::string ActPersonCount;
+    std::string ActPersonCount() { return m_actPersonCount; }
     /* 违禁品算法ID */
-    std::string ActContraband;
+    std::string ActContraband() { return m_actContraband; }
     /* 玩手机算法ID */
-    std::string ActPlayPhone;
+    std::string ActPlayPhone() { return m_actPlayPhone; }
     /* 疲劳检测算法ID */
-    std::string ActFatigueDetection;
+    std::string ActFatigueDetection() { return m_actFatigueDetection; }
     /* 睡岗识别算法ID */
-    std::string ActSleep;
+    std::string ActSleep() { return m_actSleep; }
     /* 老鼠检测 */
-    std::string ActMouseDetect;
+    std::string ActMouseDetect() { return m_actMouseDetect; }
     /* 未戴口罩识别 */
-    std::string ActNoMask;
+    std::string ActNoMask() { return m_actNoMask; }
     /* 摔倒识别 */
-    std::string ActAllDown;
+    std::string ActAllDown() { return m_actAllDown; }
     /* 动物识别 */
-    std::string ActAnimalDetect;
-
-    QReadWriteLock mutexRW;               /* 读写锁 */
+    std::string ActAnimalDetect() { return m_actAnimalDetect; }
     
 
     std::string getActionName(const std::string& actionID);
@@ -79,7 +80,29 @@ public:
 
     /* 设置一个空时间,设置这个时间,在数据库里都是空 */
     const QDateTime nullTime = QDateTime::fromString("2000-01-01 00:00:00", "yyyy-MM-dd hh:mm:ss");
-    
+
+private:
+    /* 算法ID,通过这个识别从超脑平台获取到的算法,这个算法ID是全的,带有后缀的 */
+    /* 人脸识别算法ID */
+    std::string m_actFaceIdentify;
+    /* 人员统计算法ID */
+    std::string m_actPersonCount;
+    /* 违禁品算法ID */
+    std::string m_actContraband;
+    /* 玩手机算法ID */
+    std::string m_actPlayPhone;
+    /* 疲劳检测算法ID */
+    std::string m_actFatigueDetection;
+    /* 睡岗识别算法ID */
+    std::string m_actSleep;
+    /* 老鼠检测 */
+    std::string m_actMouseDetect;
+    /* 未戴口罩识别 */
+    std::string m_actNoMask;
+    /* 摔倒识别 */
+    std::string m_actAllDown;
+    /* 动物识别 */
+    std::string m_actAnimalDetect;
 
 private:
     std::map<std::string, std::string> m_mapAction;     /* 算法ID和算法名称的对应关系,目前是从配置文件中读取的 */

+ 18 - 18
SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.cpp

@@ -316,7 +316,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         return false;
     }
     /* 人脸识别算法(人员在岗识别、非法入侵检测需要) */
-    if(info.ActionID == GVariable.ActFaceIdentify)
+    if(info.ActionID == GVariable.ActFaceIdentify())
     {
         /* 人员在岗识别 */
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_OnWork);
@@ -332,7 +332,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 人员计数 */
-    else if (info.ActionID == GVariable.ActPersonCount)
+    else if (info.ActionID == GVariable.ActPersonCount())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Regional);
         if(pFuncThreadInfo != nullptr)
@@ -341,7 +341,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 违禁物品 */
-    else if (info.ActionID == GVariable.ActContraband)
+    else if (info.ActionID == GVariable.ActContraband())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Contraband);
         if(pFuncThreadInfo != nullptr)
@@ -350,7 +350,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 玩手机 */
-    else if (info.ActionID == GVariable.ActPlayPhone)
+    else if (info.ActionID == GVariable.ActPlayPhone())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_PlayPhone);
         if(pFuncThreadInfo != nullptr)
@@ -359,7 +359,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 睡岗识别 */
-    else if (info.ActionID == GVariable.ActSleep)
+    else if (info.ActionID == GVariable.ActSleep())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
         if(pFuncThreadInfo != nullptr)
@@ -368,7 +368,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 疲劳检测 */
-    else if(info.ActionID == GVariable.ActFatigueDetection)
+    else if(info.ActionID == GVariable.ActFatigueDetection())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Fatigue);
         if(pFuncThreadInfo != nullptr)
@@ -377,7 +377,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 动物识别 */
-    else if (info.ActionID == GVariable.ActAnimalDetect)
+    else if (info.ActionID == GVariable.ActAnimalDetect())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
         if(pFuncThreadInfo != nullptr)
@@ -386,7 +386,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 老鼠识别 */
-    else if (info.ActionID == GVariable.ActMouseDetect)
+    else if (info.ActionID == GVariable.ActMouseDetect())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_Mouse);
         if(pFuncThreadInfo != nullptr)
@@ -395,7 +395,7 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
         }
     }
     /* 口罩识别 */
-    else if (info.ActionID == GVariable.ActNoMask)
+    else if (info.ActionID == GVariable.ActNoMask())
     {
         auto pFuncThreadInfo = findAppFunction(info.ChannelID, AppFunction::APP_NoMask);
         if(pFuncThreadInfo != nullptr)
@@ -685,7 +685,7 @@ bool GlobalThreadInfo::addActionInfo(const ActionInfo& info)
         return false;
     }
     /* 人脸识别算法(人员在岗识别、非法入侵检测需要) */
-    if(info.ActionID == GVariable.ActFaceIdentify)
+    if(info.ActionID == GVariable.ActFaceIdentify())
     {
         /* 人员在岗识别 */
         setAppFunction(info, AppFunction::APP_OnWork);
@@ -693,7 +693,7 @@ bool GlobalThreadInfo::addActionInfo(const ActionInfo& info)
         setAppFunction(info, AppFunction::APP_Illegal);
     }
     /* 人员计数 */
-    else if (info.ActionID == GVariable.ActPersonCount)
+    else if (info.ActionID == GVariable.ActPersonCount())
     {
         /* 区域人员检测(人员计数?) */
         setAppFunction(info, AppFunction::APP_Regional);
@@ -703,37 +703,37 @@ bool GlobalThreadInfo::addActionInfo(const ActionInfo& info)
         setAppFunction(info, AppFunction::APP_OnWork);
     }
     /* 违禁物品 */
-    else if (info.ActionID == GVariable.ActContraband)
+    else if (info.ActionID == GVariable.ActContraband())
     {
         setAppFunction(info, AppFunction::APP_Contraband);
     }
     /* 玩手机 */
-    else if (info.ActionID == GVariable.ActPlayPhone)
+    else if (info.ActionID == GVariable.ActPlayPhone())
     {
         setAppFunction(info, AppFunction::APP_PlayPhone);
     }
     /* 睡岗识别 */
-    else if (info.ActionID == GVariable.ActSleep)
+    else if (info.ActionID == GVariable.ActSleep())
     {
         setAppFunction(info, AppFunction::APP_Fatigue);
     }
     /* 疲劳检测 */
-    else if(info.ActionID == GVariable.ActFatigueDetection)
+    else if(info.ActionID == GVariable.ActFatigueDetection())
     {
         setAppFunction(info, AppFunction::APP_Fatigue);
     }
     /* 动物识别 */
-    else if (info.ActionID == GVariable.ActAnimalDetect)
+    else if (info.ActionID == GVariable.ActAnimalDetect())
     {
         setAppFunction(info, AppFunction::APP_Mouse);
     }
     /* 老鼠识别 */
-    else if (info.ActionID == GVariable.ActMouseDetect)
+    else if (info.ActionID == GVariable.ActMouseDetect())
     {
         setAppFunction(info, AppFunction::APP_Mouse);
     }
     /* 口罩识别 */
-    else if (info.ActionID == GVariable.ActNoMask)
+    else if (info.ActionID == GVariable.ActNoMask())
     {
         setAppFunction(info, AppFunction::APP_NoMask);
     }

+ 2 - 2
SecurePlayAuxServer/GlobalInfo/GlobalFuncThread.h

@@ -17,8 +17,8 @@
     RunTimeState RunState;          /* 线程运行状态 */
     std::string strFunctionName;    /* 功能名称 */
     
-    QDateTime StartTime;            /* 开始时间 */
-    QDateTime EndTime;              /* 结束时间 */
+    // QDateTime StartTime;            /* 开始时间 */
+    // QDateTime EndTime;              /* 结束时间 */
     std::list<RoomCamActInfo> listRoomCamActInfo;       /* 房间内的摄像机和算法关联信息 */
 
     std::map<int, std::string> mapCameraName;        /* 摄像机名称 */

+ 4 - 0
SecurePlayAuxServer/GlobalInfo/GlobalVariable.cpp

@@ -105,6 +105,7 @@ AlarmInfo::AlarmInfo()
     Is_Alarm = false;
     Is_InsertEQM = false;
     Is_OnWork = false;
+    PKID = 0;
     AlarmID = 0;
     DeviceID = 0;
     RoomID = 0;
@@ -132,6 +133,7 @@ AlarmInfo::AlarmInfo(const AlarmInfo& other)
     Is_Alarm = other.Is_Alarm;
     Is_InsertEQM = other.Is_InsertEQM;
     Is_OnWork = other.Is_OnWork;
+    PKID = other.PKID;
     AlarmID = other.AlarmID;
     DeviceID = other.DeviceID;
     RoomID = other.RoomID;
@@ -160,6 +162,7 @@ AlarmInfo& AlarmInfo::operator=(AlarmInfo& other)
         Is_Alarm = other.Is_Alarm;
         Is_InsertEQM = other.Is_InsertEQM;
         Is_OnWork = other.Is_OnWork;
+        PKID = other.PKID;
         AlarmID = other.AlarmID;
         DeviceID = other.DeviceID;
         RoomID = other.RoomID;
@@ -189,6 +192,7 @@ void AlarmInfo::reInit()
     Is_Alarm = false;
     Is_InsertEQM = false;
     Is_OnWork = false;
+    PKID = 0;
     AlarmID = 0;
     DeviceID = 0;
     RoomID = 0;

+ 4 - 3
SecurePlayAuxServer/GlobalInfo/GlobalVariable.h

@@ -258,6 +258,7 @@ struct AlarmInfo
     bool Is_Alarm;              /* 是否报警 */
     bool Is_InsertEQM;          /* 是否已经插入到EQM数据库中 */
     bool Is_OnWork;             /* 是否在岗 */
+    int PKID;                   /* 主键ID,主要用来判断是否已经写入数据库 */
     int AlarmID;                /* 报警ID */
     int DeviceID;               /* 设备ID,数据库表格中对应的是CamerID */
     
@@ -270,9 +271,6 @@ struct AlarmInfo
     QDateTime StartTime;        /* 报警开始时间 */
     QDateTime EndTime;          /* 报警结束时间 */
     QDateTime EventTime;        /* 事件时间(报警发生时间,在数据库里对应的是CreateTime) */
-    // std::string StartTime;      /* 报警开始时间 */
-    // std::string EndTime;        /* 报警结束时间 */
-    // std::string EventTime;      /* 事件时间(报警发生时间,在数据库里对应的是CreateTime) */
     // std::string PicUrl;         /* 报警图片URL */
     std::string ImageInfo;      /* 图片信息 */
     std::string ActionDes;      /* 算法描述信息 */
@@ -298,6 +296,9 @@ struct AlarmInfo
  */
 struct ListAlarmInfo
 {
+    ~ListAlarmInfo() {
+        clearAlarmInfo();
+    }
     std::list<AlarmInfo*> listAlarmInfo;    /* 报警信息列表 */
 
     /* 添加报警信息 */

+ 19 - 19
SecurePlayAuxServer/GlobalInfo/UniversalFunc.cpp

@@ -66,13 +66,13 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
         nJson json0;
         json0 = nJson::parse(strData);
         /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
-        nJson json1 = json0["bBoxes"];
+        nJson JsonBBoxes = json0["bBoxes"] .is_null() ? nJson::array() : json0["bBoxes"];
         
         std::string labelList;              /* 记录违禁品 */
         std::list<std::string> listBbox;    /* 记录bbox */
-        if(!json1.empty())
+        if(!JsonBBoxes.empty())
         {
-            for(auto& it0 : json1)
+            for(auto& it0 : JsonBBoxes)
             {
                 /* 如果status是true,就不是报警,直接跳过 */
                 bool status = it0["status"].get<bool>();
@@ -83,7 +83,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
                 /* 这一条Box数据报警了将其内容存储起来 */
                 alarmInfo.Is_Alarm = true;
                 /* 解析bbox,在图像中方框的未知 */
-                nJson bbox = it0["bbox"];
+                nJson bbox = it0["bbox"].is_null() ? nJson::array() : it0["bbox"];
                 std::string strBbox;
                 for(auto& it1 : bbox)
                 {
@@ -97,7 +97,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
                 listBbox.push_back(strBbox);
 
                 /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
-                if(alarmInfo.ActionID == GVariable.ActContraband)
+                if(alarmInfo.ActionID == GVariable.ActContraband())
                 {
                     /* 解析报警,取出报警类型,label是报警说明,如“玩手机的人”
                      * 这里主要用于读取违禁品名称 */
@@ -130,7 +130,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
             /* 添加报警信息的提示信息 */
             alarmInfo.listBbox = listBbox;
             /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
-            if( (alarmInfo.ActionID == GVariable.ActContraband) && !labelList.empty() )
+            if( (alarmInfo.ActionID == GVariable.ActContraband()) && !labelList.empty() )
             {
                 alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
                 SPDLOG_DEBUG("{}", alarmInfo.ActionDes);
@@ -145,7 +145,7 @@ void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
                 return;
             }
             /* 如果是人员报警,就存储人员报警信息 */
-            if(alarmInfo.ActionID == GVariable.ActFaceIdentify)
+            if(alarmInfo.ActionID == GVariable.ActFaceIdentify())
             {
                 nJson jsonArray = json0["personList"];
                 for(auto& it : jsonArray)
@@ -186,16 +186,16 @@ bool parseOtherDataPersonCount(const std::string& strData, AlarmInfo& alarmInfo)
         nJson json0;
         json0 = nJson::parse(strData);
         /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
-        nJson jsonArray = json0["bBoxes"];
+        nJson JsonBBoxes = json0["bBoxes"] .is_null() ? nJson::array() : json0["bBoxes"];
         
         std::list<std::string> listBbox;    /* 记录bbox */
-        if(jsonArray.empty())
+        if(JsonBBoxes.empty())
         {
-            SPDLOG_WARN("没有bBoxes数据");
+            // SPDLOG_WARN("没有bBoxes数据");
             return false;
         }
         /* 解析bBoxes JSON数组 */
-        for(const auto& it0 : jsonArray)
+        for(const auto& it0 : JsonBBoxes)
         {
             bool status = it0["status"].get<bool>();
             /* 如果status是true,就不是报警,直接跳过 */
@@ -236,14 +236,14 @@ bool parseOtherDataPersonCount(const std::string& strData, AlarmInfo& alarmInfo)
                 return false;
             }
             /* 如果是人员报警,就存储人员报警信息 */
-            nJson jsonArray = json0["personList"];
-            for(auto& it : jsonArray)
-            {
-                PersonInfo personInfo;
-                personInfo.PersonID = it["personId"].get<std::string>();
-                personInfo.PersonName = it["personName"].get<std::string>();
-                alarmInfo.listPersonInfo.push_back(personInfo);
-            }
+            // nJson jsonArray = json0["personList"];
+            // for(auto& it : jsonArray)
+            // {
+            //     PersonInfo personInfo;
+            //     personInfo.PersonID = it["personId"].get<std::string>();
+            //     personInfo.PersonName = it["personName"].get<std::string>();
+            //     alarmInfo.listPersonInfo.push_back(personInfo);
+            // }
         }
     }
     catch (const nJson::parse_error& e)

+ 6 - 6
SecurePlayAuxServer/SPAServer.cpp

@@ -8,7 +8,7 @@
 #include "UniversalFunc.h"
 #include "FuncOrdinary.h"
 #include "FuncIllegalInvasion.h"
-#include "FuncOnAndOffJob.h"
+#include "FuncOnAndOffWork.h"
 #include "FuncRegionalPerson.h"
 
 #include "GlobalFuncThread.h"
@@ -574,7 +574,7 @@ FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
     else if(info.appFunction == AppFunction::APP_OnWork)
     {
         /* 人员在岗检测 */
-        // auto tmpFunc = new FuncOnAndOffJob();
+        // auto tmpFunc = new FuncOnAndOffWork();
         // tmpFunc->setFuncThreadInfo(info);
         // pFunc = tmpFunc;
     }
@@ -588,9 +588,9 @@ FuncBase* SPAServer::createFuncInstance(FuncThreadInfo& info)
     else if(info.appFunction == AppFunction::APP_Regional)
     {
         /* 区域人员检测 */
-        // auto tmpFunc = new FuncRegionalPersonCount();
-        // tmpFunc->setFuncThreadInfo(info);
-        // pFunc = tmpFunc;
+        auto tmpFunc = new FuncRegionalPersonCount();
+        tmpFunc->setFuncThreadInfo(info);
+        pFunc = tmpFunc;
     }
 
     return pFunc;
@@ -614,7 +614,7 @@ void SPAServer::clearNoneFuncThreadInfo()
             else if((*it)->getApp() == AppFunction::APP_OnWork)
             {
                 /* 人员在岗检测 */
-                FuncOnAndOffJob* p = dynamic_cast<FuncOnAndOffJob*>(*it);
+                FuncOnAndOffWork* p = dynamic_cast<FuncOnAndOffWork*>(*it);
                 delete p;
             }
             else if((*it)->getApp() == AppFunction::APP_Illegal)

+ 1 - 1
SecurePlayAuxServer/communication/FromRedis.cpp

@@ -95,7 +95,7 @@ bool FromRedis::getRedisString(const std::string& key, std::string& value)
     {
         if(reply->type == REDIS_REPLY_NIL)
         {
-            SPDLOG_WARN( "Get redis data failed, key is not exist");
+            SPDLOG_WARN( "获取Redis数据失败,Key对应的值不存在,Key: {}", key);
         }else {
             /* 其他类型的返回值 */
             SPDLOG_ERROR( "Get redis data failed, type is not string, type: {}", reply->type);

+ 97 - 70
SecurePlayAuxServer/communication/FromWebAPI.cpp

@@ -3,7 +3,7 @@
 #include <QJsonDocument>
 #include <QString>
 #include <QUuid>
-#include "FuncOnAndOffJob.h"
+#include "FuncOnAndOffWork.h"
 #include "FuncRegionalPerson.h"
 #include "UniversalFunc.h"
 
@@ -35,39 +35,66 @@ bool FromWebAPI::initWebApi(const QString& url,const QString& serID, const QStri
     {
         m_httpApi = new lhhttpapi;
     }
-    int ret = 0;
-
+    
     if(!m_httpApi->Load())
     {
-        SPDLOG_LOGGER_ERROR(m_logger,"Load WebApi failed!");
+        SPDLOG_LOGGER_ERROR(m_logger, "Load WebAPI failed");
+        return false;
+    }
+    SPDLOG_LOGGER_DEBUG(m_logger, "URL: {}", url.toStdString());
+    SPDLOG_LOGGER_DEBUG(m_logger, "ServerID: {}", serID.toStdString());
+    SPDLOG_LOGGER_DEBUG(m_logger, "ServerKey: {}", appType.toStdString());
+
+    void* pHttp = nullptr;
+    int i = 0;
+    for(i = 0; i < 3; i++)
+    {
+        pHttp = m_httpApi->DBInit(url.toStdString().c_str(), true);
+        if(pHttp != nullptr)
+        {
+            break;
+        }
+        SPDLOG_LOGGER_ERROR(m_logger, "设置WebAPI地址失败: {}", m_httpApi->DoGetLastError(&i).toStdString());
+    }
+    if(i >= 3)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "WebAPI设置地址错误!");
         return false;
     }
+    
+    int ret = 0;
 
-    m_httpApi->DBInit(url.toStdString().c_str(), true);
+#ifdef QT_DEBUG
+    /* 获取服务器列表 */
+    // char serverList[8192]={0};
+    // ret = m_httpApi->DBGetServerList(serverList, 8192-1);
     // if(ret != 0)
     // {
-    //     SPDLOG_LOGGER_ERROR(m_logger,"Init WebApi failed:{}, error Info:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+    //     SPDLOG_LOGGER_ERROR(m_logger, "Get server list failed: {}, error info: {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
     //     return false;
     // }
-    // SPDLOG_LOGGER_TRACE(m_logger,"初始化WebApi成功!");
-    /* 获取服务器列表 */
-    char serverList[8192];
-    ret = m_httpApi->DBGetServerList(serverList, 8192, true);
-    if(ret != 0)
+    // SPDLOG_LOGGER_INFO(m_logger, QString("\nGet server list success:%1").arg(serverList));
+#endif
+
+    /* 登录,第二个参数是限制的服务 */
+    for(i = 0; i < 3; i++)
     {
-        SPDLOG_LOGGER_DEBUG(m_logger,"Get server list failed:{}, error info:{}",ret, m_httpApi->DoGetLastError(&ret).toStdString());
-        return false;
+        ret = m_httpApi->DBLogin("", serID, appType, m_userToken, true, pHttp);
+        if(ret == 0)
+        {
+            break;
+        }
+        SPDLOG_LOGGER_ERROR(m_logger, "Login failed: {}, error info: {}", ret, m_httpApi->DoGetLastError(&ret).toStdString());
+        /* 登录失败,等待一段时间 */
+        QThread::msleep(200);
     }
-    // SPDLOG_LOGGER_TRACE(m_logger,"Server list:{}", serverList);
-    SPDLOG_LOGGER_DEBUG(m_logger,"WebAPI Load Sucess!");
-    /* 登录,第二个参数是限制的服务 */
-    ret = m_httpApi->DBLogin(serverIP, serID, appType, m_userToken, true);
-    if(ret != 0)
+    if(i >= 3)
     {
-        SPDLOG_LOGGER_ERROR(m_logger,"Login failed:{}, error info:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        SPDLOG_LOGGER_ERROR(m_logger, "登陆WebAPI失败!");
         return false;
     }
-    SPDLOG_LOGGER_INFO(m_logger,"Login WebAPI sucess!");
+
+    SPDLOG_LOGGER_INFO(m_logger, "WebAPI Login success!");
 
     return true;
 }
@@ -1301,13 +1328,13 @@ bool FromWebAPI::insertAlarmInfo(const AlarmInfo& alarmInfo, int& PKID)
         json1["alarmID"] = alarmInfo.AlarmID;
         json1["startTime"] = alarmInfo.StartTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
         json1["createTime"] = alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
-        std::string strEndTime = "";
-        /* 这里判断一下结束时间是否需要设置,如果不需要,则设置成小于2020年即可,写入数据库就是空 */
-        if(alarmInfo.EndTime > QDateTime::fromString("2020-01-01 00:00:00", "yyyy-MM-dd hh:mm:ss"))
-        {
-            strEndTime = alarmInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
-        }
-        json1["endTime"] = strEndTime;
+        // std::string strEndTime = "";
+        // /* 这里判断一下结束时间是否需要设置,如果不需要,则设置成小于2020年即可,写入数据库就是空 */
+        // if(alarmInfo.EndTime > QDateTime::fromString("2020-01-01 00:00:00", "yyyy-MM-dd hh:mm:ss"))
+        // {
+        //     strEndTime = alarmInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
+        // }
+        json1["endTime"] = alarmInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
         json1["bbox"] = strBbox;
         json1["picUrl"] = alarmInfo.ImageInfo;
         json1["appID"] = getAppFunctionID(alarmInfo.appFunction);
@@ -1395,49 +1422,49 @@ void FromWebAPI::printAlarmInfo(const AlarmInfo& alarmInfo, std::string strBBox)
 }
 
 /* 更新报警结束时间 */
-bool FromWebAPI::updateAlarmEndTime(const AlarmInfo& alarmInfo)
-{
-    if(m_httpApi == nullptr)
-    {
-        SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
-        return false;
-    }
-    try
-    {
-        nJson json0;
-        json0["opName"] = "SPSS_UpdateAlarmEndTime";
-        nJson json1;
-        json1["EndTime"] = alarmInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
-        json1["ChannelID"] = alarmInfo.ChannelID;
-        json1["RoomID"] = alarmInfo.RoomID;
-        json1["CamerID"] = alarmInfo.DeviceID;
-        json1["ActionID"] = alarmInfo.ActionID;
-        json0["paramList"] = json1;
-
-        QString strCmd = QString::fromStdString(json0.dump());
-        QString strRet;
-        int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strCmd, strRet, true);
-        if(ret != 0)
-        {
-            SPDLOG_LOGGER_WARN(m_logger,"更新报警结束时间失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
-            return false;
-        }
-    }
-    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 true;
-}
+// bool FromWebAPI::updateAlarmEndTime(const AlarmInfo& alarmInfo)
+// {
+//     if(m_httpApi == nullptr)
+//     {
+//         SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
+//         return false;
+//     }
+//     try
+//     {
+//         nJson json0;
+//         json0["opName"] = "SPSS_UpdateAlarmEndTime";
+//         nJson json1;
+//         json1["EndTime"] = alarmInfo.EndTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
+//         json1["ChannelID"] = alarmInfo.ChannelID;
+//         json1["RoomID"] = alarmInfo.RoomID;
+//         json1["CamerID"] = alarmInfo.DeviceID;
+//         json1["ActionID"] = alarmInfo.ActionID;
+//         json0["paramList"] = json1;
+
+//         QString strCmd = QString::fromStdString(json0.dump());
+//         QString strRet;
+//         int ret = m_httpApi->DBDoInterface(enDBOperatorType::EDBOT_Update, strCmd, strRet, true);
+//         if(ret != 0)
+//         {
+//             SPDLOG_LOGGER_WARN(m_logger,"更新报警结束时间失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+//             return false;
+//         }
+//     }
+//     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 true;
+// }
 
 /**
  * @brief 根据PKID更新报警记录,用来结束报警,这个只需要PKID和结束时间

+ 1 - 1
SecurePlayAuxServer/communication/FromWebAPI.h

@@ -69,7 +69,7 @@ public:
     /* 打印报警数据信息 */
     void printAlarmInfo(const AlarmInfo& alarmInfo, std::string strBBox);
     /* 更新报警结束时间 */
-    bool updateAlarmEndTime(const AlarmInfo& alarmInfo);
+    // bool updateAlarmEndTime(const AlarmInfo& alarmInfo);
     /* 根据PKID更新报警记录,用来结束报警 */
     bool endAlarmInfoByPKID(const int PKID, const QDateTime dateTime);
     /* 更新人员信息 */

+ 16 - 0
jsons/人员计数.json

@@ -186,4 +186,20 @@
   "picUrl": "681b1577e4b076d9b3703b72.jpg",
   "taskId": 5,
   "taskName": "人员计数"
+}
+
+{
+  "actionId": "OD210_022_001835_029",
+  "actionName": "人员计数",
+  "actionResult": true,
+  "alarmId": 69659,
+  "beginTime": "2025-05-10T15:22:21",
+  "deviceName": "广电区域1",
+  "endTime": "2025-05-10T15:22:21",
+  "eventTime": "2025-05-10T15:22:21",
+  "imageInfo": "http://nginx-webdav-out.mid:80/webdav///TOcg6kglgb7zv/PUMPING/2025/05/10/681efeade4b0a2212ff16d2b.jpg",
+  "personList": [],
+  "picUrl": "681efeade4b0a2212ff16d2b.jpg",
+  "taskId": 5,
+  "taskName": "人员计数"
 }

+ 16 - 0
jsons/玩手机识别.json

@@ -39,4 +39,20 @@
     "picUrl": "681d70dee4b076d9b3704646.jpg",
     "taskId": 6,
     "taskName": "玩手机识别"
+}
+
+{
+    "actionId": "OD447_022_000070_001",
+    "actionName": "k2玩手机",
+    "actionResult": true,
+    "alarmId": 69658,
+    "beginTime": "2025-05-10T15:21:46",
+    "deviceName": "广电区域1",
+    "endTime": "2025-05-10T15:21:46",
+    "eventTime": "2025-05-10T15:21:46",
+    "imageInfo": "http://nginx-webdav-out.mid:80/webdav///TOcg6kglgb7zv/PUMPING/2025/05/10/681efe8ae4b0a2212ff16d24.jpg",
+    "personList": [],
+    "picUrl": "681efe8ae4b0a2212ff16d24.jpg",
+    "taskId": 6,
+    "taskName": "玩手机识别"
 }

+ 3 - 0
存在的问题

@@ -0,0 +1,3 @@
+1、摄像机信息表存在重复的问题
+2、自动删除一年前的数据还未添加
+3、打包成Docker镜像