UniversalFunc.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "UniversalFunc.h"
  2. #include "spdlog/spdlog.h"
  3. /**
  4. * @brief 解析Redis的基础通用数据,不包含bBoxes数组数据
  5. *
  6. * @param strData Redis返回的源数据,JSON格式
  7. * @param alarmInfo 解析出来的数据
  8. */
  9. void parseRedisBaseData(const std::string& strData, AlarmInfo& alarmInfo)
  10. {
  11. try
  12. {
  13. nJson json0;
  14. json0 = nJson::parse(strData);
  15. alarmInfo.AlarmID = json0["alarmId"].get<int>();
  16. alarmInfo.ChannelID = json0["channel"].get<int>();
  17. alarmInfo.PicUrl = json0["picUrl"].get<std::string>();
  18. alarmInfo.ImageInfo = json0["imageInfo"].get<std::string>();
  19. /* 解析时间,需要将时间中的“T”换成空格 */
  20. alarmInfo.StartTime = json0["beginTime"].get<std::string>();
  21. std::replace(alarmInfo.StartTime.begin(), alarmInfo.StartTime.end(), 'T', ' ');
  22. alarmInfo.EndTime = json0["endTime"].get<std::string>();
  23. std::replace(alarmInfo.EndTime.begin(), alarmInfo.EndTime.end(), 'T', ' ');
  24. alarmInfo.EventTime = json0["eventTime"].get<std::string>();
  25. std::replace(alarmInfo.EventTime.begin(), alarmInfo.EventTime.end(), 'T', ' ');
  26. }
  27. catch (const nJson::parse_error& e)
  28. {
  29. SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
  30. return;
  31. }
  32. catch (const nJson::type_error& e)
  33. {
  34. SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
  35. return;
  36. }
  37. catch (...)
  38. {
  39. SPDLOG_ERROR("解析Redis数据失败,其他错误!");
  40. return;
  41. }
  42. }
  43. /**
  44. * @brief 解析Redis的bBoxes数据,这个内容可能根据算法ID不同,内容不同
  45. *
  46. * @param strData
  47. * @param alarmInfo
  48. */
  49. void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
  50. {
  51. try
  52. {
  53. nJson json0;
  54. json0 = nJson::parse(strData);
  55. /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
  56. nJson json1 = json0["bBoxes"];
  57. std::string labelList; /* 记录违禁品 */
  58. std::list<std::string> listBbox; /* 记录bbox */
  59. if(!json1.empty())
  60. {
  61. for(auto& it0 : json1)
  62. {
  63. /* 如果status是true,就不是报警,直接跳过 */
  64. bool status = it0["status"].get<bool>();
  65. if(status)
  66. {
  67. continue;
  68. }
  69. /* 这一条Box数据报警了将其内容存储起来 */
  70. alarmInfo.Is_Alarm = true;
  71. /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
  72. if(alarmInfo.ActionID == g_actionList.ActContraband)
  73. {
  74. /* 解析报警,取出报警类型 */
  75. nJson label = it0["label"];
  76. for(auto& it1 : label)
  77. {
  78. std::string strLabel = it1.get<std::string>();
  79. /* 检测是否已经加入到字符串中了 */
  80. strLabel += "|";
  81. if(labelList.find(strLabel) != std::string::npos)
  82. {
  83. continue;
  84. }
  85. labelList += strLabel;
  86. }
  87. }
  88. /* 解析bbox,貌似是在图像中的位置 */
  89. nJson bbox = it0["bbox"];
  90. std::string strBbox;
  91. for(auto& it1 : bbox)
  92. {
  93. strBbox += std::to_string(it1.get<int>()) + ",";
  94. }
  95. /* 去掉最后一个“,” */
  96. if(!strBbox.empty())
  97. {
  98. strBbox.pop_back();
  99. }
  100. listBbox.push_back(strBbox);
  101. }
  102. /* 去掉最后一个“|” */
  103. if(!labelList.empty())
  104. {
  105. labelList.pop_back();
  106. }
  107. SPDLOG_DEBUG("违禁品列表:{}", labelList);
  108. }
  109. /* 如果有报警的Box,解析出报警的说明 */
  110. if(alarmInfo.Is_Alarm)
  111. {
  112. /* 添加报警信息的提示信息 */
  113. alarmInfo.listBbox = listBbox;
  114. /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
  115. if( (alarmInfo.ActionID == g_actionList.ActContraband) && !labelList.empty() )
  116. {
  117. alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
  118. SPDLOG_INFO("{}", alarmInfo.ActionDes);
  119. }else {
  120. /* 其他报警信息,直接获取 */
  121. alarmInfo.ActionDes = json0["actionDes"].get<std::string>();
  122. }
  123. /* 判断有没有报警数据 */
  124. if(alarmInfo.ImageInfo.empty())
  125. {
  126. SPDLOG_WARN("有报警区域,但是没有图片信息");
  127. return;
  128. }
  129. /* 如果是人员报警,就存储人员报警信息 */
  130. if(alarmInfo.ActionID == g_actionList.ActFace)
  131. {
  132. nJson jsonArray = json0["personList"];
  133. for(auto& it : jsonArray)
  134. {
  135. PersonInfo personInfo;
  136. personInfo.PersonID = it["personId"].get<std::string>();
  137. personInfo.PersonName = it["personName"].get<std::string>();
  138. alarmInfo.vecPersonInfo.push_back(personInfo);
  139. }
  140. }
  141. }
  142. }
  143. catch (const nJson::parse_error& e)
  144. {
  145. SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
  146. return;
  147. }
  148. catch (const nJson::type_error& e)
  149. {
  150. SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
  151. return;
  152. }
  153. catch (...)
  154. {
  155. SPDLOG_ERROR("解析Redis数据失败,其他错误!");
  156. return;
  157. }
  158. }
  159. /**
  160. * @brief 判断时间是否长时间没有更新,默认的是600秒,超过这个时间Redis还未更新,可能是超脑挂了
  161. *
  162. * @param strTime
  163. * @return true
  164. * @return false
  165. */
  166. bool isEventTimeVaild(const std::string& strTime)
  167. {
  168. /* 获取当前时间 */
  169. std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
  170. /* 字符串转成时间 */
  171. std::istringstream iss(strTime);
  172. std::tm tmEvent = {};
  173. iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
  174. /* 时间差 */
  175. std::chrono::system_clock::time_point eventTime = std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
  176. std::chrono::duration<double> diff = now - eventTime;
  177. // SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
  178. if(diff.count() > 600)
  179. {
  180. // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
  181. return false;
  182. }
  183. return true;
  184. }
  185. /* 计算与当前时间的时间差,返回秒 */
  186. int timeDiffWithNow(const std::string& strTime)
  187. {
  188. auto now = std::chrono::system_clock::now();
  189. auto eventTime = strTimeToChrono(strTime);
  190. std::chrono::duration<double> diff = now - eventTime;
  191. return diff.count();
  192. }
  193. /* 字符串时间转换成std::chrono时间点 */
  194. std::chrono::system_clock::time_point strTimeToChrono(const std::string& strTime)
  195. {
  196. std::istringstream iss(strTime);
  197. std::tm tmEvent = {};
  198. iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
  199. return std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
  200. }
  201. /* 时间点转换成字符串 */
  202. std::string chronoToStrTime(const std::chrono::system_clock::time_point& timePoint)
  203. {
  204. std::time_t time = std::chrono::system_clock::to_time_t(timePoint);
  205. std::tm tmEvent = *std::localtime(&time);
  206. char buf[64] = {0};
  207. std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tmEvent);
  208. return std::string(buf);
  209. }