FuncOrdinary.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #include "FuncOrdinary.h"
  2. #include "GlobalVariable.h"
  3. #include "FromRedis.h"
  4. #include "FromWebAPI.h"
  5. #include "UniversalFunc.h"
  6. #include "GlobalConfig.h"
  7. FuncOrdinary::FuncOrdinary()
  8. {
  9. m_logger = spdlog::get("SPAServer");
  10. if(m_logger == nullptr)
  11. {
  12. SPDLOG_LOGGER_ERROR(m_logger, "SPAServer logger is nullptr");
  13. return;
  14. }
  15. }
  16. FuncOrdinary::~FuncOrdinary()
  17. {
  18. }
  19. /* 任务线程 */
  20. void FuncOrdinary::task()
  21. {
  22. /* 初始化WebAPI和Redis接口 */
  23. if(!initDataInterface())
  24. {
  25. return;
  26. }
  27. /* 保存上次获取时间段的时间 */
  28. QDateTime lastTime = QDateTime::fromString("2025-05-07 00:00:00", "yyyy-MM-dd hh:mm:ss");
  29. /* 创建临时的报警信息 */
  30. std::list<AlarmInfo> listAlarmTemp;
  31. while (GThreadInfo.getRunning())
  32. {
  33. /* 休眠设置的时间 */
  34. std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
  35. /* 从全局的信息块中更新功能信息,如是否需要退出线程,主要是更新摄像机关联的算法信息 */
  36. GThreadInfo.updateFuncInfo(m_funcThreadInfo);
  37. /* 如果线程的运行状态为停止 */
  38. if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
  39. {
  40. /* 退出线程 */
  41. return;
  42. }
  43. /* 判断是否在检测时间段内 */
  44. if(!isInDetectTime(m_periodInfo))
  45. {
  46. continue;
  47. }
  48. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 在检测时间段内", m_baseLog);
  49. /* ========================= 读取Redis数据 ========================= */
  50. listAlarmTemp.clear();
  51. /* 读取Redis数据 */
  52. for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  53. {
  54. for(const auto& cam : roomInfo.mapCameraAction)
  55. {
  56. for(const auto act : cam.second)
  57. {
  58. /* 读取Redis数据 */
  59. std::string strKey = std::to_string(cam.first) + ":" + act;
  60. std::string strRetValue;
  61. // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
  62. if(!m_fromRedis->getRedisString(strKey, strRetValue))
  63. {
  64. SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
  65. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  66. continue;
  67. }
  68. /* 解析数据,先设置基础数据 */
  69. AlarmInfo newAlarmInfo;
  70. newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  71. newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  72. newAlarmInfo.RoomID = roomInfo.RoomID;
  73. newAlarmInfo.DeviceID = cam.first;
  74. newAlarmInfo.ActionID = act;
  75. parseRedisBaseData(strRetValue, newAlarmInfo);
  76. parseRedisBBoxesData(strRetValue, newAlarmInfo);
  77. /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  78. if(!isEventTimeVaild(newAlarmInfo.EventTime))
  79. {
  80. /* 事件时间超过600秒,可能是超脑挂了 */
  81. SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
  82. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  83. continue;
  84. }
  85. listAlarmTemp.push_back(newAlarmInfo);
  86. }
  87. }
  88. }
  89. SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据成功, 报警数据数目: {}", m_listAlarm.listAlarmInfo.size());
  90. // continue;
  91. /* ========================= 处理报警数据 ========================= */
  92. for(auto newAlarm : listAlarmTemp)
  93. {
  94. /* 找到该报警相关的房间信息 */
  95. auto roomInfo = m_funcThreadInfo.findRoomInfo(newAlarm.RoomID);
  96. if(roomInfo.RoomID == -1)
  97. {
  98. SPDLOG_LOGGER_ERROR(m_logger, "{} 房间ID: {} 不存在", m_baseLog, newAlarm.RoomID);
  99. continue;
  100. }
  101. /* 创建基础日志信息 */
  102. std::string tmpBaseLog = fmt::format("{} 房间: {}, 摄像机ID: {}, 算法ID: {}", m_baseLog, roomInfo.strRoomName, newAlarm.DeviceID, newAlarm.ActionID);
  103. /* -------------------------------------------------------------------------------
  104. * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
  105. * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
  106. * 报警数据的结束时间,并清空pAlarmInfo
  107. * ------------------------------------------------------------------------------- */
  108. /* 找出数组中与当前报警ID相同的的报警信息 */
  109. auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarm);
  110. /* 没有找到报警记录,就新建一个 */
  111. if(pAlarmInfo == nullptr)
  112. {
  113. /* 新记录有报警,新建报警记录 */
  114. if(newAlarm.Is_Alarm)
  115. {
  116. /* 图片不能是空,如果是空的,就不写入数据库 */
  117. if(!newAlarm.ImageInfo.empty())
  118. {
  119. /* 违禁品检测,开始时间是事件时间 */
  120. newAlarm.StartTime = newAlarm.EventTime;
  121. newAlarm.EndTime = GVariable.nullTime;
  122. /* 保存新的报警记录 */
  123. newAlarm.Is_InsertEQM = false;
  124. m_listAlarm.addAlarmInfo(newAlarm);
  125. SPDLOG_LOGGER_DEBUG(m_logger, "{} 新的报警,加入到缓存中", tmpBaseLog);
  126. }else
  127. {
  128. SPDLOG_LOGGER_WARN(m_logger, "{}, 有报警区域, 但是没有图片信息", tmpBaseLog);
  129. }
  130. }
  131. } else
  132. {
  133. /* 已有报警记录 */
  134. /* 更新图片信息 */
  135. if(!newAlarm.ImageInfo.empty())
  136. {
  137. pAlarmInfo->ImageInfo = newAlarm.ImageInfo;
  138. }
  139. /* 判断是否还在报警中 */
  140. if(newAlarm.Is_Alarm)
  141. {
  142. /* 正在报警中,检查是否已经写入到数据库中 */
  143. if(pAlarmInfo->Is_InsertEQM)
  144. {
  145. /* 已经写入到数据库中,不做处理 */
  146. }else
  147. {
  148. /* 判断报警时长间隔是否足够 */
  149. if(!isAlarmTimeVaild(*pAlarmInfo))
  150. {
  151. /* 不够报警时间,直接进行下一个循环 */
  152. continue;
  153. }
  154. /* 写入到数据库 */
  155. pAlarmInfo->Is_InsertEQM = false;
  156. if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo))
  157. {
  158. pAlarmInfo->Is_InsertEQM = true;
  159. }else {
  160. SPDLOG_LOGGER_ERROR(m_logger, "{} 写入tAlarmInfo报警数据失败! ", tmpBaseLog);
  161. }
  162. SPDLOG_LOGGER_INFO(m_logger, "{}, 报警开始,写入数据库", tmpBaseLog);
  163. }
  164. } else
  165. {
  166. /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
  167. * 更新数据库结束时间,结束时间是此时电脑时间 */
  168. if(isAlarmTimeVaild(*pAlarmInfo))
  169. {
  170. pAlarmInfo->EndTime = m_nowTime;
  171. /* 判断是否已经写入到数据库中 */
  172. if(pAlarmInfo->Is_InsertEQM)
  173. {
  174. /* 已经写入到数据库中,更新结束时间 */
  175. m_fromWebAPI->updateAlarmEndTime(*pAlarmInfo);
  176. }else {
  177. /* 没有写入到数据库中,写入到数据库中 */
  178. m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
  179. }
  180. SPDLOG_LOGGER_INFO(m_logger, "{}, 报警结束", tmpBaseLog);
  181. }
  182. /* 删除这个报警信息 */
  183. m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
  184. }
  185. }
  186. }
  187. }
  188. }
  189. /* old处理方法 */
  190. void FuncOrdinary::oldTask()
  191. {
  192. // /* 读取Redis信息,处理数据,第一层循环是根据房间读取,第二个循环是根据房间内的摄像机读取 */
  193. // for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  194. // {
  195. // for(const auto& it : roomInfo.mapCameraAction)
  196. // {
  197. // for(const auto act : it.second)
  198. // {
  199. // /* 读取Redis数据 */
  200. // std::string strKey = std::to_string(it.first) + ":" + act;
  201. // std::string strRetValue;
  202. // if(!m_fromRedis->getRedisString(strKey, strRetValue))
  203. // {
  204. // SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
  205. // std::this_thread::sleep_for(std::chrono::milliseconds(10));
  206. // continue;
  207. // }
  208. // /* 解析数据,先设置基础数据 */
  209. // AlarmInfo newAlarmInfo;
  210. // newAlarmInfo.ActionID = act;
  211. // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  212. // parseRedisBaseData(strRetValue, newAlarmInfo);
  213. // parseRedisBBoxesData(strRetValue, newAlarmInfo);
  214. // /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  215. // if(isEventTimeVaild(newAlarmInfo.EventTime))
  216. // {
  217. // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime);
  218. // std::this_thread::sleep_for(std::chrono::milliseconds(100));
  219. // continue;
  220. // }
  221. // /* -------------------------------------------------------------------------------
  222. // * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
  223. // * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
  224. // * 报警数据的结束时间,并清空pAlarmInfo
  225. // * ------------------------------------------------------------------------------- */
  226. // /* 找出数组中与当前报警ID相同的的报警信息 */
  227. // auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarmInfo);
  228. // /* 没有找到报警记录,就新建一个 */
  229. // if(pAlarmInfo == nullptr)
  230. // {
  231. // /* 新记录有报警,新建报警记录 */
  232. // if(newAlarmInfo.Is_Alarm)
  233. // {
  234. // /* 图片不能是空,如果是空的,就不写入数据库 */
  235. // if(!newAlarmInfo.ImageInfo.empty())
  236. // {
  237. // /* 违禁品检测,开始时间是事件时间 */
  238. // newAlarmInfo.StartTime = newAlarmInfo.EventTime;
  239. // newAlarmInfo.EndTime = "";
  240. // /* 保存新的报警记录 */
  241. // newAlarmInfo.Is_InsertEQM = false;
  242. // m_listAlarm.addAlarmInfo(newAlarmInfo);
  243. // }else
  244. // {
  245. // SPDLOG_LOGGER_WARN(m_logger, "频道:{}, 房间:{}, 摄像机:{}, 算法:{}, 有报警区域, 但是没有图片信息", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
  246. // }
  247. // }
  248. // }
  249. // /* 已有报警记录 */
  250. // else
  251. // {
  252. // /* 更新图片信息 */
  253. // if(!newAlarmInfo.ImageInfo.empty())
  254. // {
  255. // pAlarmInfo->ImageInfo = newAlarmInfo.ImageInfo;
  256. // }
  257. // /* 判断是否还在报警中 */
  258. // if(newAlarmInfo.Is_Alarm)
  259. // {
  260. // /* 正在报警中,检查是否已经写入到数据库中 */
  261. // if(pAlarmInfo->Is_InsertEQM)
  262. // {
  263. // /* 已经写入到数据库中,不做处理 */
  264. // }else
  265. // {
  266. // /* 判断报警时长间隔是否足够 */
  267. // if(!isAlarmTimeVaild(*pAlarmInfo))
  268. // {
  269. // /* 不够报警时间,直接进行下一个循环 */
  270. // continue;
  271. // }
  272. // /* 写入到数据库 */
  273. // pAlarmInfo->Is_InsertEQM = false;
  274. // if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo))
  275. // {
  276. // pAlarmInfo->Is_InsertEQM = true;
  277. // }else {
  278. // SPDLOG_LOGGER_ERROR(m_logger, "写入tAlarmInfo报警数据失败, 频率:{}, 房间:{}, 算法:{} ", m_funcThreadInfo.ChannelID, roomInfo.RoomID, act);
  279. // }
  280. // }
  281. // } else
  282. // {
  283. // /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
  284. // * 更新数据库结束时间,结束时间是此时电脑时间 */
  285. // if(isAlarmTimeVaild(*pAlarmInfo))
  286. // {
  287. // pAlarmInfo->EndTime = chronoToStrTime(std::chrono::system_clock::now());
  288. // /* 判断是否已经写入到数据库中 */
  289. // if(pAlarmInfo->Is_InsertEQM)
  290. // {
  291. // /* 已经写入到数据库中,更新结束时间 */
  292. // m_fromWebAPI->updateAlarmEndTime(*pAlarmInfo);
  293. // }else {
  294. // /* 没有写入到数据库中,写入到数据库中 */
  295. // m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
  296. // }
  297. // SPDLOG_LOGGER_INFO(m_logger, "频率:{}, 房间:{}, 摄像机:{}, 算法:{}, 报警结束", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
  298. // }
  299. // /* 删除这个报警信息 */
  300. // m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
  301. // }
  302. // }
  303. // }
  304. // }
  305. // }
  306. }
  307. /* 判断报警时长是否符合不同应用的最小间隔 */
  308. bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
  309. {
  310. int alarmTime = 0;
  311. /* 违禁品物品 */
  312. if(info.appFunction == AppFunction::APP_Contraband)
  313. {
  314. alarmTime = GVariable.AppContraband_Time;
  315. }
  316. /* 玩手机识别 */
  317. else if(info.appFunction == AppFunction::APP_PlayPhone)
  318. {
  319. alarmTime = GVariable.AppPlayPhone;
  320. }
  321. /* 老鼠识别 */
  322. else if(info.appFunction == AppFunction::APP_Mouse)
  323. {
  324. alarmTime = GVariable.AppMouse;
  325. }
  326. /* 未戴口罩识别 */
  327. else if(info.appFunction == AppFunction::APP_NoMask)
  328. {
  329. alarmTime = GVariable.AppMask;
  330. }
  331. /* 疲劳检测 */
  332. else if(info.appFunction == AppFunction::APP_Fatigue)
  333. {
  334. alarmTime = GVariable.AppTired_Time;
  335. }
  336. /* 摔倒识别 */
  337. else if(info.appFunction == AppFunction::APP_AllDown)
  338. {
  339. return true;
  340. }
  341. if(info.EventTime.secsTo(m_nowTime) < alarmTime)
  342. {
  343. return false;
  344. }
  345. return true;
  346. }