FuncOrdinary.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. while (GThreadInfo.getRunning())
  30. {
  31. /* 休眠设置的时间 */
  32. std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
  33. /* 从全局的信息块中更新功能信息,如是否需要退出线程,主要是更新摄像机关联的算法信息 */
  34. GThreadInfo.updateFuncInfo(m_funcThreadInfo);
  35. /* 如果线程的运行状态为停止 */
  36. if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
  37. {
  38. /* 退出线程 */
  39. break;
  40. }
  41. /* 判断是否在检测时间段内 */
  42. if(!isInDetectTime(m_periodInfo))
  43. {
  44. continue;
  45. }
  46. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 在检测时间段内", m_baseLog);
  47. /* 读取Redis数据 */
  48. for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  49. {
  50. for(const auto& it : roomInfo.mapCameraAction)
  51. {
  52. for(const auto act : it.second)
  53. {
  54. /* 读取Redis数据 */
  55. std::string strKey = std::to_string(it.first) + ":" + act;
  56. std::string strRetValue;
  57. SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
  58. if(!m_fromRedis->getRedisString(strKey, strRetValue))
  59. {
  60. SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
  61. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  62. continue;
  63. }
  64. SPDLOG_LOGGER_DEBUG(m_logger, "数据:{}", strRetValue);
  65. /* 解析数据,先设置基础数据 */
  66. // AlarmInfo newAlarmInfo;
  67. // newAlarmInfo.ActionID = act;
  68. // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  69. // parseRedisBaseData(strRetValue, newAlarmInfo);
  70. // parseRedisBBoxesData(strRetValue, newAlarmInfo);
  71. /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  72. // if(isEventTimeVaild(newAlarmInfo.EventTime))
  73. // {
  74. // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime);
  75. // std::this_thread::sleep_for(std::chrono::milliseconds(100));
  76. // continue;
  77. // }
  78. }
  79. }
  80. }
  81. continue;
  82. /* 读取Redis信息,处理数据,第一层循环是根据房间读取,第二个循环是根据房间内的摄像机读取 */
  83. for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  84. {
  85. for(const auto& it : roomInfo.mapCameraAction)
  86. {
  87. for(const auto act : it.second)
  88. {
  89. /* 读取Redis数据 */
  90. std::string strKey = std::to_string(it.first) + ":" + act;
  91. std::string strRetValue;
  92. if(!m_fromRedis->getRedisString(strKey, strRetValue))
  93. {
  94. SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
  95. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  96. continue;
  97. }
  98. /* 解析数据,先设置基础数据 */
  99. AlarmInfo newAlarmInfo;
  100. newAlarmInfo.ActionID = act;
  101. newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  102. parseRedisBaseData(strRetValue, newAlarmInfo);
  103. parseRedisBBoxesData(strRetValue, newAlarmInfo);
  104. /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  105. if(isEventTimeVaild(newAlarmInfo.EventTime))
  106. {
  107. SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime);
  108. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  109. continue;
  110. }
  111. /* -------------------------------------------------------------------------------
  112. * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
  113. * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
  114. * 报警数据的结束时间,并清空pAlarmInfo
  115. * ------------------------------------------------------------------------------- */
  116. /* 找出数组中与当前报警ID相同的的报警信息 */
  117. auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarmInfo);
  118. /* 没有找到报警记录,就新建一个 */
  119. if(pAlarmInfo == nullptr)
  120. {
  121. /* 新记录有报警,新建报警记录 */
  122. if(newAlarmInfo.Is_Alarm)
  123. {
  124. /* 图片不能是空,如果是空的,就不写入数据库 */
  125. if(!newAlarmInfo.ImageInfo.empty())
  126. {
  127. /* 违禁品检测,开始时间是事件时间 */
  128. newAlarmInfo.StartTime = newAlarmInfo.EventTime;
  129. newAlarmInfo.EndTime = "";
  130. /* 保存新的报警记录 */
  131. newAlarmInfo.Is_InsertEQM = false;
  132. m_listAlarm.addAlarmInfo(newAlarmInfo);
  133. }else
  134. {
  135. SPDLOG_LOGGER_WARN(m_logger, "频道:{}, 房间:{}, 摄像机:{}, 算法:{}, 有报警区域, 但是没有图片信息", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
  136. }
  137. }
  138. }
  139. /* 已有报警记录 */
  140. else
  141. {
  142. /* 更新图片信息 */
  143. if(!newAlarmInfo.ImageInfo.empty())
  144. {
  145. pAlarmInfo->ImageInfo = newAlarmInfo.ImageInfo;
  146. }
  147. /* 判断是否还在报警中 */
  148. if(newAlarmInfo.Is_Alarm)
  149. {
  150. /* 正在报警中,检查是否已经写入到数据库中 */
  151. if(pAlarmInfo->Is_InsertEQM)
  152. {
  153. /* 已经写入到数据库中,不做处理 */
  154. }else
  155. {
  156. /* 判断报警时长间隔是否足够 */
  157. if(!isAlarmTimeVaild(*pAlarmInfo))
  158. {
  159. /* 不够报警时间,直接进行下一个循环 */
  160. continue;
  161. }
  162. /* 写入到数据库 */
  163. pAlarmInfo->Is_InsertEQM = false;
  164. if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo))
  165. {
  166. pAlarmInfo->Is_InsertEQM = true;
  167. }else {
  168. SPDLOG_LOGGER_ERROR(m_logger, "写入tAlarmInfo报警数据失败, 频率:{}, 房间:{}, 算法:{} ", m_funcThreadInfo.ChannelID, roomInfo.RoomID, act);
  169. }
  170. }
  171. } else
  172. {
  173. /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
  174. * 更新数据库结束时间,结束时间是此时电脑时间 */
  175. if(isAlarmTimeVaild(*pAlarmInfo))
  176. {
  177. pAlarmInfo->EndTime = chronoToStrTime(std::chrono::system_clock::now());
  178. /* 判断是否已经写入到数据库中 */
  179. if(pAlarmInfo->Is_InsertEQM)
  180. {
  181. /* 已经写入到数据库中,更新结束时间 */
  182. m_fromWebAPI->updateAlarmEndTime(*pAlarmInfo);
  183. }else {
  184. /* 没有写入到数据库中,写入到数据库中 */
  185. m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
  186. }
  187. SPDLOG_LOGGER_INFO(m_logger, "频率:{}, 房间:{}, 摄像机:{}, 算法:{}, 报警结束", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
  188. }
  189. /* 删除这个报警信息 */
  190. m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
  191. }
  192. }
  193. }
  194. }
  195. }
  196. }
  197. }
  198. /* 判断报警时长是否符合不同应用的最小间隔 */
  199. bool FuncOrdinary::isAlarmTimeVaild(const AlarmInfo& info)
  200. {
  201. /* 违禁品物品 */
  202. if(info.appFunction == AppFunction::APP_Contraband)
  203. {
  204. if(timeDiffWithNow(info.EventTime) < GVariable.AppContraband_Time)
  205. {
  206. return false;
  207. }
  208. }
  209. /* 玩手机识别 */
  210. else if(info.appFunction == AppFunction::APP_PlayPhone)
  211. {
  212. if(timeDiffWithNow(info.EventTime) < GVariable.AppPlayPhone)
  213. {
  214. return false;
  215. }
  216. }
  217. /* 老鼠识别 */
  218. else if(info.appFunction == AppFunction::APP_Mouse)
  219. {
  220. if(timeDiffWithNow(info.EventTime) < GVariable.AppMouse)
  221. {
  222. return false;
  223. }
  224. }
  225. /* 未戴口罩识别 */
  226. else if(info.appFunction == AppFunction::APP_NoMask)
  227. {
  228. if(timeDiffWithNow(info.EventTime) < GVariable.AppMask)
  229. {
  230. return false;
  231. }
  232. }
  233. /* 疲劳检测 */
  234. else if(info.appFunction == AppFunction::APP_Fatigue)
  235. {
  236. if(timeDiffWithNow(info.EventTime) < GVariable.AppTired_Time)
  237. {
  238. return false;
  239. }
  240. }
  241. /* 摔倒识别 */
  242. else if(info.appFunction == AppFunction::APP_AllDown)
  243. {
  244. return true;
  245. }
  246. return true;
  247. }