FuncRegionalPerson.cpp 29 KB

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