FuncIllegalInvasion.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #include "FuncIllegalInvasion.h"
  2. #include "GlobalVariable.h"
  3. #include "GlobalConfig.h"
  4. #include "FromRedis.h"
  5. #include "FromWebAPI.h"
  6. #include "UniversalFunc.h"
  7. RoomIllegalInvasionInfo::RoomIllegalInvasionInfo(const RoomIllegalInvasionInfo& o)
  8. {
  9. isAlarm = o.isAlarm;
  10. RoomID = o.RoomID;
  11. RoomType = o.RoomType;
  12. numMaxFace = o.numMaxFace;
  13. numMaxPerson = o.numMaxPerson;
  14. listBBox = o.listBBox;
  15. strMessage = o.strMessage;
  16. strImage = o.strImage;
  17. CameraID = o.CameraID;
  18. }
  19. RoomIllegalInvasionInfo& RoomIllegalInvasionInfo::operator=(const RoomIllegalInvasionInfo& o)
  20. {
  21. if(this != &o) {
  22. isAlarm = o.isAlarm;
  23. RoomID = o.RoomID;
  24. RoomType = o.RoomType;
  25. numMaxFace = o.numMaxFace;
  26. numMaxPerson = o.numMaxPerson;
  27. listBBox = o.listBBox;
  28. strMessage = o.strMessage;
  29. strImage = o.strImage;
  30. CameraID = o.CameraID;
  31. }
  32. return *this;
  33. }
  34. /* 添加房间 */
  35. void ListRoomIll::addRoom(int RoomID, Enum_RoomType RoomType)
  36. {
  37. auto p = findRoom(RoomID, RoomType);
  38. if(p == nullptr)
  39. {
  40. RoomIllegalInvasionInfo ill;
  41. ill.RoomID = RoomID;
  42. ill.RoomType = RoomType;
  43. listRoomIll.push_back(ill);
  44. }
  45. }
  46. /* 查找是否有相同的房间 */
  47. RoomIllegalInvasionInfo* ListRoomIll::findRoom(int RoomID, Enum_RoomType RoomType)
  48. {
  49. for(auto& it : listRoomIll)
  50. {
  51. if(it.RoomID == RoomID && it.RoomType == RoomType)
  52. {
  53. return ⁢
  54. }
  55. }
  56. return nullptr;
  57. }
  58. IllegalInvasionInfo::IllegalInvasionInfo(const IllegalInvasionInfo& other)
  59. {
  60. isInsertEQM = other.isInsertEQM;
  61. PKID = other.PKID;
  62. CameraID = other.CameraID;
  63. RoomID = other.RoomID;
  64. ChannelID = other.ChannelID;
  65. RoomType = other.RoomType;
  66. FirstTime = other.FirstTime;
  67. strActionDec = other.strActionDec;
  68. strImageInfo = other.strImageInfo;
  69. }
  70. IllegalInvasionInfo& IllegalInvasionInfo::operator=(const IllegalInvasionInfo& other)
  71. {
  72. if(this != &other)
  73. {
  74. isInsertEQM = other.isInsertEQM;
  75. PKID = other.PKID;
  76. CameraID = other.CameraID;
  77. RoomID = other.RoomID;
  78. ChannelID = other.ChannelID;
  79. RoomType = other.RoomType;
  80. FirstTime = other.FirstTime;
  81. strActionDec = other.strActionDec;
  82. strImageInfo = other.strImageInfo;
  83. }
  84. return *this;
  85. }
  86. /* 添加信息 */
  87. void ListIllegalInvasionInfo::addIllInfo(IllegalInvasionInfo& info)
  88. {
  89. if(findIllInfo(info) == nullptr)
  90. {
  91. listIll.push_back(info);
  92. }
  93. }
  94. /* 查找相同的信息 */
  95. IllegalInvasionInfo* ListIllegalInvasionInfo::findIllInfo(IllegalInvasionInfo& info)
  96. {
  97. for(auto& it : listIll)
  98. {
  99. if(it.RoomID == info.RoomID && it.RoomType == info.RoomType)
  100. {
  101. return ⁢
  102. }
  103. }
  104. return nullptr;
  105. }
  106. IllegalInvasionInfo* ListIllegalInvasionInfo::findIllInfo(int roomID, Enum_RoomType roomType)
  107. {
  108. for(auto& it : listIll)
  109. {
  110. if(it.RoomID == roomID && it.RoomType == roomType)
  111. {
  112. return ⁢
  113. }
  114. }
  115. return nullptr;
  116. }
  117. /* 删除报警信息 */
  118. void ListIllegalInvasionInfo::deleteIllInfo(IllegalInvasionInfo& info)
  119. {
  120. for(auto it = listIll.begin(); it != listIll.end();)
  121. {
  122. if(it->RoomID == info.RoomID && it->RoomType == info.RoomType)
  123. {
  124. it = listIll.erase(it);
  125. }else {
  126. ++it;
  127. }
  128. }
  129. }
  130. void ListIllegalInvasionInfo::deleteIllInfo(int roomID, Enum_RoomType roomType)
  131. {
  132. for(auto it = listIll.begin(); it != listIll.end();)
  133. {
  134. if(it->RoomID == roomID && it->RoomType == roomType)
  135. {
  136. it = listIll.erase(it);
  137. }else {
  138. ++it;
  139. }
  140. }
  141. }
  142. /* ===================================================================================
  143. * 功能类:FuncIllegalInvasion
  144. * =================================================================================== */
  145. FuncIllegalInvasion::FuncIllegalInvasion()
  146. {
  147. m_logger = spdlog::get("SPAServer");
  148. if(m_logger == nullptr)
  149. {
  150. SPDLOG_ERROR("SPAServer logger is nullptr");
  151. return;
  152. }
  153. m_pListIllInfo = std::make_shared<ListIllegalInvasionInfo>();
  154. }
  155. FuncIllegalInvasion::~FuncIllegalInvasion()
  156. {
  157. if(m_pListIllInfo != nullptr)
  158. {
  159. m_pListIllInfo.reset();
  160. m_pListIllInfo = nullptr;
  161. }
  162. }
  163. /* 是否报警 */
  164. bool FuncIllegalInvasion::isAlarm(const std::list<PersonInfo>& listPersion)
  165. {
  166. for(const auto& it : listPersion)
  167. {
  168. if(it.PersonID == "-1")
  169. {
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175. /* 线程功能 */
  176. void FuncIllegalInvasion::task()
  177. {
  178. std::string strFaceActionID; /* 人脸识别的Action */
  179. std::string strCountActionID; /* 人员计数的Action */
  180. while (GThreadInfo.getRunning())
  181. {
  182. std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS()));
  183. /* 更新线程信息 */
  184. GThreadInfo.updateFuncInfo(m_funcThreadInfo);
  185. if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
  186. {
  187. break;
  188. }
  189. /* 判断是否在检测时间段内 */
  190. if(!isInDetectTime(m_periodInfo))
  191. {
  192. continue;
  193. }
  194. /* 更新算法ActionID */
  195. {
  196. GVariable.mutexRW.lockForRead();
  197. strFaceActionID = GVariable.ActFaceIdentify();
  198. strCountActionID = GVariable.ActPersonCount();
  199. GVariable.mutexRW.unlock();
  200. }
  201. /* -----------------------------------------------------------------------
  202. * 读取Redis数据
  203. * ----------------------------------------------------------------------- */
  204. readRedisData(m_listSrcAlarm);
  205. /* 找出房间的个数,按照房间进行判断 */
  206. ListRoomIll listRoomIll;
  207. for(auto& it : m_funcThreadInfo.listRoomCamActInfo)
  208. {
  209. listRoomIll.addRoom(it.RoomID, it.RoomType);
  210. }
  211. /* -----------------------------------------------------------------------
  212. * 处理读取到的数据
  213. * ----------------------------------------------------------------------- */
  214. /* 根据房间解析人脸识别的非法入侵,检测到了非法人脸,就可以直接报警了 */
  215. for(auto& room : listRoomIll.getData())
  216. {
  217. /* 对获取到的数据挨个判断 */
  218. for(const auto& alarm : m_listSrcAlarm.listAlarmInfo)
  219. {
  220. if(room.RoomID != alarm->RoomID)
  221. {
  222. continue;
  223. }
  224. /* 统计这个房间内《人脸算法》检测到的最大人员数 */
  225. if(alarm->ActionID == strFaceActionID)
  226. {
  227. if(alarm->listPersonInfo.size() > room.numMaxFace)
  228. {
  229. room.numMaxFace = alarm->listPersonInfo.size();
  230. room.listBBox = alarm->listBbox;
  231. room.listPersonInfo = alarm->listPersonInfo;
  232. }
  233. }
  234. /* 判断有没有非法入侵人员 */
  235. if(isAlarm(alarm->listPersonInfo))
  236. {
  237. room.isAlarm = true;
  238. room.strMessage = "人员非法入侵(未知人员)";
  239. if( !alarm->ImageInfo.empty() )
  240. {
  241. room.strImage = alarm->ImageInfo;
  242. }
  243. room.CameraID = alarm->DeviceID;
  244. }
  245. }
  246. }
  247. /* 判断《人脸算法》识别到的数目和《人员计数算法》识别到的人数是否相等,如果上面报警了,这里就不用检测了 */
  248. for(auto& room : listRoomIll.getData())
  249. {
  250. if(room.isAlarm)
  251. {
  252. /* 上面的人脸识别算法已经识别到非法入侵了 */
  253. continue;
  254. }
  255. /* 这个房间的人脸算法没有识别到非法入侵 */
  256. for(const auto& alarm : m_listSrcAlarm.listAlarmInfo)
  257. {
  258. if(room.RoomID != alarm->RoomID)
  259. {
  260. continue;
  261. }
  262. /* 人员计数 */
  263. if(alarm->ActionID == strCountActionID)
  264. {
  265. /* 统计这个房间内《人员计数算法》检测到的最大人员数 */
  266. if(alarm->listBbox.size() > room.numMaxPerson)
  267. {
  268. room.numMaxPerson = alarm->listBbox.size();
  269. room.listBBox = alarm->listBbox;
  270. if(!alarm->ImageInfo.empty())
  271. {
  272. room.strImage = alarm->ImageInfo;
  273. }
  274. room.CameraID = alarm->DeviceID;
  275. }
  276. }
  277. }
  278. /* 判断人数是否一致 */
  279. if(room.numMaxFace != room.numMaxPerson)
  280. {
  281. room.strMessage = fmt::format("非法入侵(人员计数 {} 和人脸数 {} 不一致)", room.numMaxPerson, room.numMaxFace);
  282. room.isAlarm = true;
  283. }
  284. }
  285. /* 将非法入侵的信息存储到数组缓存中,等待报警结束后判断是否需要写入EQM数据库 */
  286. for(auto& room : listRoomIll.getData())
  287. {
  288. if(room.isAlarm)
  289. {
  290. auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType);
  291. /* 正在报警,检查缓存中是否有这个报警信息 */
  292. if(pIll == nullptr)
  293. {
  294. IllegalInvasionInfo info;
  295. info.ChannelID = m_funcThreadInfo.ChannelID;
  296. info.CameraID = room.CameraID;
  297. info.RoomID = room.RoomID;
  298. info.RoomType = room.RoomType;
  299. info.strActionDec = room.strMessage;
  300. info.strImageInfo = room.strImage;
  301. info.FirstTime = QDateTime::currentDateTime();;
  302. m_pListIllInfo->addIllInfo(info);
  303. }
  304. }
  305. else
  306. {
  307. auto pIll = m_pListIllInfo->findIllInfo(room.RoomID, room.RoomType);
  308. if(pIll == nullptr)
  309. {
  310. /* 没有报警,继续下一个房间 */
  311. continue;
  312. }
  313. /* 没有报警,检查是否是报警结束了,是否符合写入数据库的条件 */
  314. QDateTime currTime = QDateTime::currentDateTime();
  315. int secs = currTime.toSecsSinceEpoch() - pIll->FirstTime.toSecsSinceEpoch();
  316. if(secs >= GVariable.AppBadMan_Time)
  317. {
  318. if(!pIll->strImageInfo.empty())
  319. {
  320. /* 超过非法入侵的时间,写入数据库 */
  321. AlarmInfo ai;
  322. ai.ChannelID = m_funcThreadInfo.ChannelID;
  323. ai.RoomID = pIll->RoomID;
  324. ai.ActionID = GVariable.ActPersonCount();
  325. ai.ActionDes = pIll->strActionDec;
  326. ai.ImageInfo = pIll->strImageInfo;
  327. ai.StartTime = pIll->FirstTime;
  328. ai.EndTime = currTime;
  329. ai.EventTime = pIll->FirstTime;
  330. ai.listPersonInfo = room.listPersonInfo;
  331. ai.listBbox = room.listBBox;
  332. bool insertRet = m_fromWebAPI->insertAlarmInfo(ai);
  333. if(insertRet)
  334. {
  335. std::string actionName = GVariable.getActionName(ai.ActionID);
  336. SPDLOG_LOGGER_INFO(m_logger, "☆ 新增报警信息,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸,{}",
  337. pIll->ChannelID, pIll->RoomID, pIll->CameraID, actionName, ai.ActionDes, ai.listBbox.size(), ai.FaceIDList.size(), ai.ImageInfo);
  338. }
  339. }
  340. else {
  341. SPDLOG_LOGGER_WARN(m_logger, "× 取消新增报警信息,因为没有图片,频道[{}],房间[{}],摄像头[{}],{},{},有{}个区域,有{}个人脸",
  342. pIll->ChannelID, pIll->RoomID, pIll->CameraID, pIll->strActionDec, pIll->strImageInfo, room.listBBox.size(), room.listPersonInfo.size());
  343. }
  344. /* 删除这个非法入侵信息 */
  345. m_pListIllInfo->deleteIllInfo(*pIll);
  346. }
  347. }
  348. }
  349. }
  350. m_listSrcAlarm.clearAlarmInfo();
  351. }
  352. /* 读取Redis数据 */
  353. // void FuncIllegalInvasion::readRedisData()
  354. // {
  355. // m_listSrcAlarm.clearAlarmInfo();
  356. // /* 读取Redis数据 */
  357. // for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  358. // {
  359. // for(const auto& cam : roomInfo.mapCameraAction)
  360. // {
  361. // for(const auto act : cam.second)
  362. // {
  363. // /* 读取Redis数据 */
  364. // std::string strKey = std::to_string(cam.first) + ":" + act;
  365. // std::string strRetValue;
  366. // // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
  367. // if(!m_fromRedis->getRedisString(strKey, strRetValue))
  368. // {
  369. // // SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
  370. // std::this_thread::sleep_for(std::chrono::milliseconds(10));
  371. // continue;
  372. // }
  373. // /* 解析数据,先设置基础数据 */
  374. // AlarmInfo newAlarmInfo;
  375. // newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  376. // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  377. // newAlarmInfo.RoomID = roomInfo.RoomID;
  378. // newAlarmInfo.DeviceID = cam.first;
  379. // newAlarmInfo.ActionID = act;
  380. // parseRedisBaseData(strRetValue, newAlarmInfo);
  381. // parseRedisBBoxesData(strRetValue, newAlarmInfo);
  382. // /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  383. // if(!isEventTimeVaild(newAlarmInfo.EventTime))
  384. // {
  385. // /* 事件时间超过600秒,可能是超脑挂了 */
  386. // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  387. // std::this_thread::sleep_for(std::chrono::milliseconds(100));
  388. // continue;
  389. // }
  390. // m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
  391. // SPDLOG_LOGGER_DEBUG(m_logger, "报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
  392. // strKey, roomInfo.RoomID, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
  393. // newAlarmInfo.listBbox.size(), newAlarmInfo.listPersonInfo.size());
  394. // }
  395. // }
  396. // }
  397. // }