|
@@ -82,9 +82,9 @@ void SPAServer::threadFromSuperBrain()
|
|
vecAlgNewInfo.clear();
|
|
vecAlgNewInfo.clear();
|
|
vecDevNewInfo.clear();
|
|
vecDevNewInfo.clear();
|
|
/* 更新算法详细信息 */
|
|
/* 更新算法详细信息 */
|
|
- m_mutexCameraActionID.lock();
|
|
|
|
|
|
+ m_mutexActionInfo.lock();
|
|
m_toEQMDataBase.getActionInfo(m_listActionInfo);
|
|
m_toEQMDataBase.getActionInfo(m_listActionInfo);
|
|
- m_mutexCameraActionID.unlock();
|
|
|
|
|
|
+ m_mutexActionInfo.unlock();
|
|
std::this_thread::sleep_for(std::chrono::seconds(10));
|
|
std::this_thread::sleep_for(std::chrono::seconds(10));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -137,27 +137,27 @@ bool SPAServer::processDeviceInfo(std::vector<DeviceInfo> vecNewDevInfo)
|
|
/* 如果本地缓存没有数据,那么就全部插入 */
|
|
/* 如果本地缓存没有数据,那么就全部插入 */
|
|
if(m_vecEqmDevInfo.size() > 0)
|
|
if(m_vecEqmDevInfo.size() > 0)
|
|
{
|
|
{
|
|
- for(const auto& it : vecNewDevInfo)
|
|
|
|
|
|
+ for(auto& DevInfo : vecNewDevInfo)
|
|
{
|
|
{
|
|
bool isExist = false;
|
|
bool isExist = false;
|
|
- for(const auto& it0 : m_vecEqmDevInfo)
|
|
|
|
|
|
+ for(auto& it0 : m_vecEqmDevInfo)
|
|
{
|
|
{
|
|
- if(it.DeviceID == it0.DeviceID)
|
|
|
|
|
|
+ if(DevInfo.DeviceID == it0.DeviceID)
|
|
{
|
|
{
|
|
isExist = true;
|
|
isExist = true;
|
|
/* 对比其他项是否相等,不相等就更新 */
|
|
/* 对比其他项是否相等,不相等就更新 */
|
|
- if(it == it0)
|
|
|
|
|
|
+ if(DevInfo == it0)
|
|
{
|
|
{
|
|
continue;
|
|
continue;
|
|
}else {
|
|
}else {
|
|
- vecDevUpdate.push_back(it);
|
|
|
|
|
|
+ vecDevUpdate.push_back(DevInfo);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!isExist)
|
|
if(!isExist)
|
|
{
|
|
{
|
|
- vecDevInsert.push_back(it);
|
|
|
|
|
|
+ vecDevInsert.push_back(DevInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}else {
|
|
}else {
|
|
@@ -548,22 +548,35 @@ void SPAServer::parseRedisData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
bool SPAServer::isEventTimeVaild(const std::string& strTime)
|
|
bool SPAServer::isEventTimeVaild(const std::string& strTime)
|
|
{
|
|
{
|
|
/* 获取当前时间 */
|
|
/* 获取当前时间 */
|
|
- time_t now = time(0);
|
|
|
|
|
|
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
|
/* 字符串转成时间 */
|
|
/* 字符串转成时间 */
|
|
- tm tmTime;
|
|
|
|
- strptime(strTime.c_str(), "%Y-%m-%d %H:%M:%S", &tmTime);
|
|
|
|
- time_t eventTime = mktime(&tmTime);
|
|
|
|
|
|
+ std::istringstream iss(strTime);
|
|
|
|
+ std::tm tmEvent = {};
|
|
|
|
+ iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
|
|
/* 时间差 */
|
|
/* 时间差 */
|
|
- double diff = difftime(now, eventTime);
|
|
|
|
- SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
|
|
|
|
-
|
|
|
|
|
|
+ std::chrono::system_clock::time_point eventTime = std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
|
|
|
|
+ std::chrono::duration<double> diff = now - eventTime;
|
|
|
|
+ // SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
|
|
|
|
+ if(diff.count() > 600)
|
|
|
|
+ {
|
|
|
|
+ // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
* @brief 分派任务的线程
|
|
* @brief 分派任务的线程
|
|
- * 线程定时刷新房间和摄像机的管理关系,以及和算法Action的关联关系
|
|
|
|
|
|
+ 1、 线程定时刷新房间和摄像机的关联关系,以及和算法Action的关联关系
|
|
|
|
+ 2、 将算法信息加入到不同的列表中
|
|
|
|
+ 需要多个摄像机配合的加入到m_runListRoomActionInfo列表
|
|
|
|
+ 不需要多个摄像机配合的加入到m_runListActionInfo列表
|
|
|
|
+ 3、 每次刷新都会清空算法的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,就会创建新的ActionInfo
|
|
|
|
+ 那么RunState的状态是INIT,需要开启新的线程
|
|
|
|
+ 如果刷新完成后,算法对应的摄像机列表为空,那么对应的线程就会停止运行,将RunState设置为STOP,本线程的下一轮
|
|
|
|
+ 循环就会删除这个ActionInfo
|
|
|
|
+
|
|
*/
|
|
*/
|
|
void SPAServer::threadRoomCamera()
|
|
void SPAServer::threadRoomCamera()
|
|
{
|
|
{
|
|
@@ -578,71 +591,82 @@ void SPAServer::threadRoomCamera()
|
|
|
|
|
|
/* 取出每个房间的所有算法,int是RoomID,string是Action */
|
|
/* 取出每个房间的所有算法,int是RoomID,string是Action */
|
|
std::multimap<int, std::string> mapCameraActionID;
|
|
std::multimap<int, std::string> mapCameraActionID;
|
|
- m_mutexRoomActionInfo.lock();
|
|
|
|
- m_mutexCameraActionID.lock();
|
|
|
|
- /* 将算法信息根据房间分类,并找到其需要的摄像机 */
|
|
|
|
- m_listRoomActionInfo.clear();
|
|
|
|
|
|
+ m_mutexRunRAI.lock();
|
|
|
|
+ m_mutexActionInfo.lock();
|
|
|
|
+ /* 先清理已经退出的线程所用到的Action或者RoomAction */
|
|
|
|
+ m_runListRoomActionInfo.clearStopRoomAction();
|
|
|
|
+ m_runListActionInfo.clearStopAction();
|
|
|
|
+
|
|
|
|
+ m_mutexRunActionInfo.lock();
|
|
|
|
+ /* 将算法信息加入到不同的列表中
|
|
|
|
+ * 需要多个摄像机配合的加入到m_runListRoomActionInfo列表
|
|
|
|
+ * 不需要多个摄像机配合的加入到m_runListActionInfo列表
|
|
|
|
+ * */
|
|
|
|
+ m_runListRoomActionInfo.clearCameraList();
|
|
|
|
+ m_runListActionInfo.clearCameraList();
|
|
for(const auto& it : m_listActionInfo.getData())
|
|
for(const auto& it : m_listActionInfo.getData())
|
|
{
|
|
{
|
|
- m_listRoomActionInfo.addActionInfo(*it);
|
|
|
|
|
|
+ if(it->ActionID == ActPersonWork || it->ActionID == ActPersonNumber)
|
|
|
|
+ {
|
|
|
|
+ m_runListRoomActionInfo.addActionInfo(*it);
|
|
|
|
+ }else {
|
|
|
|
+ m_runListActionInfo.addActionCamera(it);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- /* 根据每个房间的算法功能,创建线程 */
|
|
|
|
- for(const auto& it0 : m_listRoomActionInfo.getData())
|
|
|
|
|
|
+ m_mutexActionInfo.unlock();
|
|
|
|
+ /* 这个容器只用于多个摄像机融合的算法,一个房间的一个算法是一个线程 */
|
|
|
|
+ for(const auto& it0 : m_runListRoomActionInfo.getData())
|
|
{
|
|
{
|
|
- /* 人员在岗识别,这个算法需要多个摄像机配合 */
|
|
|
|
|
|
+ /* 人员在岗识别 */
|
|
if(it0->ActionID == ActPersonWork)
|
|
if(it0->ActionID == ActPersonWork)
|
|
{
|
|
{
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 人员在岗识别", it0->RoomID);
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 人员在岗识别", it0->RoomID);
|
|
-
|
|
|
|
|
|
+ /* 判断是否需要创建新的线程 */
|
|
|
|
+ if(it0->RunState == RunTimeState::RUN_STATE_INIT)
|
|
|
|
+ {
|
|
|
|
+ /* 创建新的线程 */
|
|
|
|
+ CPPTP.add_task(&SPAServer::threadActPersonWork, this, it0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- /* 区域人员检测,这个需要融合检测 */
|
|
|
|
|
|
+ /* 区域人员检测 */
|
|
else if (it0->ActionID == ActPersonNumber)
|
|
else if (it0->ActionID == ActPersonNumber)
|
|
{
|
|
{
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 区域人员检测", it0->RoomID);
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 区域人员检测", it0->RoomID);
|
|
-
|
|
|
|
|
|
+ if(it0->RunState == RunTimeState::RUN_STATE_INIT)
|
|
|
|
+ {
|
|
|
|
+ CPPTP.add_task(&SPAServer::threadActPersonNumber, this, it0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+ /* 这个容器用于不关联的算法信息,每个设备上的每个算法是一个线程 */
|
|
|
|
+ for(const auto& it0 : m_runListActionInfo.getData())
|
|
|
|
+ {
|
|
/* 违禁物品识别,不需要多个摄像机融合判断,多少个报警都直接上报 */
|
|
/* 违禁物品识别,不需要多个摄像机融合判断,多少个报警都直接上报 */
|
|
- else if (it0->ActionID == ActContraband)
|
|
|
|
|
|
+ if (it0->ActionID == ActContraband)
|
|
{
|
|
{
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 违禁品检测", it0->RoomID);
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 违禁品检测", it0->RoomID);
|
|
-
|
|
|
|
|
|
+ if(it0->RunState == RunTimeState::RUN_STATE_INIT)
|
|
|
|
+ {
|
|
|
|
+ CPPTP.add_task(&SPAServer::threadActContraband, this, it0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
/* 非法入侵检测,这个也不需要摄像机融合 */
|
|
/* 非法入侵检测,这个也不需要摄像机融合 */
|
|
else if (it0->ActionID == ActIllegalInvasion)
|
|
else if (it0->ActionID == ActIllegalInvasion)
|
|
{
|
|
{
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 非法入侵检测", it0->RoomID);
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 非法入侵检测", it0->RoomID);
|
|
-
|
|
|
|
}
|
|
}
|
|
/* 疲劳检测,不需要摄像机融合检测,直接上报 */
|
|
/* 疲劳检测,不需要摄像机融合检测,直接上报 */
|
|
else if (it0->ActionID == ActFatigueDetection)
|
|
else if (it0->ActionID == ActFatigueDetection)
|
|
{
|
|
{
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 疲劳检测", it0->RoomID);
|
|
SPDLOG_LOGGER_INFO(m_logger, "RoomID:{} 疲劳检测", it0->RoomID);
|
|
-
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
- m_mutexCameraActionID.unlock();
|
|
|
|
- m_mutexRoomActionInfo.unlock();
|
|
|
|
|
|
+ m_mutexRunRAI.unlock();
|
|
|
|
+ m_mutexRunActionInfo.unlock();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-/* 判断相机是否有这个算法 */
|
|
|
|
-bool SPAServer::isCameraHasAction(const int CameraID, const std::string& strActionID)
|
|
|
|
-{
|
|
|
|
- for(const auto& it : m_mapCameraActionID)
|
|
|
|
- {
|
|
|
|
- if(it.first == CameraID)
|
|
|
|
- {
|
|
|
|
- if(it.second == strActionID)
|
|
|
|
- {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* 将该算法对应的摄像机放入摄像机列表 */
|
|
/* 将该算法对应的摄像机放入摄像机列表 */
|
|
bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID)
|
|
bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCameraInfo>& listRC, std::multimap<int, std::string>& mapCameraActionID)
|
|
{
|
|
{
|
|
@@ -673,8 +697,8 @@ bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCame
|
|
/* 更新房间、算法需要的摄像机个数 */
|
|
/* 更新房间、算法需要的摄像机个数 */
|
|
bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo)
|
|
bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo)
|
|
{
|
|
{
|
|
- std::lock_guard<std::mutex> look(m_mutexRoomActionInfo);
|
|
|
|
- for(auto& it : m_listRoomActionInfo.getData())
|
|
|
|
|
|
+ std::lock_guard<std::mutex> look(m_mutexRunRAI);
|
|
|
|
+ for(auto& it : m_runListRoomActionInfo.getData())
|
|
{
|
|
{
|
|
if((it->RoomID == pRAInfo->RoomID) && (it->ActionID == pRAInfo->ActionID))
|
|
if((it->RoomID == pRAInfo->RoomID) && (it->ActionID == pRAInfo->ActionID))
|
|
{
|
|
{
|
|
@@ -686,6 +710,36 @@ bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAI
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* 更新算法的摄像机ID */
|
|
|
|
+bool SPAServer::updateActionCameraID(std::shared_ptr<ActionInfo> pInfo)
|
|
|
|
+{
|
|
|
|
+ pInfo->CameraID = -1;
|
|
|
|
+ std::lock_guard<std::mutex> look(m_mutexRunActionInfo);
|
|
|
|
+ for(auto& it : m_runListActionInfo.getData())
|
|
|
|
+ {
|
|
|
|
+ if(it->isEqualBaseInfo(*pInfo))
|
|
|
|
+ {
|
|
|
|
+ pInfo->CameraID = it->CameraID;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 设置线程状态 */
|
|
|
|
+void SPAServer::setThreadState(std::shared_ptr<ActionInfo> pInfo, RunTimeState state)
|
|
|
|
+{
|
|
|
|
+ std::lock_guard<std::mutex> look(m_mutexRunActionInfo);
|
|
|
|
+ for(auto& it : m_runListActionInfo.getData())
|
|
|
|
+ {
|
|
|
|
+ if(it->isEqualBaseInfo(*pInfo))
|
|
|
|
+ {
|
|
|
|
+ it->RunState = state;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -711,12 +765,16 @@ void SPAServer::threadActPersonWork(RoomActionInfo* RAInfo)
|
|
*pRAInfo = *RAInfo;
|
|
*pRAInfo = *RAInfo;
|
|
int CameraCount = pRAInfo->listCameraID.size();
|
|
int CameraCount = pRAInfo->listCameraID.size();
|
|
/* 摄像机数目小于0就退出线程 */
|
|
/* 摄像机数目小于0就退出线程 */
|
|
- while (CameraCount > 0)
|
|
|
|
|
|
+ while (m_threadRunning)
|
|
{
|
|
{
|
|
/* 更新算法关联的摄像机个数 */
|
|
/* 更新算法关联的摄像机个数 */
|
|
pRAInfo->listCameraID.clear();
|
|
pRAInfo->listCameraID.clear();
|
|
updateRoomActionCameraCount(pRAInfo);
|
|
updateRoomActionCameraCount(pRAInfo);
|
|
CameraCount = pRAInfo->listCameraID.size();
|
|
CameraCount = pRAInfo->listCameraID.size();
|
|
|
|
+ if(CameraCount == 0)
|
|
|
|
+ {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
/* 读取Redis数据 */
|
|
/* 读取Redis数据 */
|
|
for(const auto& camID : pRAInfo->listCameraID)
|
|
for(const auto& camID : pRAInfo->listCameraID)
|
|
@@ -754,14 +812,18 @@ void SPAServer::threadActPersonNumber(RoomActionInfo* RAInfo)
|
|
/* 局部变量 */
|
|
/* 局部变量 */
|
|
std::shared_ptr<RoomActionInfo> pRAInfo = std::make_shared<RoomActionInfo>();
|
|
std::shared_ptr<RoomActionInfo> pRAInfo = std::make_shared<RoomActionInfo>();
|
|
*pRAInfo = *RAInfo;
|
|
*pRAInfo = *RAInfo;
|
|
- int CameraCount = pRAInfo->listCameraID.size();
|
|
|
|
- /* 摄像机数目小于0就退出线程 */
|
|
|
|
- while (CameraCount > 0)
|
|
|
|
|
|
+ int CameraCount = 0;
|
|
|
|
+ /* 摄像机数目等于0就退出线程 */
|
|
|
|
+ while (m_threadRunning)
|
|
{
|
|
{
|
|
/* 更新算法关联的摄像机个数 */
|
|
/* 更新算法关联的摄像机个数 */
|
|
pRAInfo->listCameraID.clear();
|
|
pRAInfo->listCameraID.clear();
|
|
updateRoomActionCameraCount(pRAInfo);
|
|
updateRoomActionCameraCount(pRAInfo);
|
|
CameraCount = pRAInfo->listCameraID.size();
|
|
CameraCount = pRAInfo->listCameraID.size();
|
|
|
|
+ if(CameraCount == 0)
|
|
|
|
+ {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
/* 读取Redis数据 */
|
|
/* 读取Redis数据 */
|
|
for(const auto& camID : pRAInfo->listCameraID)
|
|
for(const auto& camID : pRAInfo->listCameraID)
|
|
@@ -780,4 +842,101 @@ void SPAServer::threadActPersonNumber(RoomActionInfo* RAInfo)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @brief 报警判断条件:机房内出现摄像头的违禁物品识别算法输出结果包含指定违规内容时,记为报警行为,直接
|
|
|
|
+ 展示报警结果
|
|
|
|
+ *
|
|
|
|
+ * @param info
|
|
|
|
+ */
|
|
|
|
+void SPAServer::threadActContraband(ActionInfo* info)
|
|
|
|
+{
|
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "开启违禁物品识别线程,RoomID:{} ,Action:{}", info->RoomID, info->ActionID);
|
|
|
|
+ /* 创建读取Redis的实例 */
|
|
|
|
+ std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
|
|
|
|
+ /* 局部变量,保存这个线程的信息 */
|
|
|
|
+ std::shared_ptr<ActionInfo> pActInfo = std::make_shared<ActionInfo>();
|
|
|
|
+ *pActInfo = *info;
|
|
|
|
+ /* 摄像机ID小于0就退出线程 */
|
|
|
|
+ while (m_threadRunning)
|
|
|
|
+ {
|
|
|
|
+ /* 更新算法关联的摄像机ID */
|
|
|
|
+ updateActionCameraID(pActInfo);
|
|
|
|
+ /* 如果摄像机ID是小于0,那么这个算法就没有对应的摄像机了,线程就退出了 */
|
|
|
|
+ if(pActInfo->CameraID < 0)
|
|
|
|
+ {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ /* 读取Redis数据 */
|
|
|
|
+ std::string strKey = std::to_string(pActInfo->CameraID) + ":" + pActInfo->ActionID;
|
|
|
|
+ std::string strRetValue;
|
|
|
|
+ if(!fromRedis->getRedisString(strKey, strRetValue))
|
|
|
|
+ {
|
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /* 解析数据 */
|
|
|
|
+ AlarmInfo alarmInfo;
|
|
|
|
+ parseRedisData(strRetValue, alarmInfo);
|
|
|
|
+ /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
|
|
|
|
+ if(isEventTimeVaild(alarmInfo.EventTime))
|
|
|
|
+ {
|
|
|
|
+ SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /* 判断有无报警记录,写入到EQM数据库 */
|
|
|
|
+ }
|
|
|
|
+ /* 设置线程退出的状态 */
|
|
|
|
+ setThreadState(pActInfo, RunTimeState::RUN_STATE_STOP);
|
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "违禁物品识别线程退出,RoomID:{} ,CameraID, Action:{}", pActInfo->RoomID, pActInfo->CameraID, pActInfo->ActionID);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief 1、野猫、宠物识别:报警判断条件:机房内出现摄像头的宠物识别算法输出报警结果时,记为报警行为,直接
|
|
|
|
+ 展示报警结果
|
|
|
|
+ 2、无权限人员识别:报警判断条件:当判断出区域非法入侵行为时,依据人脸识别结果,判断是否为人脸库人
|
|
|
|
+ 员,非人脸库的人员时判断为非法入侵行为(背影需要报警需要结合区域人员检测算法判断)
|
|
|
|
+ *
|
|
|
|
+ * @param info
|
|
|
|
+ */
|
|
|
|
+void SPAServer::threadActIllegalInvasion(ActionInfo* info)
|
|
|
|
+{
|
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "开启非法入侵检测线程,RoomID:{} ,Action:{}", info->RoomID, info->ActionID);
|
|
|
|
+ /* 创建读取Redis的实例 */
|
|
|
|
+ std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
|
|
|
|
+ /* 局部变量,保存这个线程的信息 */
|
|
|
|
+ std::shared_ptr<ActionInfo> pActInfo = std::make_shared<ActionInfo>();
|
|
|
|
+ *pActInfo = *info;
|
|
|
|
+ /* 摄像机ID小于0就退出线程 */
|
|
|
|
+ while (m_threadRunning)
|
|
|
|
+ {
|
|
|
|
+ /* 更新算法关联的摄像机ID */
|
|
|
|
+ updateActionCameraID(pActInfo);
|
|
|
|
+ /* 如果摄像机ID是小于0,那么这个算法就没有对应的摄像机了,线程就退出了 */
|
|
|
|
+ if(pActInfo->CameraID < 0)
|
|
|
|
+ {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ /* 读取Redis数据 */
|
|
|
|
+ std::string strKey = std::to_string(pActInfo->CameraID) + ":" + pActInfo->ActionID;
|
|
|
|
+ std::string strRetValue;
|
|
|
|
+ if(!fromRedis->getRedisString(strKey, strRetValue))
|
|
|
|
+ {
|
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /* 解析数据 */
|
|
|
|
+ AlarmInfo alarmInfo;
|
|
|
|
+ parseRedisData(strRetValue, alarmInfo);
|
|
|
|
+ /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
|
|
|
|
+ if(isEventTimeVaild(alarmInfo.EventTime))
|
|
|
|
+ {
|
|
|
|
+ SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, alarmInfo.EventTime);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ /* 判断有无报警记录,写入到EQM数据库 */
|
|
|
|
+ }
|
|
|
|
+ /* 设置线程退出的状态 */
|
|
|
|
+ setThreadState(pActInfo, RunTimeState::RUN_STATE_STOP);
|
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "非法入侵检测线程退出,RoomID:{} ,CameraID:{}, Action:{}", pActInfo->RoomID, pActInfo->CameraID, pActInfo->ActionID);
|
|
|
|
+}
|
|
|
|
|