FuncBase.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #include "FuncBase.h"
  2. #include "GlobalConfig.h"
  3. #include "UniversalFunc.h"
  4. #include "FromRedis.h"
  5. #include "FromWebAPI.h"
  6. FuncBase::FuncBase()
  7. {
  8. m_fromRedis = std::make_shared<FromRedis>();
  9. m_fromWebAPI = std::make_shared<FromWebAPI>();
  10. }
  11. FuncBase::~FuncBase()
  12. {
  13. if(m_fromRedis != nullptr)
  14. {
  15. m_fromRedis.reset();
  16. m_fromRedis = nullptr;
  17. }
  18. if(m_fromWebAPI != nullptr)
  19. {
  20. m_fromWebAPI.reset();
  21. m_fromWebAPI = nullptr;
  22. }
  23. if(m_logger != nullptr)
  24. {
  25. m_logger.reset();
  26. m_logger = nullptr;
  27. }
  28. }
  29. /* 任务线程 */
  30. void FuncBase::thread_task()
  31. {
  32. /* 先做一些通用的初始化 */
  33. if(m_logger == nullptr)
  34. {
  35. m_logger = spdlog::get("SPAServer");
  36. if(m_logger == nullptr)
  37. {
  38. SPDLOG_ERROR("SPAServer logger is nullptr");
  39. return;
  40. }
  41. }
  42. /* 线程功能信息 */
  43. if(m_funcThreadInfo.appFunction == AppFunction::APP_NONE)
  44. {
  45. SPDLOG_LOGGER_ERROR(m_logger, "未设置线程功能信息");
  46. return;
  47. }
  48. SPDLOG_LOGGER_INFO(m_logger, "---------------------- 开启频道: [{}:{}] “{}”功能 ----------------------", m_funcThreadInfo.strChannelName, m_funcThreadInfo.ChannelID, m_funcThreadInfo.strFunctionName);
  49. for(auto& room : m_funcThreadInfo.listRoomCamActInfo)
  50. {
  51. for(auto& cam : room.mapCameraAction)
  52. {
  53. for(auto& act : cam.second)
  54. {
  55. SPDLOG_LOGGER_DEBUG(m_logger, "房间ID: {}, 摄像机ID: {}, 算法ID: {}", room.RoomID, cam.first, act);
  56. }
  57. }
  58. }
  59. /* 设置线程的全局运行状态 */
  60. GThreadInfo.setThreadState(m_funcThreadInfo, RunTimeState::RUN_STATE_RUN);
  61. /* 设置线程运行状态 */
  62. m_bRunning = true;
  63. /* 设置初始化字符串 */
  64. m_baseLog = fmt::format("★ 频道[{}] 功能线程[{}] ", m_funcThreadInfo.strChannelName, m_funcThreadInfo.strFunctionName);
  65. /* 执行线程功能,会一直阻塞,直到退出 */
  66. task();
  67. /* 设置线程退出的状态,设置成 RUN_STATE_EXITCOMPLET ,就会被管理线程回收 */
  68. GThreadInfo.setThreadState(m_funcThreadInfo, RunTimeState::RUN_STATE_EXITCOMPLET);
  69. SPDLOG_LOGGER_INFO(m_logger, "{} 退出", m_baseLog);
  70. m_bRunning = false;
  71. }
  72. /* 设置功能信息 */
  73. void FuncBase::setFuncThreadInfo(FuncThreadInfo* pFuncAct)
  74. {
  75. m_funcThreadInfo = *pFuncAct;
  76. }
  77. void FuncBase::setFuncThreadInfo(FuncThreadInfo& FuncAct)
  78. {
  79. m_funcThreadInfo = FuncAct;
  80. }
  81. /* 获取该实例的功能 */
  82. AppFunction FuncBase::getApp()
  83. {
  84. return m_funcThreadInfo.appFunction;
  85. }
  86. /* 获取线程运行状态 */
  87. bool FuncBase::getThreadRunning() const
  88. {
  89. return m_bRunning;
  90. }
  91. /* 初始化数据接口 */
  92. bool FuncBase::initDataInterface()
  93. {
  94. /* 初始化WebAPI */
  95. if(!m_fromWebAPI->initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType()))
  96. {
  97. SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化WebAPI失败, 退出线程", m_baseLog);
  98. return false;
  99. }else {
  100. SPDLOG_LOGGER_INFO(m_logger, "{} 初始化WebAPI成功", m_baseLog);
  101. }
  102. /* 初始化Redis */
  103. m_fromRedis->setRedisIPAndPort(GConfig.redisIP(), GConfig.redisPort());
  104. m_fromRedis->setRedisPassword(GConfig.redisPWD());
  105. if(!m_fromRedis->connectRedis())
  106. {
  107. SPDLOG_LOGGER_ERROR(m_logger, "{} 连接Redis失败, 退出线程", m_baseLog);
  108. return false;
  109. }else {
  110. SPDLOG_LOGGER_INFO(m_logger, "{} 连接Redis成功", m_baseLog);
  111. }
  112. return true;
  113. }
  114. /* 读取Redis数据 */
  115. void FuncBase::readRedisData(ListAlarmInfo& listAlarmInfo)
  116. {
  117. /* 清空报警信息 */
  118. listAlarmInfo.clearAlarmInfo();
  119. for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
  120. {
  121. for(const auto& it : roomInfo.mapCameraAction)
  122. {
  123. for(const auto& act : it.second)
  124. {
  125. std::string strKey = std::to_string(it.first) + ":" + act;
  126. std::string strRetValue;
  127. if(!m_fromRedis->getRedisString(strKey, strRetValue))
  128. {
  129. SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey);
  130. continue;
  131. }
  132. /* 解析数据 */
  133. AlarmInfo newAlarmInfo;
  134. newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
  135. newAlarmInfo.RoomID = roomInfo.RoomID;
  136. newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
  137. newAlarmInfo.ActionID = act;
  138. parseRedisBaseData(strRetValue, newAlarmInfo);
  139. parseOtherDataPersonCount(strRetValue, newAlarmInfo);
  140. /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
  141. if(!isEventTimeVaild(newAlarmInfo.EventTime))
  142. {
  143. SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
  144. m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString());
  145. continue;
  146. }
  147. listAlarmInfo.addAlarmInfo(newAlarmInfo);
  148. printRawDataInfo(roomInfo, strKey, newAlarmInfo);
  149. }
  150. }
  151. }
  152. }
  153. /* 更新检测时间范围,一定时间更新一次,不是每次都更新 */
  154. bool FuncBase::updateDetectTime(DetectPeriodInfo& periodInfo)
  155. {
  156. /* 从数据库获取监测时间,10秒钟获取一次 */
  157. if(periodInfo.lastTime.secsTo(m_nowTime) > 10)
  158. {
  159. periodInfo.lastTime = m_nowTime;
  160. /* 获取监测时间 */
  161. if(!m_fromWebAPI->getFuncDetectTime(m_funcThreadInfo.ChannelID, m_funcThreadInfo.appFunction, m_periodInfo))
  162. {
  163. SPDLOG_LOGGER_ERROR(m_logger, "{} 获取检测时间失败", m_baseLog);
  164. return false;
  165. }
  166. }
  167. return true;
  168. }
  169. /* 判断是否在检测时间内,重载版,会自动打印日志 */
  170. bool FuncBase::isInDetectTime(const DetectPeriodInfo& periodInfo)
  171. {
  172. /* 刷新当前时间 */
  173. m_nowTime = QDateTime::currentDateTime();
  174. /* 先更新检测时间段 */
  175. if(!updateDetectTime(m_periodInfo))
  176. {
  177. return false;
  178. }
  179. /* 判断是按照天还是按周执行 */
  180. if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_ALL)
  181. {
  182. /* 所有时段都可以检测 */
  183. return true;
  184. }
  185. else if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_DAY)
  186. {
  187. /* 按天检测 */
  188. QTime st = periodInfo.listWeekTime.front().StartTime.time();
  189. QTime et = periodInfo.listWeekTime.front().EndTime.time();
  190. if(st.isValid() && et.isValid())
  191. {
  192. if(m_nowTime.time() >= st && m_nowTime.time() <= et)
  193. {
  194. return true;
  195. }
  196. }
  197. }
  198. else if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_WEEK)
  199. {
  200. /* 按周检测 */
  201. for(const auto& it : periodInfo.listWeekTime)
  202. {
  203. /* 其他星期几 */
  204. if(it.WeekDay == m_nowTime.date().dayOfWeek())
  205. {
  206. if(it.StartTime.time() <= m_nowTime.time() && it.EndTime.time() >= m_nowTime.time())
  207. {
  208. return true;
  209. }
  210. }
  211. }
  212. }
  213. /* 拼接时间段,如果时按周计算,会有好多个时间段 */
  214. std::string dectectTime = "检测时间: ";
  215. if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_WEEK)
  216. {
  217. dectectTime += fmt::format("按周检测\n");
  218. for(const auto& it : periodInfo.listWeekTime)
  219. {
  220. dectectTime += fmt::format("{} [{} - {}] \n", getWeekDayString(it.WeekDay), it.StartTime.toString("hh:mm:ss").toStdString(),
  221. it.EndTime.toString("hh:mm:ss").toStdString());
  222. }
  223. }
  224. else if(Enum_PeriodType::PERIOD_DAY == periodInfo.PeriodType)
  225. {
  226. dectectTime += fmt::format("按天检测 [{} - {}]", periodInfo.listWeekTime.front().StartTime.toString("hh:mm:ss").toStdString(),
  227. periodInfo.listWeekTime.front().EndTime.toString("hh:mm:ss").toStdString());
  228. }
  229. // SPDLOG_LOGGER_DEBUG(m_logger, "{} 不在检测时间段内, {}", m_baseLog, dectectTime);
  230. SPDLOG_LOGGER_DEBUG(m_logger, "{} 不在检测时间段内", m_baseLog);
  231. return false;
  232. }
  233. /* 判断报警数据有效时间,超过600秒可能是超脑那边挂了 */
  234. bool FuncBase::isEventTimeVaild(const QDateTime& eventTime)
  235. {
  236. /* 判断时间差 */
  237. qint64 diff = m_nowTime.toSecsSinceEpoch() - eventTime.toSecsSinceEpoch();
  238. if(diff > 600)
  239. {
  240. return false;
  241. }
  242. return true;
  243. }
  244. /* 打印一些原始数据信息 */
  245. void FuncBase::printRawDataInfo(const RoomCamActInfo& roomInfo, const std::string& strKey, const AlarmInfo& alarmInfo)
  246. {
  247. SPDLOG_LOGGER_DEBUG(m_logger, "{:<40} 报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}",
  248. m_baseLog, strKey, roomInfo.RoomID, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(),
  249. alarmInfo.listBbox.size(), alarmInfo.listPersonInfo.size());
  250. }