Quellcode durchsuchen

V0.1.15
1、重新修改了算法和摄像机对应关系的获取方式,直接使用数据库获取到
2、编译貌似不能通过,虚拟机太卡了

Apple vor 7 Monaten
Ursprung
Commit
b85038adfc

+ 186 - 0
SecurePlayAuxServer/GlobalInfo/GlobalInfo.cpp

@@ -9,4 +9,190 @@ int g_eventTimeVaild = 600;         /* 事件时间有效性,单位秒,超
 
 
 
+/* ====================================================================================
+ * ***************************    DeviceInfo成员函数    *******************************
+ * ====================================================================================*/
+
+/* 对比是否相等 */
+bool DeviceInfo::operator==(const DeviceInfo& other)
+{
+    if(DeviceID != other.DeviceID) {
+        return false;
+    }
+    else if(DeviceName != other.DeviceName || DeviceIP != other.DeviceIP) {
+        return false;
+    }
+    else if(DeviceSerial != other.DeviceSerial || DeviceType != other.DeviceType) {
+        return false;
+    }
+    else if(DevicePort != other.DevicePort || UserAccount != other.UserAccount || UserPassword != other.UserPassword) {
+        return false;
+    }
+    return true;
+}
+
+/* 对比设备关联的算法信息是否相等 */
+bool DeviceInfo::isEqualAlgorithmInfo(const std::vector<AlgorithmInfo>& other)
+{
+    /* 算法数目不相等,直接返回false */
+    if(vecAlgorithmInfo.size() != other.size()) {
+        return false;
+    }else {
+        /* 算法数目相等,进一步对比算法信息 */
+        bool isEquality = true;
+        /* 逐步对比算法信息 */
+        for(const auto& it0 : vecAlgorithmInfo) {
+            bool isEq2 = true;
+            for(const auto& it1 : other) {
+                if(it0 == it1) {
+                    continue;
+                }else {
+                    isEq2 = false;
+                    break;
+                }
+            }
+            if(!isEq2) {
+                isEquality = false;
+                break;
+            }
+        }
+        if(!isEquality) {
+            return false;
+        }
+    }
+    return true;
+}
+
+/* ====================================================================================
+ * **************************    ListActionInfo成员函数    ****************************
+ * ====================================================================================*/
+
+/* 添加关联信息,会自动进行重复判断,如果已有相同的信息,则跳过 */
+bool ListActionInfo::insertActionInfo(ActionInfo* info)
+{
+    /* 先判断是否已经在列表中了 */
+    if(findActionInList(info) == nullptr)
+    {
+        ActionInfo* pActionInfo = new ActionInfo;
+        *pActionInfo = *info;
+        listActionInfo.push_back(pActionInfo);
+    }
+
+    return true;
+    
+}
+
+/* 删除信息 */
+bool ListActionInfo::deleteActionInfo(ActionInfo* info)
+{
+    if(info == nullptr)
+    {
+        return false;
+    }
+    if(findActionInList(info) != nullptr)
+    {
+        listActionInfo.remove(info);
+        delete info;
+        info = nullptr;
+    }
+    return true;
+}
+
+/* 查找算法ID是否已在列表中 */
+ActionInfo* ListActionInfo::findActionInList(ActionInfo* pInfo)
+{
+    for(const auto& it0 : listActionInfo)
+    {
+        if(*it0 == *pInfo)
+        {
+            return it0;
+        }
+    }
+    return nullptr;
+}
+
+/* 清空容器 */
+void ListActionInfo::clear()
+{
+    for(auto& it0 : listActionInfo)
+    {
+        delete it0;
+        it0 = nullptr;
+    }
+    listActionInfo.clear();
+}
+
+/* ====================================================================================
+ * ***********************    ListRoomActionInfo成员函数    ***************************
+ * ====================================================================================*/
+
+/* 添加关联信息,会自动进行重复判断,如果已有相同的room和action关联信息,则跳过 */
+bool ListRoomActionInfo::insertRoomActionInfo(const RoomActionInfo& info)
+{
+    /* 先判断是否已经在列表中了 */
+    if(findActionIDInList(info.RoomID, info.ActionID) == nullptr)
+    {
+        RoomActionInfo* pRoomActionInfo = new RoomActionInfo;
+        *pRoomActionInfo = info;
+        listRoomActionInfo.push_back(pRoomActionInfo);
+    }
+
+    return true;
+}
+
+/* 添加关联信息,会自动进行重复判断,如果已有相同的room和action关联信息,则跳过 */
+bool ListRoomActionInfo::insertRoomActionInfo(const int RoomID, const std::string& strActionID)
+{
+    /* 先判断是否已经在列表中了 */
+    if(findActionIDInList(RoomID, strActionID) == nullptr)
+    {
+        RoomActionInfo* pRoomActionInfo = new RoomActionInfo;
+        pRoomActionInfo->RoomID = RoomID;
+        pRoomActionInfo->ActionID = strActionID;
+        listRoomActionInfo.push_back(pRoomActionInfo);
+    }
+    return true;
+}
+
+/* 清空容器 */
+void ListRoomActionInfo::clear()
+{
+    for(auto& it0 : listRoomActionInfo)
+    {
+        delete it0;
+        it0 = nullptr;
+    }
+    listRoomActionInfo.clear();
+}
+
+/* 添加算法信息,根据传入的算法信息,自动将其加入到对应的容器中 */
+void ListRoomActionInfo::addActionInfo(const ActionInfo& info)
+{
+    auto pRAInfo = findActionIDInList(info.ChannelID, info.RoomID, info.ActionID);
+    if(pRAInfo != nullptr)
+    {
+        pRAInfo->listCameraID.push_back(info.CameraID);
+    }else {
+        RoomActionInfo* pRoomActionInfo = new RoomActionInfo;
+        pRoomActionInfo->ChannelID = info.ChannelID;
+        pRoomActionInfo->RoomID = info.RoomID;
+        pRoomActionInfo->ActionID = info.ActionID;
+        pRoomActionInfo->RoomType = info.RoomType;
+        pRoomActionInfo->strRoomName = info.strRoomName;
+        pRoomActionInfo->listCameraID.push_back(info.CameraID);
+        listRoomActionInfo.push_back(pRoomActionInfo);
+    }
+}
 
+/* 查找算法ID是否已在列表中 */
+RoomActionInfo* ListRoomActionInfo::findActionIDInList(const int chnID, const int RoomID, const std::string& strActionID)
+{
+    for(const auto& it0 : listRoomActionInfo)
+    {
+        if((it0->RoomID == RoomID) && (it0->ActionID == strActionID) && (it0->ChannelID == chnID))
+        {
+            return it0;
+        }
+    }
+    return nullptr;
+}

+ 117 - 53
SecurePlayAuxServer/GlobalInfo/GlobalInfo.h

@@ -55,12 +55,10 @@ struct AlgorithmInfo
     }
     /* 对比是否相等 */
     bool operator==(const AlgorithmInfo& other) const {
-        if(ActionID != other.ActionID)
-        {
+        if(ActionID != other.ActionID) {
             return false;
         }
-        if(ActionName != other.ActionName || ActionTaskID != other.ActionTaskID)
-        {
+        if(ActionName != other.ActionName || ActionTaskID != other.ActionTaskID) {
             return false;
         }
         return true;
@@ -109,52 +107,9 @@ struct DeviceInfo
         return *this;
     }
     /* 对比是否相等 */
-    bool operator==(const DeviceInfo& other) const {
-        if(DeviceID != other.DeviceID) {
-            return false;
-        }
-        else if(DeviceName != other.DeviceName || DeviceIP != other.DeviceIP) {
-            return false;
-        }
-        else if(DeviceSerial != other.DeviceSerial || DeviceType != other.DeviceType) {
-            return false;
-        }
-        else if(DevicePort != other.DevicePort || UserAccount != other.UserAccount || UserPassword != other.UserPassword) {
-            return false;
-        }
-
-        return true;
-    }
+    bool operator==(const DeviceInfo& other);
     /* 对比设备关联的算法信息是否相等 */
-    bool isEqualAlgorithmInfo(const std::vector<AlgorithmInfo>& other) const {
-        /* 算法数目不相等,直接返回false */
-        if(vecAlgorithmInfo.size() != other.size()) {
-            return false;
-        }else {
-            /* 算法数目相等,进一步对比算法信息 */
-            bool isEquality = true;
-            /* 逐步对比算法信息 */
-            for(const auto& it0 : vecAlgorithmInfo) {
-                bool isEq2 = true;
-                for(const auto& it1 : other) {
-                    if(it0 == it1) {
-                        continue;
-                    }else {
-                        isEq2 = false;
-                        break;
-                    }
-                }
-                if(!isEq2) {
-                    isEquality = false;
-                    break;
-                }
-            }
-            if(!isEquality) {
-                return false;
-            }
-        }
-        return true;
-    }
+    bool isEqualAlgorithmInfo(const std::vector<AlgorithmInfo>& other);
 };
 
 
@@ -231,6 +186,7 @@ struct AlarmInfo
     std::vector<PersonInfo> vecPersonInfo;    /* 人员信息 */
 };
 
+
 /**
  * @brief 房间和摄像机关联信息,这个是从客户端配置的
  *        一个房间对应多个摄像机
@@ -239,7 +195,7 @@ struct AlarmInfo
 struct RoomCameraInfo
 {
     int RoomID;                     /* 房间ID */
-    std::list<int> listCameraID;    /* 摄像机和算法关联信息 */
+    std::list<int> listCameraID;    /* 摄像机列表 */
 
     RoomCameraInfo() = default;
     RoomCameraInfo& operator=(const RoomCameraInfo& other) {
@@ -259,25 +215,132 @@ struct RoomCameraInfo
 };
 
 
+/**
+ * @brief 单个算法信息,包括包含的摄像机,房间、频率信息
+ * 
+ */
+struct ActionInfo
+{
+    int ChannelID;                  /* 通道ID */
+    int RoomID;                     /* 房间ID */
+    int CameraID;                   /* 摄像机ID */
+    int RoomType;                   /* 房间类型 */
+    std::string ActionID;           /* 算法ID */
+    std::string strRoomName;        /* 房间名称 */
+
+    ActionInfo() = default;
+    ActionInfo& operator=(const ActionInfo& other) {
+        if (this != &other) {
+            ChannelID = other.ChannelID;
+            RoomID = other.RoomID;
+            CameraID = other.CameraID;
+            ActionID = other.ActionID;
+            strRoomName = other.strRoomName;
+            RoomType = other.RoomType;
+        }
+        return *this;
+    }
+    /* 对比 */
+    bool operator==(const ActionInfo& other) const {
+        if(ChannelID != other.ChannelID) {
+            return false;
+        }
+        if(RoomID != other.RoomID) {
+            return false;
+        }
+        if(CameraID != other.CameraID) {
+            return false;
+        }
+        if(ActionID != other.ActionID) {
+            return false;
+        }
+        if(RoomType != other.RoomType) {
+            return false;
+        }
+        return true;
+    }
+    
+};
+
+/**
+ * @brief 算法信息列表
+ * 
+ */
+class ListActionInfo
+{
+public:
+    ListActionInfo() = default;
+
+    /* 添加关联信息,会自动进行重复判断,如果已有相同的信息,则跳过 */
+    bool insertActionInfo(ActionInfo* info);
+    /* 删除信息 */
+    bool deleteActionInfo(ActionInfo* info);
+    /* 查找算法ID是否已在列表中 */
+    ActionInfo* findActionInList(ActionInfo* pInfo);
+    /* 获取容器 */
+    std::list<ActionInfo*>& getData() {
+        return listActionInfo;
+    }
+    /* 清空容器 */
+    void clear();
+
+    std::list<ActionInfo*> listActionInfo;    /* 房间和算法ID关联列表 */
+
+};
+
 /**
  * @brief 房间ID和算法ID关联的信息,里面也包含该算法使用了哪些摄像机
  * 
  */
 struct RoomActionInfo
 {
-    int RoomID;                 /* 房间ID */
-    std::string ActionID;       /* 算法ID */
-    std::list<int> listCameraID;  /* 摄像机ID */
+    int ChannelID;                  /* 通道ID */
+    int RoomID;                     /* 房间ID */
+    int RoomType;                   /* 房间类型 */
+    std::string ActionID;           /* 算法ID */
+    std::string strRoomName;        /* 房间名称 */
+    std::list<int> listCameraID;    /* 摄像机ID */
 
     RoomActionInfo() = default;
+    RoomActionInfo(const RoomActionInfo& other)
+        : ChannelID(other.ChannelID), RoomID(other.RoomID), RoomType(other.RoomType), ActionID(other.ActionID), strRoomName(other.strRoomName), listCameraID(other.listCameraID) {}
     RoomActionInfo& operator=(const RoomActionInfo& other) {
         if (this != &other) {
+            ChannelID = other.ChannelID;
             RoomID = other.RoomID;
+            RoomType = other.RoomType;
             ActionID = other.ActionID;
+            strRoomName = other.strRoomName;
             listCameraID = other.listCameraID;
         }
         return *this;
     }
+    
+
+};
+
+/* 房间和算法ID关联列表 */
+class ListRoomActionInfo
+{
+public:
+    ListRoomActionInfo() = default;
+
+    /* 添加关联信息,会自动进行重复判断,如果已有相同的room和action关联信息,则跳过 */
+    bool insertRoomActionInfo(const RoomActionInfo& info);
+    /* 添加关联信息,会自动进行重复判断,如果已有相同的room和action关联信息,则跳过 */
+    bool insertRoomActionInfo(const int RoomID, const std::string& strActionID);
+    /* 清空容器 */
+    void clear();
+    /* 添加算法信息,根据传入的算法信息,自动将其加入到对应的容器中 */
+    void addActionInfo(const ActionInfo& info);
+    /* 查找算法ID是否已在列表中 */
+    RoomActionInfo* findActionIDInList(const int chnID, const int RoomID, const std::string& strActionID);
+    /* 获取容器 */
+    std::list<RoomActionInfo*>& getData() {
+        return listRoomActionInfo;
+    }
+
+    std::list<RoomActionInfo*> listRoomActionInfo;    /* 房间和算法ID关联列表 */
 
 };
 
@@ -286,4 +349,5 @@ struct RoomActionInfo
 
 
 
+
 #endif /* GLOBALINFO_H */

+ 169 - 73
SecurePlayAuxServer/SPAServer.cpp

@@ -81,9 +81,9 @@ void SPAServer::threadFromSuperBrain()
 
         vecAlgNewInfo.clear();
         vecDevNewInfo.clear();
-        /* 更新关联关系 */
+        /* 更新算法详细信息 */
         m_mutexCameraActionID.lock();
-        m_toEQMDataBase.getDeviceAlgorithmInfo(m_mapCameraActionID);
+        m_toEQMDataBase.getActionInfo(m_listActionInfo);
         m_mutexCameraActionID.unlock();
         std::this_thread::sleep_for(std::chrono::seconds(10));
     }
@@ -562,7 +562,7 @@ bool SPAServer::isEventTimeVaild(const std::string& strTime)
 
 
 /**
- * @brief 刷新房间和摄像机关联的线程
+ * @brief 分派任务的线程
  *        线程定时刷新房间和摄像机的管理关系,以及和算法Action的关联关系
  */
 void SPAServer::threadRoomCamera()
@@ -575,113 +575,209 @@ void SPAServer::threadRoomCamera()
     while (m_threadRunning)
     {
         /* 先获取EQM数据库信息,取出房间和摄像机关联信息 */
-        toEQMDataBase->getRoomCameraInfo(listRC);
+
         /* 取出每个房间的所有算法,int是RoomID,string是Action */
         std::multimap<int, std::string> mapCameraActionID;
+        m_mutexRoomActionInfo.lock();
         m_mutexCameraActionID.lock();
-        for(const auto& it0 : listRC)
+        /* 将算法信息根据房间分类,并找到其需要的摄像机 */
+        m_listRoomActionInfo.clear();
+        for(const auto& it : m_listActionInfo.getData())
+        {
+            m_listRoomActionInfo.addActionInfo(*it);
+        }
+        /* 根据每个房间的算法功能,创建线程 */
+        for(const auto& it0 : m_listRoomActionInfo.getData())
         {
-            /* 根据房间内的摄像机的ID寻找对应的算法 */
-            for(const auto& it1 : it0.listCameraID)
+            /* 人员在岗识别,这个算法需要多个摄像机配合 */
+            if(it0->ActionID == ActPersonWork)
             {
-                for(const auto& it2 : m_mapCameraActionID)
-                {
-                    if(it1 == it2.first)
-                    {
-                    }
-                }
+                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 人员在岗识别", it0->RoomID);
+
+            }
+            /* 区域人员检测,这个需要融合检测 */
+            else if (it0->ActionID == ActPersonNumber)
+            {
+                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 区域人员检测", it0->RoomID);
+
             }
+            /* 违禁物品识别,不需要多个摄像机融合判断,多少个报警都直接上报 */
+            else if (it0->ActionID == ActContraband)
+            {
+                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 违禁品检测", it0->RoomID);
+
+            }
+            /* 非法入侵检测,这个也不需要摄像机融合 */
+            else if (it0->ActionID == ActIllegalInvasion)
+            {
+                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 非法入侵检测", it0->RoomID);
+
+            }
+            /* 疲劳检测,不需要摄像机融合检测,直接上报 */
+            else if (it0->ActionID == ActFatigueDetection)
+            {
+                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 疲劳检测", it0->RoomID);
+
+            }
+            
         }
         m_mutexCameraActionID.unlock();
-        /* 根据每个房间的算法功能,匹配其对应的摄像机 */
-        m_mutexRoomCameraInfo.lock();
-        /* 循环查找每个房间的算法ID与之关联的设备 */
-        for(const auto& it0 : mapCameraActionID)
+        m_mutexRoomActionInfo.unlock();
+    }
+}
+
+
+/* 判断相机是否有这个算法 */
+bool SPAServer::isCameraHasAction(const int CameraID, const std::string& strActionID)
+{
+    for(const auto& it : m_mapCameraActionID)
+    {
+        if(it.first == CameraID)
         {
-            /* 人员在岗识别 */
-            if(it0.second == ActPersonWork)
+            if(it.second == strActionID)
             {
-                SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 人员在岗识别", it0.first);
-                /* 先查找这个算法ID是否已在列表中 */
-                if(findActionIDInList(it0.first, it0.second) == nullptr)
-                {
-                    /* 不在列表中就创建一个 */
-                    RoomActionInfo* roomActionInfo = new RoomActionInfo;
-                    roomActionInfo->RoomID = it0.first;
-                    roomActionInfo->ActionID = it0.second;
-                    /* 将这个算法相关联的在这个房间内的相机加入其中 */
-                    for(const auto& it1 : listRC)
-                    {
-                        if(it1.RoomID == it0.first)
-                        {
-                            /* 判断这些相机哪些有这个算法 */
-                            for(const auto& it2 : it1.listCameraID)
-                            {
-                                if(isCameraHasAction(it2, it0.second))
-                                {
-                                    roomActionInfo->listCameraID.push_back(it2);
-                                }
-                            }
-                        }
-                    }
-                    m_listRoomCameraInfo.push_back(roomActionInfo);
-                } else 
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+/* 将该算法对应的摄像机放入摄像机列表 */
+bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID)
+{
+    for(const auto& rci : listRC)
+    {
+        if(rci.RoomID == pRAInfo->RoomID)
+        {
+            /* 这个摄像机在这个房间内,再判断这个摄像机有没有这个算法 */
+            for(const auto& camID : rci.listCameraID)
+            {
+                for(const auto& cai : mapCameraActionID)
                 {
-                    /* 算法在列表中,清空算法的摄像机列表,重新加入列表中 */
-                    RoomActionInfo* roomActionInfo = findActionIDInList(it0.first, it0.second);
-                    roomActionInfo->listCameraID.clear();
-                    /* 将这个算法相关联的在这个房间内的相机加入其中 */
-                    for(const auto& it1 : listRC)
+                    if(camID == cai.first)
                     {
-                        if(it1.RoomID == it0.first)
+                        /* 再判断这个摄像机的算法是否是当前需要的 */
+                        if(cai.second == pRAInfo->ActionID)
                         {
-                            /* 判断这些相机哪些有这个算法 */
-                            for(const auto& it2 : it1.listCameraID)
-                            {
-                                if(isCameraHasAction(it2, it0.second))
-                                {
-                                    roomActionInfo->listCameraID.push_back(it2);
-                                }
-                            }
+                            pRAInfo->listCameraID.push_back(camID);
                         }
                     }
                 }
             }
-            /* 违禁物品识别 */
         }
     }
+    return true;
+}
+
+/* 更新房间、算法需要的摄像机个数 */
+bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo)
+{
+    std::lock_guard<std::mutex> look(m_mutexRoomActionInfo);
+    for(auto& it : m_listRoomActionInfo.getData())
+    {
+        if((it->RoomID == pRAInfo->RoomID) && (it->ActionID == pRAInfo->ActionID))
+        {
+            it->listCameraID = pRAInfo->listCameraID;
+            break;
+        }
+    }
+
+    return true;
 }
 
 
-/* 查找算法ID是否已在列表中 */
-RoomActionInfo* SPAServer::findActionIDInList(const int RoomID, const std::string& strActionID)
+
+/**
+ * @brief 人员在岗识别线程,应该是人脸识别线程,这个需要房间内多个摄像机共同识别
+            1、离岗判断条件:直播间无人算离岗(直播间所有摄像头的区域人员检测算法输出结果都为0时记为离岗开始,
+                当结果存在非0时记为离岗结束)
+            2、离岗输出结果:当判断出离岗行为时,依据人脸识别结果,找到离岗时间点前有人的最近一帧画面中的人员,
+                判断为离岗人员,并计算离岗时长,形成离岗记录(频率、机房、离岗人员、离岗开始时间、离岗结束时间、离
+                岗持续时长)
+            3、在岗时长计算方式:每天00:00:00-23:59:59人脸识别结果中所有人员名称的出现次数✖抽帧频率(如5秒抽
+                取1帧,则出现200次人名表示在岗1000秒时长),形成每日的人员在岗时长记录
+            4、报警判断条件:依据离岗次数和单次离岗时长进行报警,展示报警结果
+ * 
+ * @param pRAInfo 传入房间ID和算法ID
+ */
+void SPAServer::threadActPersonWork(RoomActionInfo* RAInfo)
 {
-    for(const auto& it0 : m_listRoomCameraInfo)
+    SPDLOG_LOGGER_INFO(m_logger, "开启人员在岗识别线程,RoomID:{} ,Action:{}", RAInfo->RoomID, RAInfo->ActionID);
+    /* 创建读取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就退出线程 */
+    while (CameraCount > 0)
     {
-        if(it0->RoomID == RoomID)
+        /* 更新算法关联的摄像机个数 */
+        pRAInfo->listCameraID.clear();
+        updateRoomActionCameraCount(pRAInfo);
+        CameraCount = pRAInfo->listCameraID.size();
+
+        /* 读取Redis数据 */
+        for(const auto& camID : pRAInfo->listCameraID)
         {
-            if(it0->ActionID == strActionID)
+            std::string strKey = std::to_string(camID) + ":" + pRAInfo->ActionID;
+            std::string strRetValue;
+            if(!fromRedis->getRedisString(strKey, strRetValue))
             {
-                return it0;
+                SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+                continue;
             }
+            /* 解析数据 */
+            AlarmInfo alarmInfo;
+            parseRedisData(strRetValue, alarmInfo);
         }
     }
-    return nullptr;
 }
 
-/* 判断相机是否有这个算法 */
-bool SPAServer::isCameraHasAction(const int CameraID, const std::string& strActionID)
+/**
+ * @brief 区域人员检测,检测这个区域内的人数,不能少于多少人,不能多余多少人
+ *          1、报警判断条件:直播间报警:当前频率所有直播间摄像头的区域人员检测算法输出结果均大于或小于设定人
+               数值时,记为报警行为,直接展示报警结果
+            2、录播间报警:当前频率所有录播间摄像头的区域人员检测算法输出结果均大于或小于设定人数值时,记为报
+               警行为,直接展示报警结果
+            3、直播间+录播间报警:当前频率直播间人数+录播间人数大于或小于设定人数值时,记为报警行为,直接展示
+               报警结果
+ * 
+ * @param RAInfo 传入的房间ID和算法ID
+ */
+void SPAServer::threadActPersonNumber(RoomActionInfo* RAInfo)
 {
-    for(const auto& it : m_mapCameraActionID)
+    SPDLOG_LOGGER_INFO(m_logger, "开启区域人员检测线程,RoomID:{} ,Action:{}", RAInfo->RoomID, RAInfo->ActionID);
+    /* 创建读取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就退出线程 */
+    while (CameraCount > 0)
     {
-        if(it.first == CameraID)
+        /* 更新算法关联的摄像机个数 */
+        pRAInfo->listCameraID.clear();
+        updateRoomActionCameraCount(pRAInfo);
+        CameraCount = pRAInfo->listCameraID.size();
+
+        /* 读取Redis数据 */
+        for(const auto& camID : pRAInfo->listCameraID)
         {
-            if(it.second == strActionID)
+            std::string strKey = std::to_string(camID) + ":" + pRAInfo->ActionID;
+            std::string strRetValue;
+            if(!fromRedis->getRedisString(strKey, strRetValue))
             {
-                return true;
+                SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
+                continue;
             }
+            /* 解析数据 */
+            AlarmInfo alarmInfo;
+            parseRedisData(strRetValue, alarmInfo);
         }
     }
-    return false;
 }
 
+

+ 15 - 7
SecurePlayAuxServer/SPAServer.h

@@ -37,12 +37,20 @@ private:
     /* 判断时间是否长时间没有更新 */
     bool isEventTimeVaild(const std::string& strTime);
 
-    /* 刷新房间和摄像机关联的线程 */
+    /* 分派任务的线程 */
     void threadRoomCamera();
-    /* 查找算法ID是否已在列表中 */
-    RoomActionInfo* findActionIDInList(const int RoomID, const std::string& strActionID);
     /* 判断相机是否有这个算法 */
     bool isCameraHasAction(const int CameraID, const std::string& strActionID);
+    /* 将该算法对应的摄像机放入摄像机列表 */
+    bool insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID);
+    /* 更新房间、算法需要的摄像机个数 */
+    bool updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo);
+    
+    /* 人员在岗识别线程,应该是人脸识别线程,这个需要房间内多个摄像机共同识别 */
+    void threadActPersonWork(RoomActionInfo* RAInfo);
+    /* 区域人员检测,检测这个区域内的人数,不能少于多少人,不能多余多少人 */
+    void threadActPersonNumber(RoomActionInfo* RAInfo);
+
 
 private:
     std::shared_ptr<spdlog::logger> m_logger = nullptr;
@@ -56,11 +64,10 @@ private:
     std::string m_KeyFace;                              /* 人脸检测的Key */
 
     std::string ActPersonWork;                          /* 人员在岗识别 */
+    std::string ActPersonNumber;                        /* 区域人员检测 */
     std::string ActContraband;                          /* 违禁品检测 */
     std::string ActIllegalInvasion;                     /* 非法入侵检测 */
     std::string ActFatigueDetection;                    /* 疲劳检测 */
-    std::string ActPersonNumber;                        /* 区域人员检测 */
-    
 
     /* 算法信息,这个就是tAction在内存中的数据,方便后续对比,程序启动的时候会先获取一份 */
     std::vector<AlgorithmInfo> m_vecEqmAlgInfo;
@@ -69,11 +76,12 @@ private:
     /* 摄像机ID和算法ID对应表 */
     std::mutex m_mutexCameraActionID;
     std::multimap<int, std::string> m_mapCameraActionID;
+    ListActionInfo m_listActionInfo;
     /* 设备和算法关联信息,这里存储着已经删除的设备对应的算法信息,将在这一轮循环中删除 */
     std::list<int> m_listDevIDDelete;
     /* 房间和算法关联的信息,包含所需要的摄像机ID */
-    std::mutex m_mutexRoomCameraInfo;
-    std::list<RoomActionInfo*> m_listRoomCameraInfo;
+    std::mutex m_mutexRoomActionInfo;
+    ListRoomActionInfo m_listRoomActionInfo;
 
 };
 

+ 12 - 7
SecurePlayAuxServer/communication/ToEQMDataBase.cpp

@@ -671,17 +671,17 @@ bool ToEQMDataBase::getDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo, std
     return true;
 }
 
-/* 获取设备和算法关联信息,重载版,只获取关联关系 */
-bool ToEQMDataBase::getDeviceAlgorithmInfo(std::multimap<int, std::string>& mapCameraActionID)
+/* 获取设备和算法关联信息,包括频率信息,房间信息,重载版,只获取关联关系 */
+bool ToEQMDataBase::getActionInfo(ListActionInfo& listInfo)
 {
     if(m_httpApi == nullptr)
     {
         SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
         return false;
     }
-    mapCameraActionID.clear();
+    listInfo.clear();
     nJson json0;
-    json0["opName"] = "SPSS_SelectFromActionCamer";
+    json0["opName"] = "SPSS_SelectFromActionInfo";
     QString strCmd = QString::fromStdString(json0.dump());
     QString strRet;
     auto ret = m_httpApi->DBQDoInterface(enDBOperatorType::EDBOT_Select, strCmd, strRet);
@@ -708,9 +708,14 @@ bool ToEQMDataBase::getDeviceAlgorithmInfo(std::multimap<int, std::string>& mapC
         /* 取出所有的设备算法信息 */
         for(const auto& it : result)
         {
-            int cameraID = it["camerId"].get<int>();
-            std::string actionID = it["actionId"].is_null() ? "" : it["actionId"].get<std::string>();
-            mapCameraActionID.insert(std::make_pair(cameraID, actionID));
+            ActionInfo info;
+            info.CameraID = it["camerId"].is_null() ? -1 : it["camerId"].get<int>();
+            info.ActionID = it["actionId"].is_null() ? "" : it["actionId"].get<std::string>();
+            info.RoomID = it["roomId"].is_null() ? -1 : it["roomId"].get<int>();
+            info.ChannelID = it["chnid"].is_null() ? -1 : it["chnid"].get<int>();
+            info.RoomType = it["rtype"].is_null() ? -1 : it["rtype"].get<int>();
+            info.strRoomName = it["rname"].is_null() ? "" : it["rname"].get<std::string>();
+            listInfo.insertActionInfo(&info);
         }
     }
     catch (const nJson::parse_error& e) {

+ 2 - 1
SecurePlayAuxServer/communication/ToEQMDataBase.h

@@ -39,7 +39,8 @@ public:
     bool deleteDeviceAlgorithmInfo(std::list<int>& vecID);
     /* 获取设备和算法信息关联表,需要先从EQM数据库中获取到设备信息,然后根据读取到的设备信息,取出已经删除的设备ID */
     bool getDeviceAlgorithmInfo(std::vector<DeviceInfo>& vecInfo, std::list<int>& listDevIDDelete);
-    bool getDeviceAlgorithmInfo(std::multimap<int, std::string>& mapCameraActionID);
+    /* 获取每个算法的详细信息 */
+    bool getActionInfo(ListActionInfo& listInfo);
 
     /* 获取摄像机和房间关联信息 */
     bool getRoomCameraInfo(std::list<RoomCameraInfo>& vecInfo);