FuncRegionalPerson.cpp 29 KB

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