FuncRegionalPerson.cpp 28 KB

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