|
@@ -33,7 +33,7 @@ SPAServer::SPAServer()
|
|
|
/* 初始化WebAPI */
|
|
|
m_toEQMDataBase.initWebApi("http://192.1.3.133:31000/v6/", "", "4c2f9fc91c22dd98331e47af2e2964f4");
|
|
|
/* 模拟违禁品算法ID,后续需要动态调整 */
|
|
|
- m_keyContraband = "OD210_026_005246_001-IZRTKyEx";
|
|
|
+ g_actionList.ActContraband = "OD210_026_005246_001-IZRTKyEx";
|
|
|
|
|
|
}
|
|
|
|
|
@@ -55,7 +55,7 @@ void SPAServer::startServer()
|
|
|
info.RedisPWD = "Ff1z@TOFr^iwd%Ra";
|
|
|
info.DeviceID = 117;
|
|
|
info.vecAction.push_back("OD210_026_005246_001-IZRTKyEx");
|
|
|
- m_keyContraband = "OD210_026_005246_001-IZRTKyEx";
|
|
|
+ g_actionList.ActContraband = "OD210_026_005246_001-IZRTKyEx";
|
|
|
// CPPTP.add_task(&SPAServer::threadFromRedis, this, info);
|
|
|
// threadFromRedis(info);
|
|
|
}
|
|
@@ -467,7 +467,7 @@ void SPAServer::parseRedisData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
|
/* 这一条Box数据报警了将其内容存储起来 */
|
|
|
alarmInfo.Is_Alarm = true;
|
|
|
/* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
|
|
|
- if(alarmInfo.ActionID == m_keyContraband)
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActContraband)
|
|
|
{
|
|
|
/* 解析报警,取出报警类型 */
|
|
|
nJson label = it0["label"];
|
|
@@ -515,7 +515,7 @@ void SPAServer::parseRedisData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
|
{
|
|
|
/* 添加报警信息的提示信息 */
|
|
|
alarmInfo.BboxList = bboxList;
|
|
|
- if( (alarmInfo.ActionID == m_keyContraband) && !labelList.empty() )
|
|
|
+ if( (alarmInfo.ActionID == g_actionList.ActContraband) && !labelList.empty() )
|
|
|
{
|
|
|
alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "{}", alarmInfo.ActionDes);
|
|
@@ -529,7 +529,7 @@ void SPAServer::parseRedisData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
|
return;
|
|
|
}
|
|
|
/* 如果是人员报警,就存储人员报警信息 */
|
|
|
- if(alarmInfo.ActionID == m_KeyFace)
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActFace)
|
|
|
{
|
|
|
nJson jsonArray = json0["personList"];
|
|
|
for(auto& it : jsonArray)
|
|
@@ -625,7 +625,7 @@ void SPAServer::parseRedisBBoxesData(const std::string& strData, AlarmInfo& alar
|
|
|
/* 这一条Box数据报警了将其内容存储起来 */
|
|
|
alarmInfo.Is_Alarm = true;
|
|
|
/* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
|
|
|
- if(alarmInfo.ActionID == m_keyContraband)
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActContraband)
|
|
|
{
|
|
|
/* 解析报警,取出报警类型 */
|
|
|
nJson label = it0["label"];
|
|
@@ -674,7 +674,7 @@ void SPAServer::parseRedisBBoxesData(const std::string& strData, AlarmInfo& alar
|
|
|
/* 添加报警信息的提示信息 */
|
|
|
alarmInfo.BboxList = bboxList;
|
|
|
/* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
|
|
|
- if( (alarmInfo.ActionID == m_keyContraband) && !labelList.empty() )
|
|
|
+ if( (alarmInfo.ActionID == g_actionList.ActContraband) && !labelList.empty() )
|
|
|
{
|
|
|
alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "{}", alarmInfo.ActionDes);
|
|
@@ -689,7 +689,7 @@ void SPAServer::parseRedisBBoxesData(const std::string& strData, AlarmInfo& alar
|
|
|
return;
|
|
|
}
|
|
|
/* 如果是人员报警,就存储人员报警信息 */
|
|
|
- if(alarmInfo.ActionID == m_KeyFace)
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActFace)
|
|
|
{
|
|
|
nJson jsonArray = json0["personList"];
|
|
|
for(auto& it : jsonArray)
|
|
@@ -833,26 +833,27 @@ void SPAServer::threadRoomCamera()
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * @brief 人员在岗识别线程,应该是人脸识别线程,这个需要房间内多个摄像机共同识别
|
|
|
- 1、离岗判断条件:直播间无人算离岗(直播间所有摄像头的区域人员检测算法输出结果都为0时记为离岗开始,
|
|
|
- 当结果存在非0时记为离岗结束)
|
|
|
- 2、离岗输出结果:当判断出离岗行为时,依据人脸识别结果,找到离岗时间点前有人的最近一帧画面中的人员,
|
|
|
- 判断为离岗人员,并计算离岗时长,形成离岗记录(频率、机房、离岗人员、离岗开始时间、离岗结束时间、离
|
|
|
- 岗持续时长)
|
|
|
- 3、在岗时长计算方式:每天00:00:00-23:59:59人脸识别结果中所有人员名称的出现次数✖抽帧频率(如5秒抽
|
|
|
- 取1帧,则出现200次人名表示在岗1000秒时长),形成每日的人员在岗时长记录
|
|
|
- 4、报警判断条件:依据离岗次数和单次离岗时长进行报警,展示报警结果
|
|
|
+ * @brief 人员在岗识别线程,这个功能主要是给客户端提供实时的人脸识别信息
|
|
|
+ * 1、这个写入tWorkOnInfo表格,十分钟写一次
|
|
|
+ * 2、理论上这里需要实时更新数据库,但是实际上时每十分钟写入一次数据
|
|
|
*
|
|
|
- * @param pRAInfo 传入房间ID和算法ID
|
|
|
+ * @param RFAInfo 传入房间ID和算法ID
|
|
|
*/
|
|
|
void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
|
|
|
{
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
|
|
|
/* 创建读取Redis的实例 */
|
|
|
std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
|
|
|
+ /* 创建写入数据库实例 */
|
|
|
+ std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
|
|
|
/* 局部变量 */
|
|
|
std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
|
|
|
*pRFAInfo = *RFAInfo;
|
|
|
+
|
|
|
+ /* 保存每个摄像机的报警信息 */
|
|
|
+ std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
|
|
|
+ /* 保存人脸信息的数据 */
|
|
|
+ std::shared_ptr<ListRoomFaceInfo> pListRoomFaceInfo = std::make_shared<ListRoomFaceInfo>();
|
|
|
|
|
|
while (m_threadRunning)
|
|
|
{
|
|
@@ -864,6 +865,7 @@ void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
|
|
|
}
|
|
|
|
|
|
/* 读取Redis数据 */
|
|
|
+ pListAlarmInfo->clear();
|
|
|
for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
|
|
|
{
|
|
|
for(const auto& it : RoomInfo.mapCameraAction)
|
|
@@ -879,41 +881,96 @@ void SPAServer::threadActPersonWork(FuncActionInfo* RFAInfo)
|
|
|
/* 解析数据 */
|
|
|
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);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-
|
|
|
+ /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
|
|
|
+ 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").toStdString());
|
|
|
+ /* 删除这条信息 */
|
|
|
+ it = pListRoomFaceInfo->listRoomFaceInfo.erase(it);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
+ ++it;
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
setThreadState(pRFAInfo, RunTimeState::RUN_STATE_STOP);
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
- * @brief 区域人员检测,检测这个区域内的人数,不能少于多少人,不能多余多少人
|
|
|
- * 1、报警判断条件:直播间报警:当前频率所有直播间摄像头的区域人员检测算法输出结果均大于或小于设定人
|
|
|
- 数值时,记为报警行为,直接展示报警结果
|
|
|
- 2、录播间报警:当前频率所有录播间摄像头的区域人员检测算法输出结果均大于或小于设定人数值时,记为报
|
|
|
- 警行为,直接展示报警结果
|
|
|
- 3、直播间+录播间报警:当前频率直播间人数+录播间人数大于或小于设定人数值时,记为报警行为,直接展示
|
|
|
- 报警结果
|
|
|
+ * @brief 区域非法入侵检测
|
|
|
+ 1、野猫、宠物识别:报警判断条件:机房内出现摄像头的宠物识别算法输出报警结果时,记为报警行为,直接
|
|
|
+ 展示报警结果
|
|
|
+ 2、无权限人员识别:报警判断条件:当判断出区域非法入侵行为时,依据人脸识别结果,判断是否为人脸库人
|
|
|
+ 员,非人脸库的人员时判断为非法入侵行为(背影需要报警需要结合区域人员检测算法判断)
|
|
|
+ 3、人员计数和人脸识别数不相等时,判断为非法入侵行为
|
|
|
*
|
|
|
- * @param RAInfo 传入的房间ID和算法ID
|
|
|
+ * @param info
|
|
|
*/
|
|
|
-void SPAServer::threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo)
|
|
|
+void SPAServer::threadActIllegalInvasion(FuncActionInfo* RFAInfo)
|
|
|
{
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
|
|
|
/* 创建读取Redis的实例 */
|
|
|
std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
|
|
|
- /* 局部变量 */
|
|
|
- std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
|
|
|
/* 创建写入数据库实例 */
|
|
|
std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
|
|
|
+ /* 局部变量 */
|
|
|
+ std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
|
|
|
*pRFAInfo = *RFAInfo;
|
|
|
/* 保存每个摄像机的报警信息 */
|
|
|
std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
|
|
|
- /* 保存人员计数的信息 */
|
|
|
- std::shared_ptr<ListRoomFaceInfo> pListRoomFaceInfo = std::make_shared<ListRoomFaceInfo>();
|
|
|
+ /* 保存非法入侵的信息 */
|
|
|
+ std::shared_ptr<ListIllegalInvasionInfo> pListIllInfo = std::make_shared<ListIllegalInvasionInfo>();
|
|
|
|
|
|
+ std::string strFaceActionID; /* 人脸识别的Action */
|
|
|
+ std::string strCountActionID; /* 人员计数的Action */
|
|
|
+
|
|
|
+ /* 封装lambda表达式 */
|
|
|
+ std::function<bool(const std::vector<PersonInfo>&)> funcIsAlarm = [](const std::vector<PersonInfo>& vecPersion) {
|
|
|
+ for(const auto& it : vecPersion)
|
|
|
+ {
|
|
|
+ if(it.PersonID == "-1")
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+
|
|
|
while (m_threadRunning)
|
|
|
{
|
|
|
/* 更新线程信息 */
|
|
@@ -950,40 +1007,178 @@ void SPAServer::threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo)
|
|
|
pListAlarmInfo->push_back(alarmInfo);
|
|
|
}
|
|
|
}
|
|
|
+ /* 更新算法ActionID */
|
|
|
+ {
|
|
|
+ g_actionList.mutexRW.lockForRead();
|
|
|
+ strFaceActionID = g_actionList.ActFace;
|
|
|
+ strCountActionID = g_actionList.ActPersonNumber;
|
|
|
+ g_actionList.mutexRW.unlock();
|
|
|
+ }
|
|
|
|
|
|
- /* 处理数据,将报警信息的人脸信息取出来,放入到人脸信息列表中 */
|
|
|
- for(auto& alarmInfo : *pListAlarmInfo)
|
|
|
+ /* 找出房间的个数,按照房间进行判断 */
|
|
|
+ ListRoomIll listRoomIll;
|
|
|
+ for(auto& it : pRFAInfo->listRoomCamActInfo)
|
|
|
{
|
|
|
- /* 添加到人脸列表中,会自动去重,自动创建对应的频道和房间信息 */
|
|
|
- pListRoomFaceInfo->addRoomFaceInfo(alarmInfo);
|
|
|
+ listRoomIll.addRoom(it.RoomID, it.RoomType);
|
|
|
}
|
|
|
- /* 计算人脸个数,并判断是否需要写入数据库 */
|
|
|
- QDateTime now = QDateTime::currentDateTime();
|
|
|
- for(auto it = pListRoomFaceInfo->listRoomFaceInfo.begin(); it != pListRoomFaceInfo->listRoomFaceInfo.end(); )
|
|
|
+
|
|
|
+ /* 根据房间解析人脸识别的非法入侵,这个有了就不用判断后面的人员计数不相等了 */
|
|
|
+ for(auto& room : listRoomIll.getData())
|
|
|
{
|
|
|
- if(it->MaxNum < it->listPersonInfo.size())
|
|
|
+ for(const auto& it : *pListAlarmInfo)
|
|
|
{
|
|
|
- it->MaxNum = it->listPersonInfo.size();
|
|
|
+ /* 人俩识别算法 */
|
|
|
+ if(it.ActionID == strFaceActionID)
|
|
|
+ {
|
|
|
+ if(it.vecPersonInfo.size() > room.numMaxFace)
|
|
|
+ {
|
|
|
+ room.numMaxFace = it.vecPersonInfo.size();
|
|
|
+ room.strBoxList = it.BboxList;
|
|
|
+ room.vecPersonInfo = it.vecPersonInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* 判断有没有非法入侵人员 */
|
|
|
+ if(funcIsAlarm(it.vecPersonInfo))
|
|
|
+ {
|
|
|
+ room.isAlarm = true;
|
|
|
+ room.strMessage = "人员非法入侵(未知人员)";
|
|
|
+ if( !it.ImageInfo.empty() )
|
|
|
+ {
|
|
|
+ room.strImage = it.ImageInfo;
|
|
|
+ }
|
|
|
+ room.CameraID = it.DeviceID;
|
|
|
+ }
|
|
|
}
|
|
|
- if(it->MinNum > it->listPersonInfo.size())
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 判断人脸识别到的数目和人员计数算法识别到的人数是否相等,如果上面报警了,这里就不用检测了 */
|
|
|
+ for(auto& room : listRoomIll.getData())
|
|
|
+ {
|
|
|
+ if(room.isAlarm)
|
|
|
{
|
|
|
- it->MinNum = it->listPersonInfo.size();
|
|
|
+ continue;
|
|
|
}
|
|
|
- /* 判断是否需要写入数据库,超过设置的时间就写入,默认是600秒 */
|
|
|
- if(now.toSecsSinceEpoch() - it->StartTime.toSecsSinceEpoch() > g_config.AppUpdateOnWorkTimeInterval)
|
|
|
+ /* 这个房间的人脸算法没有识别到非法入侵 */
|
|
|
+ for(const auto& it : *pListAlarmInfo)
|
|
|
{
|
|
|
- /* 写入数据库 */
|
|
|
- if(toEQMDataBase->insertOnWorkInfo(*it))
|
|
|
+ if(it.ActionID == strCountActionID)
|
|
|
{
|
|
|
- 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);
|
|
|
+ if(it.vecPersonInfo.size() > room.numMaxPerson)
|
|
|
+ {
|
|
|
+ room.numMaxPerson = it.vecPersonInfo.size();
|
|
|
+ room.strBoxList = it.BboxList;
|
|
|
+ if(!it.ImageInfo.empty())
|
|
|
+ {
|
|
|
+ room.strImage = it.ImageInfo;
|
|
|
+ }
|
|
|
+ room.CameraID = it.DeviceID;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* 判断人数是否一致 */
|
|
|
+ if(room.numMaxFace != room.numMaxPerson)
|
|
|
+ {
|
|
|
+ room.strMessage = fmt::format("非法入侵(人员计数 {} 和人脸数 {} 不一致)", room.numMaxPerson, room.numMaxFace);
|
|
|
+ room.isAlarm = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 将非法入侵的信息存储到数组缓存中,等待报警结束后判断是否需要写入EQM数据库 */
|
|
|
+ for(auto& room : listRoomIll.getData())
|
|
|
+ {
|
|
|
+ if(room.isAlarm)
|
|
|
+ {
|
|
|
+ /* 正在报警,检查是否有 */
|
|
|
+ if(pListIllInfo->findIllInfo(room.RoomID, room.RoomType) == nullptr)
|
|
|
+ {
|
|
|
+ IllegalInvasionInfo info;
|
|
|
+ info.ChannelID = pRFAInfo->ChannelID;
|
|
|
+ info.CameraID = room.CameraID;
|
|
|
+ info.RoomID = room.RoomID;
|
|
|
+ info.RoomType = room.RoomType;
|
|
|
+ info.strActionDec = room.strMessage;
|
|
|
+ info.strImageInfo = room.strImage;
|
|
|
+ info.FirstTime = QDateTime::currentDateTime();;
|
|
|
+ pListIllInfo->addIllInfo(info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */
|
|
|
+ QDateTime currTime = QDateTime::currentDateTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ setThreadState(pRFAInfo, RunTimeState::RUN_STATE_STOP);
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "关闭 {} 线程,ChannelID:{}", pRFAInfo->strFunctionName, pRFAInfo->ChannelID);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 区域人员检测,检测这个区域内的人数,不能少于多少人,不能多余多少人
|
|
|
+ * 1、报警判断条件:直播间报警:当前频率所有直播间摄像头的区域人员检测算法输出结果均大于或小于设定人
|
|
|
+ 数值时,记为报警行为,直接展示报警结果
|
|
|
+ 2、录播间报警:当前频率所有录播间摄像头的区域人员检测算法输出结果均大于或小于设定人数值时,记为报
|
|
|
+ 警行为,直接展示报警结果
|
|
|
+ 3、直播间+录播间报警:当前频率直播间人数+录播间人数大于或小于设定人数值时,记为报警行为,直接展示
|
|
|
+ 报警结果
|
|
|
+ *
|
|
|
+ * @param RAInfo 传入的房间ID和算法ID
|
|
|
+ */
|
|
|
+void SPAServer::threadActRegionalPersonnelDetection(FuncActionInfo* RFAInfo)
|
|
|
+{
|
|
|
+ SPDLOG_LOGGER_INFO(m_logger, "开启 {} 线程,ChannelID:{} ,", RFAInfo->strFunctionName, RFAInfo->ChannelID);
|
|
|
+ /* 创建读取Redis的实例 */
|
|
|
+ std::shared_ptr<FromRedis> fromRedis = std::make_shared<FromRedis>();
|
|
|
+ /* 创建写入数据库实例 */
|
|
|
+ std::shared_ptr<ToEQMDataBase> toEQMDataBase = std::make_shared<ToEQMDataBase>();
|
|
|
+ /* 局部变量 */
|
|
|
+ std::shared_ptr<FuncActionInfo> pRFAInfo = std::make_shared<FuncActionInfo>();
|
|
|
+ *pRFAInfo = *RFAInfo;
|
|
|
+ /* 保存每个摄像机的报警信息 */
|
|
|
+ std::shared_ptr<std::list<AlarmInfo>> pListAlarmInfo = std::make_shared<std::list<AlarmInfo>>();
|
|
|
+
|
|
|
+ while (m_threadRunning)
|
|
|
+ {
|
|
|
+ /* 更新线程信息 */
|
|
|
+ updateFuncInfo(pRFAInfo);
|
|
|
+ if(pRFAInfo->appFunction == AppFunction::APP_NONE)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 读取Redis数据 */
|
|
|
+ pListAlarmInfo->clear();
|
|
|
+ for(const auto& RoomInfo : pRFAInfo->listRoomCamActInfo)
|
|
|
+ {
|
|
|
+ for(const auto& it : RoomInfo.mapCameraAction)
|
|
|
+ {
|
|
|
+ std::string strKey = std::to_string(it.first) + ":" + it.second;
|
|
|
+ std::string strRetValue;
|
|
|
+ if(!fromRedis->getRedisString(strKey, strRetValue))
|
|
|
+ {
|
|
|
+ SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
|
|
|
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
continue;
|
|
|
}
|
|
|
+ /* 解析数据 */
|
|
|
+ AlarmInfo alarmInfo;
|
|
|
+ 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);
|
|
|
}
|
|
|
- ++it;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
|
|
|
}
|
|
|
setThreadState(pRFAInfo, RunTimeState::RUN_STATE_STOP);
|
|
@@ -1128,57 +1323,6 @@ void SPAServer::threadActNormal(FuncActionInfo* info)
|
|
|
SPDLOG_LOGGER_INFO(m_logger, "{} 线程退出,Channel:{}",pFuncAct->strFunctionName, pFuncAct->ChannelID);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @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);
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
|
|
|
/* 将该算法对应的摄像机放入摄像机列表 */
|
|
@@ -1219,7 +1363,7 @@ bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCame
|
|
|
bool SPAServer::updateFuncInfo(std::shared_ptr<FuncActionInfo> pInfo)
|
|
|
{
|
|
|
pInfo->clearActionList();
|
|
|
- std::lock_guard<std::mutex> look(m_mutexRunAI);
|
|
|
+ std::lock_guard<std::mutex> look(m_mutexRunFAI);
|
|
|
auto fa = m_runListFuncActInfo.findAppFunction(*pInfo);
|
|
|
if(fa == nullptr)
|
|
|
{
|
|
@@ -1233,7 +1377,7 @@ bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCame
|
|
|
/* 设置线程状态 */
|
|
|
void SPAServer::setThreadState(std::shared_ptr<FuncActionInfo> pInfo, RunTimeState state)
|
|
|
{
|
|
|
- std::lock_guard<std::mutex> look(m_mutexRunAI);
|
|
|
+ std::lock_guard<std::mutex> look(m_mutexRunFAI);
|
|
|
auto p = m_runListFuncActInfo.findAppFunction(*pInfo);
|
|
|
if(p != nullptr)
|
|
|
{
|
|
@@ -1241,20 +1385,6 @@ void SPAServer::setThreadState(std::shared_ptr<FuncActionInfo> pInfo, RunTimeSta
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/* 设置线程状态 */
|
|
|
-void SPAServer::setThreadState(std::shared_ptr<RoomActionInfo> pInfo, RunTimeState state)
|
|
|
-{
|
|
|
- std::lock_guard<std::mutex> look(m_mutexRunRAI);
|
|
|
- for(auto& it : m_runListRoomActionInfo.getData())
|
|
|
- {
|
|
|
- if(it->isEqualBaseInfo(*pInfo))
|
|
|
- {
|
|
|
- it->RunState = state;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
|
|
|
/* 计算与当前时间的时间差,返回秒 */
|