FuncRegionalPerson.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. #include "FuncRegionalPerson.h"
  2. #include "FromWebAPI.h"
  3. #include "FromRedis.h"
  4. #include "GlobalConfig.h"
  5. #include "GlobalVariable.h"
  6. #include "UniversalFunc.h"
  7. #include "bundled/core.h"
  8. #include "spdlog.h"
  9. #include <string>
  10. PersonCountRuleInfo::PersonCountRuleInfo()
  11. {
  12. isUpdate = false;
  13. noRule = false;
  14. ChannelID = -1;
  15. // week = 0;
  16. // RuleType = Enum_PeriodType::PERIOD_ALL;
  17. LiveMinEnable = false;
  18. LiveMaxEnable = false;
  19. DicMinEnable = false;
  20. DicMaxEnable = false;
  21. LiveDicMinEnable = false;
  22. LiveDicMaxEnable = false;
  23. LiveMin = 0;
  24. LiveMax = 0;
  25. DicMin = 0;
  26. DicMax = 0;
  27. LiveDicMin = 0;
  28. LiveDicMax = 0;
  29. RuleName = "";
  30. }
  31. PersonCountRuleInfo& PersonCountRuleInfo::operator=(PersonCountRuleInfo& other)
  32. {
  33. if(this != &other)
  34. {
  35. ChannelID = other.ChannelID;
  36. // week = other.week;
  37. // RuleType = other.RuleType;
  38. // PeriodName = other.PeriodName;
  39. // StartTime = other.StartTime;
  40. // EndTime = other.EndTime;
  41. LiveMinEnable = other.LiveMinEnable;
  42. LiveMaxEnable = other.LiveMaxEnable;
  43. DicMinEnable = other.DicMinEnable;
  44. DicMaxEnable = other.DicMaxEnable;
  45. LiveDicMinEnable = other.LiveDicMinEnable;
  46. LiveDicMaxEnable = other.LiveDicMaxEnable;
  47. LiveMin = other.LiveMin;
  48. LiveMax = other.LiveMax;
  49. DicMin = other.DicMin;
  50. DicMax = other.DicMax;
  51. LiveDicMin = other.LiveDicMin;
  52. LiveDicMax = other.LiveDicMax;
  53. RuleName = other.RuleName;
  54. }
  55. return *this;
  56. }
  57. /* 对比规则需不需要更新 */
  58. bool PersonCountRuleInfo::equals(const PersonCountRuleInfo& other) const
  59. {
  60. if (ChannelID != other.ChannelID) {
  61. return false;
  62. }
  63. if (LiveMinEnable != other.LiveMinEnable || LiveMaxEnable != other.LiveMaxEnable ||
  64. DicMinEnable != other.DicMinEnable || DicMaxEnable != other.DicMaxEnable ||
  65. LiveDicMinEnable != other.LiveDicMinEnable || LiveDicMaxEnable != other.LiveDicMaxEnable) {
  66. return false;
  67. }
  68. if (LiveMin != other.LiveMin || LiveMax != other.LiveMax ||
  69. DicMin != other.DicMin || DicMax != other.DicMax ||
  70. LiveDicMin != other.LiveDicMin || LiveDicMax != other.LiveDicMax) {
  71. return false;
  72. }
  73. return true;
  74. }
  75. RoomPeopleInfo::RoomPeopleInfo()
  76. {
  77. RoomID = -1;
  78. RoomType = Enum_RoomType::ROOM_NONE;
  79. RoomName = "";
  80. MaxNum = 0;
  81. imagePath = "";
  82. }
  83. RoomPeopleInfo::RoomPeopleInfo(const RoomPeopleInfo& other)
  84. {
  85. RoomID = other.RoomID;
  86. RoomType = other.RoomType;
  87. RoomName = other.RoomName;
  88. MaxNum = other.MaxNum;
  89. imagePath = other.imagePath;
  90. }
  91. RoomPeopleInfo& RoomPeopleInfo::operator=(const RoomPeopleInfo& other)
  92. {
  93. if (this != &other) {
  94. RoomID = other.RoomID;
  95. RoomType = other.RoomType;
  96. RoomName = other.RoomName;
  97. MaxNum = other.MaxNum;
  98. imagePath = other.imagePath;
  99. }
  100. return *this;
  101. }
  102. AlarmBuffer::AlarmBuffer()
  103. {
  104. // isMax = false;
  105. // isInsertDB = false;
  106. ChannelID = -1;
  107. RoomID = -1;
  108. RoomType = Enum_RoomType::ROOM_NONE;
  109. PeopleNum = 0;
  110. PKID = 0;
  111. AlarmTime = QDateTime();
  112. imagePath = "";
  113. actionDecs = "";
  114. }
  115. AlarmBuffer::AlarmBuffer(const AlarmBuffer& other)
  116. {
  117. // isMax = other.isMax;
  118. // isInsertDB = other.isInsertDB;
  119. ChannelID = other.ChannelID;
  120. RoomID = other.RoomID;
  121. RoomType = other.RoomType;
  122. PeopleNum = other.PeopleNum;
  123. PKID = other.PKID;
  124. AlarmTime = other.AlarmTime;
  125. imagePath = other.imagePath;
  126. actionDecs = other.actionDecs;
  127. }
  128. AlarmBuffer& AlarmBuffer::operator=(const AlarmBuffer& other)
  129. {
  130. if (this != &other) {
  131. // isMax = other.isMax;
  132. // isInsertDB = other.isInsertDB;
  133. ChannelID = other.ChannelID;
  134. RoomID = other.RoomID;
  135. RoomType = other.RoomType;
  136. PeopleNum = other.PeopleNum;
  137. PKID = other.PKID;
  138. AlarmTime = other.AlarmTime;
  139. imagePath = other.imagePath;
  140. actionDecs = other.actionDecs;
  141. }
  142. return *this;
  143. }
  144. FuncRegionalPersonCount::FuncRegionalPersonCount()
  145. {
  146. m_logger = spdlog::get("SPAServer");
  147. if(m_logger == nullptr)
  148. {
  149. SPDLOG_ERROR("SPAServer logger is nullptr");
  150. return;
  151. }
  152. }
  153. FuncRegionalPersonCount::~FuncRegionalPersonCount()
  154. {
  155. m_listSrcAlarm.clearAlarmInfo();
  156. }
  157. void FuncRegionalPersonCount::task()
  158. {
  159. /* 初始化WebAPI和Redis */
  160. if(!initDataInterface())
  161. {
  162. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据接口失败", m_baseLog);
  163. return;
  164. }
  165. while (m_bRunning)
  166. {
  167. std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
  168. /* 更新线程信息,并判断是否需要退出 */
  169. GThreadInfo.updateFuncInfo(m_funcThreadInfo);
  170. if( (m_funcThreadInfo.appFunction == AppFunction::APP_NONE) ||
  171. (m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP) )
  172. {
  173. break;
  174. }
  175. /* 判断是否在检测时间段内 */
  176. if(!isInDetectTime(m_periodInfo))
  177. {
  178. /* 判断报警是否已经结束,没有结束就结束报警 */
  179. autoEndAlarm();
  180. continue;
  181. }
  182. /* 更新报警规则 */
  183. if(!getPersonCountRuleInfo())
  184. {
  185. /* 判断是不是无报警规则了 */
  186. if(m_personCountRule.noRule)
  187. {
  188. SPDLOG_LOGGER_ERROR(m_logger, "{} 没有报警规则,退出功能检测线程", m_baseLog);
  189. /* 判断报警是否已经结束,没有结束就结束报警 */
  190. autoEndAlarm();
  191. return;
  192. }
  193. continue;
  194. }
  195. if(m_personCountRule.isUpdate)
  196. {
  197. /* 报警规则更新了,结束报警 */
  198. autoEndAlarm();
  199. }
  200. /* 更新房间列表 */
  201. updateRoomList();
  202. if(m_listRoomCamAct.empty())
  203. {
  204. SPDLOG_LOGGER_ERROR(m_logger, "★ 频道[{}][{}],{},房间列表为空",
  205. m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName,
  206. getAppFunctionName(m_funcThreadInfo.appFunction));
  207. /* 判断报警是否已经结束,没有结束就结束报警 */
  208. autoEndAlarm();
  209. continue;
  210. }
  211. /* -----------------------------------------------------------------------
  212. * 读取Redis数据
  213. * ----------------------------------------------------------------------- */
  214. readRedisData();
  215. // SPDLOG_LOGGER_DEBUG(m_logger, "房间数目: {}, 报警条目数目: {}", m_listRoomCamAct.size(), m_pListAlarm->listAlarmInfo.size());
  216. // SPDLOG_LOGGER_DEBUG(m_logger, "报警人数: {}", m_pListAlarm->listAlarmInfo.front()->listBbox.size());
  217. /************ 挨个房间检测人数,取出每个房间内人数的最大值 ************/
  218. for(const auto& RoomInfo : m_listRoomCamAct)
  219. {
  220. /* 取出房间内的最大值 */
  221. RoomPeopleInfo peopleInfo;
  222. peopleInfo.RoomID = RoomInfo.RoomID;
  223. peopleInfo.RoomType = RoomInfo.RoomType;
  224. peopleInfo.RoomName = RoomInfo.strRoomName;
  225. /* 获取该房间内最大人数 */
  226. getRoomMaxNum(RoomInfo.RoomID, peopleInfo.MaxNum, peopleInfo.imagePath);
  227. m_mapRoomPeople.insert(std::make_pair(RoomInfo.RoomID, peopleInfo));
  228. }
  229. /************ 单独判断每个房间内人数的最大值和最小值 ************/
  230. for(const auto& it : m_mapRoomPeople)
  231. {
  232. // SPDLOG_LOGGER_DEBUG(m_logger, "房间:{} 人数: {}", it.second.RoomName, it.second.MaxNum);
  233. /* 处理房间内的人数最大值 */
  234. handleRoomMaxNum(it.second);
  235. /* 处理房间内人数最小值 */
  236. handleRoomMinNum(it.second);
  237. }
  238. /************ 检测频率直播间 + 导播间房间的人数 ************/
  239. int liveDicMaxNum = 0;
  240. std::string strImagePath = "";
  241. for(const auto& it : m_mapRoomPeople)
  242. {
  243. /* 直播间 + 导播间 */
  244. if(it.second.RoomType == Enum_RoomType::ROOM_LIVE || it.second.RoomType == Enum_RoomType::ROOM_DIC)
  245. {
  246. liveDicMaxNum += it.second.MaxNum;
  247. strImagePath = it.second.imagePath;
  248. }
  249. }
  250. RoomPeopleInfo liveDicMaxNumInfo;
  251. liveDicMaxNumInfo.RoomID = 0;
  252. liveDicMaxNumInfo.RoomType = Enum_RoomType::ROOM_LIVEDIC;
  253. liveDicMaxNumInfo.MaxNum = liveDicMaxNum;
  254. liveDicMaxNumInfo.imagePath = strImagePath;
  255. liveDicMaxNumInfo.RoomName = "直播间+导播间";
  256. handleRoomMaxNum(liveDicMaxNumInfo);
  257. handleRoomMinNum(liveDicMaxNumInfo);
  258. }
  259. }
  260. /* 读取Redis数据 */
  261. void FuncRegionalPersonCount::readRedisData()
  262. {
  263. m_listSrcAlarm.clearAlarmInfo();
  264. for(const auto& roomInfo : m_listRoomCamAct)
  265. {
  266. for(const auto& it : roomInfo.mapCameraAction)
  267. {
  268. for(const auto& act : it.second)
  269. {
  270. std::string strKey = std::to_string(it.first) + ":" + act;
  271. std::string strRetValue;
  272. if(!m_fromRedis->getRedisString(strKey, strRetValue))
  273. {
  274. SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey);
  275. continue;
  276. }
  277. /* 解析数据 */
  278. AlarmInfo newAlarmInfo;
  279. newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  280. newAlarmInfo.RoomID = roomInfo.RoomID;
  281. newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  282. newAlarmInfo.ActionID = act;
  283. parseRedisBaseData(strRetValue, newAlarmInfo);
  284. parseOtherDataPersonCount(strRetValue, newAlarmInfo);
  285. /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  286. if(!isEventTimeVaild(newAlarmInfo.EventTime))
  287. {
  288. SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
  289. m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
  290. continue;
  291. }
  292. m_listSrcAlarm.addAlarmInfo(newAlarmInfo);
  293. printRawDataInfo(roomInfo, strKey, newAlarmInfo);
  294. }
  295. }
  296. }
  297. }
  298. /* 获取该频率的人员计数规则 */
  299. bool FuncRegionalPersonCount::getPersonCountRuleInfo()
  300. {
  301. std::list<PersonCountRuleInfo> listRule;
  302. if(!m_fromWebAPI->getPersonCountRuleInfo(listRule))
  303. {
  304. SPDLOG_LOGGER_ERROR(m_logger, "获取《人员计数》报警规则失败");
  305. return false;
  306. }
  307. if(listRule.size() == 0)
  308. {
  309. SPDLOG_LOGGER_ERROR(m_logger, "★ 频道[{}][{}],{},未配置人员计数规则",
  310. m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName,
  311. getAppFunctionName(m_funcThreadInfo.appFunction));
  312. return false;
  313. }
  314. /* 获取这个频率的报警信息 */
  315. bool isFind = false;
  316. m_personCountRule.noRule = false;
  317. m_personCountRule.isUpdate = false;
  318. for(auto& it : listRule)
  319. {
  320. if(it.ChannelID == m_funcThreadInfo.ChannelID)
  321. {
  322. isFind = true;
  323. /* 判断规则是否有更新 */
  324. if(!it.equals(m_personCountRule))
  325. {
  326. /* 规则有更新 */
  327. m_personCountRule = it;
  328. m_personCountRule.isUpdate = true;
  329. SPDLOG_LOGGER_INFO(m_logger, "{} 报警规则有更新", m_baseLog);
  330. }
  331. break;
  332. }
  333. }
  334. if(!isFind)
  335. {
  336. SPDLOG_LOGGER_ERROR(m_logger, "频率:{}《人员计数》无报警规则", m_funcThreadInfo.ChannelID);
  337. m_personCountRule.noRule = true;
  338. return false;
  339. }
  340. return true;
  341. }
  342. /* 更新房间列表 */
  343. void FuncRegionalPersonCount::updateRoomList()
  344. {
  345. /* 清空房间列表 */
  346. m_listRoomCamAct.clear();
  347. for(const auto& it : m_funcThreadInfo.listRoomCamActInfo)
  348. {
  349. /* 只添加直播间和导播间 */
  350. if(it.RoomType == Enum_RoomType::ROOM_LIVE || it.RoomType == Enum_RoomType::ROOM_DIC)
  351. {
  352. m_listRoomCamAct.push_back(it);
  353. }
  354. }
  355. }
  356. /* 自动结束报警 */
  357. void FuncRegionalPersonCount::autoEndAlarm()
  358. {
  359. /* 判断报警是否已经结束,没有结束就结束报警 */
  360. if(m_mapAlarmBuffer.empty())
  361. {
  362. SPDLOG_LOGGER_DEBUG(m_logger, "{} 报警已经结束", m_baseLog);
  363. return;
  364. }
  365. /* 结束该频率人员计数的所有报警 */
  366. if(!m_fromWebAPI->endPersonCountAlarm(m_funcThreadInfo.ChannelID, m_funcThreadInfo.appFunction))
  367. {
  368. SPDLOG_LOGGER_ERROR(m_logger, "{} 结束报警失败", m_baseLog);
  369. return;
  370. }
  371. /* 清空报警列表 */
  372. clearAlarmBufferMap();
  373. SPDLOG_LOGGER_INFO(m_logger, "{} 结束报警,已清空报警缓存", m_baseLog);
  374. }
  375. /* 取出一个房间内的最大人数 */
  376. bool FuncRegionalPersonCount::getRoomMaxNum(int roomID, int& maxNum, std::string& strImagePath)
  377. {
  378. strImagePath.clear();
  379. for(auto it : m_listSrcAlarm.listAlarmInfo)
  380. {
  381. if(it->RoomID == roomID)
  382. {
  383. /* 取出最大人数 */
  384. int num = it->listBbox.size();
  385. if(num > maxNum)
  386. {
  387. maxNum = num;
  388. strImagePath = it->ImageInfo;
  389. }
  390. if(strImagePath.empty())
  391. {
  392. strImagePath = it->ImageInfo;
  393. }
  394. }
  395. }
  396. return true;
  397. }
  398. /* 处理房间内的人数最大值 */
  399. void FuncRegionalPersonCount::handleRoomMaxNum(const RoomPeopleInfo& peopleInfo)
  400. {
  401. std::string roomName = "";
  402. int maxNum = 0;
  403. /* 判断当前房间是否开启了最大人员检测功能 */
  404. if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVE)
  405. {
  406. if(!m_personCountRule.LiveMaxEnable)
  407. {
  408. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间最大人数检测功能未开启", m_baseLog);
  409. return;
  410. }
  411. /* 判断有没有名称 */
  412. if(peopleInfo.RoomName.empty())
  413. {
  414. roomName = "直播间";
  415. } else {
  416. roomName = peopleInfo.RoomName;
  417. }
  418. maxNum = m_personCountRule.LiveMax;
  419. }
  420. else if(peopleInfo.RoomType == Enum_RoomType::ROOM_DIC)
  421. {
  422. if(!m_personCountRule.DicMaxEnable)
  423. {
  424. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 导播间最大人数检测功能未开启", m_baseLog);
  425. return;
  426. }
  427. /* 判断有没有名称 */
  428. if(peopleInfo.RoomName.empty())
  429. {
  430. roomName = "导播间";
  431. } else {
  432. roomName = peopleInfo.RoomName;
  433. }
  434. maxNum = m_personCountRule.DicMax;
  435. }
  436. else if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC)
  437. {
  438. if(!m_personCountRule.LiveDicMaxEnable)
  439. {
  440. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间+导播间最大人数检测功能未开启", m_baseLog);
  441. return;
  442. }
  443. /* 判断有没有名称 */
  444. if(peopleInfo.RoomName.empty())
  445. {
  446. roomName = "直播间+导播间";
  447. } else {
  448. roomName = peopleInfo.RoomName;
  449. }
  450. maxNum = m_personCountRule.LiveDicMax;
  451. }
  452. else
  453. {
  454. SPDLOG_LOGGER_WARN(m_logger, "{} 房间类型错误", m_baseLog);
  455. return;
  456. }
  457. /* 查找房间信息 */
  458. RoomCamActInfo roomInfo;
  459. if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC)
  460. {
  461. /* 创造一个摄像机和算法信息 */
  462. std::list<std::string> listAct;
  463. listAct.push_back("0");
  464. roomInfo.mapCameraAction.insert(std::make_pair(0, listAct));
  465. } else {
  466. if(!findRoomInfo(peopleInfo.RoomID, roomInfo))
  467. {
  468. SPDLOG_LOGGER_ERROR(m_logger, "房间ID:{},房间信息不存在", peopleInfo.RoomID);
  469. return;
  470. }
  471. }
  472. /* 开启了最大人数的检测,判断是否超过最大人数 */
  473. if(peopleInfo.MaxNum > maxNum)
  474. {
  475. /* 超过了最大人数,判断是否已经加入了内存缓冲区 */
  476. AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID);
  477. if(alarmBuffer != nullptr)
  478. {
  479. /* 更新时间,这里只更新时间吗?最大人数和图片不更新吗? */
  480. alarmBuffer->AlarmTime = m_nowTime;
  481. }else
  482. {
  483. /* 没有加入缓冲区,先写入数据库,再加入缓冲区 */
  484. AlarmInfo alarmInfo;
  485. alarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  486. alarmInfo.appFunction = m_funcThreadInfo.appFunction;
  487. alarmInfo.RoomID = peopleInfo.RoomID;
  488. alarmInfo.DeviceID = roomInfo.mapCameraAction.begin()->first;
  489. alarmInfo.ImageInfo = peopleInfo.imagePath;
  490. alarmInfo.ActionID = roomInfo.mapCameraAction.begin()->second.front();
  491. alarmInfo.StartTime = m_nowTime;
  492. alarmInfo.EventTime = m_nowTime;
  493. alarmInfo.Is_Alarm = true;
  494. alarmInfo.ActionDes = fmt::format("{}人数为{},已超过最大人数{}限制",
  495. roomName, peopleInfo.MaxNum, maxNum);
  496. for(auto& it : roomInfo.mapCameraAction)
  497. {
  498. alarmInfo.listBbox.push_back(GConfig.getCameraName(it.first));
  499. }
  500. int pkid = 0;
  501. if(!m_fromWebAPI->insertAlarmInfo(alarmInfo, pkid))
  502. {
  503. SPDLOG_LOGGER_ERROR(m_logger, "{} 写入报警信息失败", m_baseLog);
  504. return;
  505. }
  506. SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},超过最大人数{},报警开始,已写入数据库",
  507. m_baseLog, roomName, maxNum);
  508. /* 将报警信息写入缓存中 */
  509. // alarmBuffer.isMax = true;
  510. // alarmBuffer.isInsertDB = true;
  511. AlarmBuffer* alarmBuffer = new AlarmBuffer();
  512. if(alarmBuffer == nullptr)
  513. {
  514. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建报警缓冲区失败", m_baseLog);
  515. return;
  516. }
  517. alarmBuffer->ChannelID = m_funcThreadInfo.ChannelID;
  518. alarmBuffer->RoomID = peopleInfo.RoomID;
  519. alarmBuffer->PKID = pkid;
  520. alarmBuffer->RoomType = peopleInfo.RoomType;
  521. alarmBuffer->PeopleNum = peopleInfo.MaxNum;
  522. alarmBuffer->AlarmTime = m_nowTime;
  523. alarmBuffer->imagePath = peopleInfo.imagePath;
  524. alarmBuffer->actionDecs = alarmInfo.ActionDes;
  525. m_mapAlarmBuffer.insert(std::make_pair(peopleInfo.RoomID, alarmBuffer));
  526. }
  527. }else
  528. {
  529. /* 未超过最大人数,判断是否已经写入的数据库,如果已经写入了数据库,就结束报警 */
  530. AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID);
  531. if(alarmBuffer != nullptr)
  532. {
  533. /* 已写入数据库,结束报警,但是需要注意,人数少于一定时间后才结束报警,不会立马结束 */
  534. if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > GVariable.AppPeopleCount_LessTime)
  535. {
  536. SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},超过最大人数{},报警结束",
  537. m_baseLog, roomName, maxNum);
  538. /* 结束报警 */
  539. if(!m_fromWebAPI->endAlarmInfoByPKID(alarmBuffer->PKID, m_nowTime))
  540. {
  541. SPDLOG_LOGGER_ERROR(m_logger, "{} 结束超过最大人数报警失败,PKID: {}", m_baseLog, alarmBuffer->PKID);
  542. return;
  543. }
  544. /* 删除报警缓冲区 */
  545. m_mapAlarmBuffer.erase(peopleInfo.RoomID);
  546. delete alarmBuffer;
  547. alarmBuffer = nullptr;
  548. }
  549. }
  550. }
  551. }
  552. /* 处理房间内人数最小值 */
  553. void FuncRegionalPersonCount::handleRoomMinNum(const RoomPeopleInfo& peopleInfo)
  554. {
  555. std::string roomName = "";
  556. int minNum = 0;
  557. /* 判断当前房间是否开启了最少人员检测功能 */
  558. if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVE)
  559. {
  560. if(!m_personCountRule.LiveMinEnable)
  561. {
  562. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间最少人数检测功能未开启", m_baseLog);
  563. return;
  564. }
  565. /* 判断有没有名称 */
  566. if(peopleInfo.RoomName.empty())
  567. {
  568. roomName = "直播间";
  569. } else {
  570. roomName = peopleInfo.RoomName;
  571. }
  572. minNum = m_personCountRule.LiveMin;
  573. }
  574. else if(peopleInfo.RoomType == Enum_RoomType::ROOM_DIC)
  575. {
  576. if(!m_personCountRule.DicMinEnable)
  577. {
  578. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 导播间最少人数检测功能未开启", m_baseLog);
  579. return;
  580. }
  581. /* 判断有没有名称 */
  582. if(peopleInfo.RoomName.empty())
  583. {
  584. roomName = "导播间";
  585. } else {
  586. roomName = peopleInfo.RoomName;
  587. }
  588. minNum = m_personCountRule.DicMin;
  589. }
  590. else if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC)
  591. {
  592. if(!m_personCountRule.LiveDicMinEnable)
  593. {
  594. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间+导播间最少人数检测功能未开启", m_baseLog);
  595. return;
  596. }
  597. /* 判断有没有名称 */
  598. if(peopleInfo.RoomName.empty())
  599. {
  600. roomName = "直播间+导播间";
  601. } else {
  602. roomName = peopleInfo.RoomName;
  603. }
  604. minNum = m_personCountRule.LiveDicMin;
  605. }
  606. else
  607. {
  608. SPDLOG_LOGGER_WARN(m_logger, "{} 房间类型错误", m_baseLog);
  609. return;
  610. }
  611. /* 查找房间信息 */
  612. RoomCamActInfo roomInfo;
  613. if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC)
  614. {
  615. /* 创造一个摄像机和算法信息 */
  616. std::list<std::string> listAct;
  617. listAct.push_back("0");
  618. roomInfo.mapCameraAction.insert(std::make_pair(0, listAct));
  619. } else {
  620. if(!findRoomInfo(peopleInfo.RoomID, roomInfo))
  621. {
  622. SPDLOG_LOGGER_ERROR(m_logger, "房间ID:{},房间信息不存在", peopleInfo.RoomID);
  623. return;
  624. }
  625. }
  626. /* 开启了最小人数的检测,判断是否小于最少人数
  627. 如果小于,不会立刻写入数据库,先存储到缓存中,经过一定时间后再写入数据库 */
  628. if(peopleInfo.MaxNum < minNum)
  629. {
  630. /* 小于最少人数,判断是否已经加入了内存缓冲区 */
  631. AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID);
  632. if(alarmBuffer != nullptr)
  633. {
  634. /* 已经存在缓存中了,判断是否已经写入数据库 */
  635. if(alarmBuffer->PKID == 0)
  636. {
  637. /* 还未写入数据库,判断是否超过时间 */
  638. // if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > 2)
  639. if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > GVariable.AppPeopleCount_LessTime)
  640. {
  641. /* 超过时间,写入数据库 */
  642. AlarmInfo alarmInfo;
  643. alarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  644. alarmInfo.appFunction = m_funcThreadInfo.appFunction;
  645. alarmInfo.RoomID = peopleInfo.RoomID;
  646. alarmInfo.DeviceID = roomInfo.mapCameraAction.begin()->first;
  647. alarmInfo.ImageInfo = peopleInfo.imagePath;
  648. alarmInfo.ActionID = roomInfo.mapCameraAction.begin()->second.front();
  649. alarmInfo.EventTime = m_nowTime;
  650. alarmInfo.Is_Alarm = true;
  651. alarmInfo.ActionDes = fmt::format("{}人数为{},已低于最小人数{}限制",
  652. roomName, peopleInfo.MaxNum, minNum);
  653. for(auto& it : roomInfo.mapCameraAction)
  654. {
  655. alarmInfo.listBbox.push_back(GConfig.getCameraName(it.first));
  656. }
  657. int pkid = 0;
  658. if(!m_fromWebAPI->insertAlarmInfo(alarmInfo, pkid))
  659. {
  660. SPDLOG_LOGGER_ERROR(m_logger, "{} 写入报警信息失败", m_baseLog);
  661. return;
  662. }
  663. SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},已低于最小人数{}限制,已写入数据库",
  664. m_baseLog, roomName, peopleInfo.MaxNum, minNum);
  665. /* 更新报警缓冲区 */
  666. alarmBuffer->PKID = pkid;
  667. }
  668. }
  669. }else
  670. {
  671. AlarmBuffer* alarmBuffer = new AlarmBuffer();
  672. if(alarmBuffer == nullptr)
  673. {
  674. SPDLOG_LOGGER_ERROR(m_logger, "{} 创建报警缓冲区失败", m_baseLog);
  675. return;
  676. }
  677. /* 将报警信息写入缓存中 */
  678. alarmBuffer->ChannelID = m_funcThreadInfo.ChannelID;
  679. alarmBuffer->RoomID = peopleInfo.RoomID;
  680. alarmBuffer->PKID = 0;
  681. alarmBuffer->RoomType = peopleInfo.RoomType;
  682. alarmBuffer->PeopleNum = peopleInfo.MaxNum;
  683. alarmBuffer->AlarmTime = m_nowTime;
  684. alarmBuffer->imagePath = peopleInfo.imagePath;
  685. m_mapAlarmBuffer.insert(std::make_pair(peopleInfo.RoomID, alarmBuffer));
  686. SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},已低于最小人数{}限制,已写入缓存",
  687. m_baseLog, roomName, peopleInfo.MaxNum, minNum);
  688. }
  689. }else
  690. {
  691. /* 不小于最少人数 */
  692. auto alarmBuffer = findAlarmBuffer(peopleInfo.RoomID);
  693. if(alarmBuffer != nullptr)
  694. {
  695. /* 判断是否已经写入数据库 */
  696. if(alarmBuffer->PKID != 0)
  697. {
  698. /* 已经写入数据库,结束报警 */
  699. if(!m_fromWebAPI->endAlarmInfoByPKID(alarmBuffer->PKID, m_nowTime))
  700. {
  701. SPDLOG_LOGGER_ERROR(m_logger, "{} 结束低于最小人数报警失败,PKID: {}", m_baseLog, alarmBuffer->PKID);
  702. return;
  703. }
  704. SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},结束低于最小人数{}报警",
  705. m_baseLog, roomName, peopleInfo.MaxNum, minNum);
  706. /* 删除报警缓冲区 */
  707. m_mapAlarmBuffer.erase(peopleInfo.RoomID);
  708. delete alarmBuffer;
  709. alarmBuffer = nullptr;
  710. }
  711. }
  712. }
  713. }
  714. /* 根据房间ID查找报警缓冲区 */
  715. AlarmBuffer* FuncRegionalPersonCount::findAlarmBuffer(int roomID)
  716. {
  717. if(m_mapAlarmBuffer.empty())
  718. {
  719. return nullptr;
  720. }
  721. for(auto& it : m_mapAlarmBuffer)
  722. {
  723. if(it.first == roomID)
  724. {
  725. return it.second;
  726. }
  727. }
  728. return nullptr;
  729. }
  730. /* 根据房间ID查找房间信息 */
  731. bool FuncRegionalPersonCount::findRoomInfo(int roomID, RoomCamActInfo& roomInfo)
  732. {
  733. if(m_listRoomCamAct.empty())
  734. {
  735. return false;
  736. }
  737. for(auto& it : m_listRoomCamAct)
  738. {
  739. if(it.RoomID == roomID)
  740. {
  741. roomInfo = it;
  742. return true;
  743. }
  744. }
  745. return false;
  746. }
  747. /* 清空报警列表 */
  748. void FuncRegionalPersonCount::clearAlarmBufferMap()
  749. {
  750. for(auto& it : m_mapAlarmBuffer)
  751. {
  752. if(it.second != nullptr)
  753. {
  754. delete it.second;
  755. it.second = nullptr;
  756. }
  757. }
  758. m_mapAlarmBuffer.clear();
  759. }