Pārlūkot izejas kodu

V0.3.1
1、基本完成了人员在岗的功能
2、人员在岗功能写入数据库还有问题

Apple 6 mēneši atpakaļ
vecāks
revīzija
4e3c7b959f

+ 79 - 0
SecurePlayAuxServer/GlobalInfo/GlobalInfo.cpp

@@ -207,6 +207,79 @@ AlarmInfo* ListAlarmInfo::findAlarmInfo(AlarmInfo& info)
 }
 
 
+/* 查找是否有相同的人脸信息 */
+bool RoomFaceInfo::findPersonInfo(const PersonInfo& info)
+{
+    for(auto& it0 : listPersonInfo)
+    {
+        if(it0.PersonID == info.PersonID && it0.PersonName == info.PersonName)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+/* 添加房间人脸信息 */
+void ListRoomFaceInfo::addRoomFaceInfo(RoomFaceInfo& info)
+{
+    /* 先查找有没有重复的 */
+    auto p = findRoomFaceInfo(info);
+    if(p != nullptr)
+    {
+        return;
+    }
+    listRoomFaceInfo.push_back(info);
+}
+
+void ListRoomFaceInfo::addRoomFaceInfo(AlarmInfo& info)
+{
+    auto p = findRoomFaceInfo(info.ChannelID, info.RoomID);
+    if(p == nullptr)
+    {
+        RoomFaceInfo rfi;
+        rfi.ChannelID = info.ChannelID;
+        rfi.RoomID = info.RoomID;
+        rfi.MaxNum = 0;
+        rfi.MinNum = 0;
+        rfi.StartTime = QDateTime::currentDateTime();
+        listRoomFaceInfo.push_back(rfi);
+    }
+    for(auto& it0 : info.vecPersonInfo)
+    {
+        if(!p->findPersonInfo(it0))
+        {
+            p->listPersonInfo.push_back(it0);
+        }
+    }
+}
+
+RoomFaceInfo* ListRoomFaceInfo::findRoomFaceInfo(RoomFaceInfo& info)
+{
+    for(auto& it0 : listRoomFaceInfo)
+    {
+        if(it0.ChannelID == info.ChannelID && it0.RoomID == info.RoomID)
+        {
+            return &it0;
+        }
+    }
+    return nullptr;
+}
+
+/* 查找有没有相同的结构 */
+RoomFaceInfo* ListRoomFaceInfo::findRoomFaceInfo(int ChannelID, int RoomID)
+{
+    for(auto& it0 : listRoomFaceInfo)
+    {
+        if(it0.ChannelID == ChannelID && it0.RoomID == RoomID)
+        {
+            return &it0;
+        }
+    }
+    return nullptr;
+}
+
+
 
 AlarmRuleInfo::AlarmRuleInfo()
 {
@@ -888,6 +961,10 @@ bool ListFuncActInfo::addActionInfo(const ActionInfo& info)
             pFuncActionInfo->addActionInfo(info);
         }
         pFuncActionInfo = findAppFunction(info.ChannelID, AppFunction::APP_ILLEGAL);
+        if(pFuncActionInfo != nullptr)
+        {
+            pFuncActionInfo->addActionInfo(info);
+        }
     }
     /* 人员计数 */
     else if (info.ActionID == g_actionList.ActPersonNumber)
@@ -1066,6 +1143,8 @@ bool GlobalConfig::readConfig(const QString& strConfigFile)
     settings.setIniCodec("UTF-8");
 
     settings.beginGroup("System");
+
+    AppUpdateOnWorkTimeInterval = settings.value("WorkOnInfoSecond", 600).toInt();  /* 更新在岗信息的时间间隔 */
     AppPeopleOnWork = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
     Contraband = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
     AppBadMan = settings.value("APPBADMAN", 50).toInt();                     /* 非法入侵 */

+ 46 - 0
SecurePlayAuxServer/GlobalInfo/GlobalInfo.h

@@ -251,6 +251,51 @@ struct ListAlarmInfo
     AlarmInfo* findAlarmInfo(AlarmInfo& info);
 };
 
+/**
+ * @brief 房间内的人脸信息
+ * 
+ */
+struct RoomFaceInfo
+{
+    int ChannelID = 0;
+    int RoomID = 0;
+    int MaxNum = 0;
+    int MinNum = 0;
+    QDateTime StartTime;
+    QDateTime EndTime;
+    std::list<PersonInfo> listPersonInfo;
+
+    RoomFaceInfo() = default;
+    RoomFaceInfo& operator=(const RoomFaceInfo& other) {
+        if (this != &other) {
+            ChannelID = other.ChannelID;
+            RoomID = other.RoomID;
+            MaxNum = other.MaxNum;
+            MinNum = other.MinNum;
+            StartTime = other.StartTime;
+            EndTime = other.EndTime;
+            listPersonInfo = other.listPersonInfo;
+        }
+        return *this;
+    }
+    /* 查找是否有相同的人脸信息 */
+    bool findPersonInfo(const PersonInfo& info);
+};
+
+/**
+ * @brief 房间内的人脸信息
+ * 
+ */
+struct ListRoomFaceInfo
+{
+    std::list<RoomFaceInfo> listRoomFaceInfo;
+
+    void addRoomFaceInfo(RoomFaceInfo& info);
+    void addRoomFaceInfo(AlarmInfo& info);
+    RoomFaceInfo* findRoomFaceInfo(RoomFaceInfo& info);
+    RoomFaceInfo* findRoomFaceInfo(int ChannelID, int RoomID);
+};
+
 
 /**
  * @brief 报警规则
@@ -550,6 +595,7 @@ public:
     /* 打印读取到的值 */
     void printValue();
     
+    int AppUpdateOnWorkTimeInterval;/* 更新在岗信息的时间间隔 */
     int AppPeopleOnWork;        /* 离岗时间 */
     int Contraband;             /* 违禁物品出现的时间 */
     int AppBadMan;              /* 非法入侵 */

+ 93 - 59
SecurePlayAuxServer/SPAServer.cpp

@@ -845,42 +845,47 @@ void SPAServer::threadRoomCamera()
  * 
  * @param pRAInfo 传入房间ID和算法ID
  */
-void SPAServer::threadActPersonWork(RoomActionInfo* RAInfo)
+void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
 {
-    SPDLOG_LOGGER_INFO(m_logger, "开启人员在岗识别线程,RoomID:{} ,Action:{}", RAInfo->RoomID, RAInfo->ActionID);
+    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
     /* 创建读取Redis的实例 */
     std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
     /* 局部变量 */
-    std::shared_ptr<RoomActionInfo> pRAInfo = std::make_shared<RoomActionInfo>();
-    *pRAInfo = *RAInfo;
-    int CameraCount = pRAInfo->listCameraID.size();
-    /* 摄像机数目小于0就退出线程 */
+    std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
+    *pRFAInfo = *RFAInfo;
+    
     while (m_threadRunning)
     {
-        /* 更新算法关联的摄像机个数 */
-        pRAInfo->listCameraID.clear();
-        updateRoomActionCameraCount(pRAInfo);
-        CameraCount = pRAInfo->listCameraID.size();
-        if(CameraCount == 0)
+        /* 更新线程信息 */
+        updateFuncInfo(pRFAInfo);
+        if(pRFAInfo->appFunction == AppFunction::APP_NONE)
         {
             break;
         }
 
         /* 读取Redis数据 */
-        for(const auto& camID : pRAInfo->listCameraID)
+        for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
         {
-            std::string strKey = std::to_string(camID) + ":" + pRAInfo->ActionID;
-            std::string strRetValue;
-            if(!fromRedis->getRedisString(strKey, strRetValue))
+            for(const auto& it : RoomInfo.mapCameraAction)
             {
-                SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
-                continue;
+                std::string strKey = std::to_string(it.first) + ":" + it.second;
+                std::string strRetValue;
+                if(!fromRedis->getRedisString(strKey, strRetValue))
+                {
+                    SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    continue;
+                }
+                /* 解析数据 */
+                AlarmInfo alarmInfo;
+                parseRedisData(strRetValue, alarmInfo);
+
+
             }
-            /* 解析数据 */
-            AlarmInfo alarmInfo;
-            parseRedisData(strRetValue, alarmInfo);
         }
     }
+    setThreadState(pRFAInfo, RunTimeState::RUN_STATE_STOP);
+    SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
 }
 
 /**
@@ -894,51 +899,95 @@ void SPAServer::threadActPersonWork(RoomActionInfo* RAInfo)
  * 
  * @param RAInfo 传入的房间ID和算法ID
  */
-void SPAServer::threadActRegionalPersonnelDetection(RoomActionInfo* RAInfo)
+void SPAServer::threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo)
 {
-    SPDLOG_LOGGER_INFO(m_logger, "开启区域人员检测线程,RoomID:{} ,Action:{}", RAInfo->RoomID, RAInfo->ActionID);
+    SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
     /* 创建读取Redis的实例 */
     std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
     /* 局部变量 */
-    std::shared_ptr<RoomActionInfo> pRAInfo = std::make_shared<RoomActionInfo>();
+    std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
     /* 创建写入数据库实例 */
     std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
-    *pRAInfo = *RAInfo;
-    int CameraCount = 0;
+    *pRFAInfo = *RFAInfo;
     /* 保存每个摄像机的报警信息 */
     std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
+    /* 保存人员计数的信息 */
+    std::shared_ptr<ListRoomFaceInfo> pListRoomFaceInfo = std::make_shared<ListRoomFaceInfo>();
     
     while (m_threadRunning)
     {
-        /* 更新算法关联的摄像机个数 */
-        pRAInfo->listCameraID.clear();
-        updateRoomActionCameraCount(pRAInfo);
-        CameraCount = pRAInfo->listCameraID.size();
-        /* 摄像机数目等于0就退出线程 */
-        if(CameraCount == 0)
+        /* 更新线程信息 */
+        updateFuncInfo(pRFAInfo);
+        if(pRFAInfo->appFunction == AppFunction::APP_NONE)
         {
             break;
         }
 
         /* 读取Redis数据 */
-        for(const auto& camID : pRAInfo->listCameraID)
+        pListAlarmInfo->clear();
+        for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
         {
-            std::string strKey = std::to_string(camID) + ":" + pRAInfo->ActionID;
-            std::string strRetValue;
-            if(!fromRedis->getRedisString(strKey, strRetValue))
+            for(const auto& it : RoomInfo.mapCameraAction)
             {
-                SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
-                std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                continue;
+                std::string strKey = std::to_string(it.first) + ":" + it.second;
+                std::string strRetValue;
+                if(!fromRedis->getRedisString(strKey, strRetValue))
+                {
+                    SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    continue;
+                }
+                /* 解析数据 */
+                AlarmInfo alarmInfo;
+                parseRedisData(strRetValue, alarmInfo);
+                /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
+                if(isEventTimeVaild(alarmInfo.EventTime))
+                {
+                    SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
+                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+                    continue;
+                }
+                pListAlarmInfo->push_back(alarmInfo);
             }
-            /* 解析数据 */
-            AlarmInfo alarmInfo;
-            parseRedisBaseData(strRetValue, alarmInfo);
-            parseRedisBBoxesData(strRetValue, alarmInfo);
         }
+
+        /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
+        for(auto& alarmInfo : *pListAlarmInfo)
+        {
+            /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
+            pListRoomFaceInfo->addRoomFaceInfo(alarmInfo);
+        }
+        /* 计算人脸个数,并判断是否需要写入数据库 */
+        QDateTime now = QDateTime::currentDateTime();
+        for(auto it = pListRoomFaceInfo->listRoomFaceInfo.begin(); it != pListRoomFaceInfo->listRoomFaceInfo.end(); )
+        {
+            if(it->MaxNum < it->listPersonInfo.size())
+            {
+                it->MaxNum = it->listPersonInfo.size();
+            }
+            if(it->MinNum > it->listPersonInfo.size())
+            {
+                it->MinNum = it->listPersonInfo.size();
+            }
+            /* 判断是否需要写入数据库,超过设置的时间就写入,默认是600秒 */
+            if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > g_config.AppUpdateOnWorkTimeInterval)
+            {
+                /* 写入数据库 */
+                if(toEQMDataBase->insertOnWorkInfo(*it))
+                {
+                    SPDLOG_LOGGER_INFO(m_logger, "ChannelID:{}, RoomID:{}, 在岗信息写入数据库成功, StartTime", it->ChannelID, it->RoomID, it->StartTime.toString("yyyy-MM-dd hh:mm:ss"));
+                    /* 删除这条信息 */
+                    it = pListRoomFaceInfo->listRoomFaceInfo.erase(it);
+                    continue;
+                }
+            }
+            ++it;
+        }
+
+
     }
-    setThreadState(pRAInfo, RunTimeState::RUN_STATE_STOP);
-    SPDLOG_LOGGER_INFO(m_logger, "关闭区域人员检测线程,RoomID:{} ,Action:{}", RAInfo->RoomID, RAInfo->ActionID);
+    setThreadState(pRFAInfo, RunTimeState::RUN_STATE_STOP);
+    SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
 }
 
 /**
@@ -1159,21 +1208,6 @@ bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCame
     return true;
 }
 
-/* 更新房间、算法需要的摄像机个数,从内存中更新 */
-bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo)
-{
-    std::lock_guard<std::mutex> look(m_mutexRunRAI);
-    for(auto& it : m_runListRoomActionInfo.getData())
-    {
-        if((it->RoomID == pRAInfo->RoomID) && (it->ActionID == pRAInfo->ActionID))
-        {
-            it->listCameraID = pRAInfo->listCameraID;
-            break;
-        }
-    }
-
-    return true;
-}
 
 /**
  * @brief 功能线程更新功能信息,这里是从内存中的数组里获取

+ 7 - 8
SecurePlayAuxServer/SPAServer.h

@@ -47,19 +47,18 @@ private:
     void threadRoomCamera();
     
     /* 人员在岗识别线程,应该是人脸识别线程,这个需要房间内多个摄像机共同识别 */
-    void threadActPersonWork(RoomActionInfo* RAInfo);
-    /* 区域人员检测,检测这个区域内的人数,不能少于多少人,不能多余多少人 */
-    void threadActRegionalPersonnelDetection(RoomActionInfo* RAInfo);
-    /* 普通任务线程,一个算法值对应一个摄像机 */
-    void threadActNormal(FuncActionInfo* info);
+    void threadActPersonWork(FuncActionInfo* RFAInfo);
+    /* 区域人员检测(人员计数),检测这个区域内的人数,不能少于多少人,不能多余多少人 */
+    void threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo);
     /* 非法入侵检测 */
     void threadActIllegalInvasion(ActionInfo* info);
-    /* 人员计数 */
+    /* 普通任务线程,一个算法值对应一个摄像机 */
+    void threadActNormal(FuncActionInfo* info);
+    
 
     /* 将该算法对应的摄像机放入摄像机列表 */
     bool insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID);
-    /* 更新房间、算法需要的摄像机个数 */
-    bool updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo);
+
     /* 更新算法的摄像机ID */
     bool updateFuncInfo(std::shared_ptr<FuncActionInfo> pInfo);
     /* 设置线程状态 */

+ 35 - 0
SecurePlayAuxServer/communication/ToEQMDataBase.cpp

@@ -985,3 +985,38 @@ bool ToEQMDataBase::getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo)
     return true;
 }
 
+
+/* 写入在岗信息 */
+bool ToEQMDataBase::insertOnWorkInfo(const RoomFaceInfo& onWorkInfo)
+{
+    if(m_httpApi == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
+        return false;
+    }
+    nJson json0;
+    json0["opName"] = "SPSS_InsertToOnWork";
+    nJson json1;
+    json1["nChID"] = onWorkInfo.ChannelID;
+    json1["RoomID"] = onWorkInfo.RoomID;
+    json1["FaceID"] = onWorkInfo.FaceID;
+    json1["StartTime"] = onWorkInfo.StartTime;
+    json1["EndTime"] = onWorkInfo.EndTime;
+    
+    json1["CamerID"] = onWorkInfo.DeviceID;
+    json1["ActionID"] = onWorkInfo.ActionID;
+    json0["paramList"] = json1;
+
+    QString strCmd = QString::fromStdString(json0.dump());
+    QString strRet;
+    auto ret = m_httpApi->DBQDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+    if(ret < 0)
+    {
+        SPDLOG_LOGGER_WARN(m_logger,"插入在岗信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        return false;
+    }
+    SPDLOG_LOGGER_DEBUG(m_logger,"插入在岗信息成功!");
+
+    return true;
+}
+

+ 3 - 0
SecurePlayAuxServer/communication/ToEQMDataBase.h

@@ -54,6 +54,9 @@ public:
     bool getAlarmRuleInfo(std::vector<AlarmRuleInfo>& vecInfo);
     /* 获取报警时段,也同时获取报警的应用信息 */
     bool getAlarmAppInfo(std::list<AppAndTimeInfo>& listInfo);
+
+    /* 写入在岗信息 */
+    bool insertOnWorkInfo(const RoomFaceInfo& onWorkInfo);
     
 
 private: