|
@@ -0,0 +1,223 @@
|
|
|
+#include "UniversalFunc.h"
|
|
|
+
|
|
|
+#include "spdlog/spdlog.h"
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 解析Redis的基础通用数据,不包含bBoxes数组数据
|
|
|
+ *
|
|
|
+ * @param strData Redis返回的源数据,JSON格式
|
|
|
+ * @param alarmInfo 解析出来的数据
|
|
|
+ */
|
|
|
+ void parseRedisBaseData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ nJson json0;
|
|
|
+ json0 = nJson::parse(strData);
|
|
|
+ alarmInfo.AlarmID = json0["alarmId"].get<int>();
|
|
|
+ alarmInfo.ChannelID = json0["channel"].get<int>();
|
|
|
+ alarmInfo.PicUrl = json0["picUrl"].get<std::string>();
|
|
|
+ alarmInfo.ImageInfo = json0["imageInfo"].get<std::string>();
|
|
|
+
|
|
|
+ /* 解析时间,需要将时间中的“T”换成空格 */
|
|
|
+ alarmInfo.StartTime = json0["beginTime"].get<std::string>();
|
|
|
+ std::replace(alarmInfo.StartTime.begin(), alarmInfo.StartTime.end(), 'T', ' ');
|
|
|
+ alarmInfo.EndTime = json0["endTime"].get<std::string>();
|
|
|
+ std::replace(alarmInfo.EndTime.begin(), alarmInfo.EndTime.end(), 'T', ' ');
|
|
|
+ alarmInfo.EventTime = json0["eventTime"].get<std::string>();
|
|
|
+ std::replace(alarmInfo.EventTime.begin(), alarmInfo.EventTime.end(), 'T', ' ');
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (const nJson::parse_error& e)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ catch (const nJson::type_error& e)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief 解析Redis的bBoxes数据,这个内容可能根据算法ID不同,内容不同
|
|
|
+ *
|
|
|
+ * @param strData
|
|
|
+ * @param alarmInfo
|
|
|
+ */
|
|
|
+void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ nJson json0;
|
|
|
+ json0 = nJson::parse(strData);
|
|
|
+ /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
|
|
|
+ nJson json1 = json0["bBoxes"];
|
|
|
+
|
|
|
+ std::string labelList; /* 记录违禁品 */
|
|
|
+ std::list<std::string> listBbox; /* 记录bbox */
|
|
|
+ if(!json1.empty())
|
|
|
+ {
|
|
|
+ for(auto& it0 : json1)
|
|
|
+ {
|
|
|
+ /* 如果status是true,就不是报警,直接跳过 */
|
|
|
+ bool status = it0["status"].get<bool>();
|
|
|
+ if(status)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* 这一条Box数据报警了将其内容存储起来 */
|
|
|
+ alarmInfo.Is_Alarm = true;
|
|
|
+ /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActContraband)
|
|
|
+ {
|
|
|
+ /* 解析报警,取出报警类型 */
|
|
|
+ nJson label = it0["label"];
|
|
|
+ for(auto& it1 : label)
|
|
|
+ {
|
|
|
+ std::string strLabel = it1.get<std::string>();
|
|
|
+ /* 检测是否已经加入到字符串中了 */
|
|
|
+ strLabel += "|";
|
|
|
+ if(labelList.find(strLabel) != std::string::npos)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ labelList += strLabel;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* 解析bbox,貌似是在图像中的位置 */
|
|
|
+ nJson bbox = it0["bbox"];
|
|
|
+ std::string strBbox;
|
|
|
+ for(auto& it1 : bbox)
|
|
|
+ {
|
|
|
+ strBbox += std::to_string(it1.get<int>()) + ",";
|
|
|
+ }
|
|
|
+ /* 去掉最后一个“,” */
|
|
|
+ if(!strBbox.empty())
|
|
|
+ {
|
|
|
+ strBbox.pop_back();
|
|
|
+ }
|
|
|
+ listBbox.push_back(strBbox);
|
|
|
+ }
|
|
|
+ /* 去掉最后一个“|” */
|
|
|
+ if(!labelList.empty())
|
|
|
+ {
|
|
|
+ labelList.pop_back();
|
|
|
+ }
|
|
|
+ SPDLOG_DEBUG("违禁品列表:{}", labelList);
|
|
|
+
|
|
|
+ }
|
|
|
+ /* 如果有报警的Box,解析出报警的说明 */
|
|
|
+ if(alarmInfo.Is_Alarm)
|
|
|
+ {
|
|
|
+ /* 添加报警信息的提示信息 */
|
|
|
+ alarmInfo.listBbox = listBbox;
|
|
|
+ /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
|
|
|
+ if( (alarmInfo.ActionID == g_actionList.ActContraband) && !labelList.empty() )
|
|
|
+ {
|
|
|
+ alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
|
|
|
+ SPDLOG_INFO("{}", alarmInfo.ActionDes);
|
|
|
+ }else {
|
|
|
+ /* 其他报警信息,直接获取 */
|
|
|
+ alarmInfo.ActionDes = json0["actionDes"].get<std::string>();
|
|
|
+ }
|
|
|
+ /* 判断有没有报警数据 */
|
|
|
+ if(alarmInfo.ImageInfo.empty())
|
|
|
+ {
|
|
|
+ SPDLOG_WARN("有报警区域,但是没有图片信息");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* 如果是人员报警,就存储人员报警信息 */
|
|
|
+ if(alarmInfo.ActionID == g_actionList.ActFace)
|
|
|
+ {
|
|
|
+ nJson jsonArray = json0["personList"];
|
|
|
+ for(auto& it : jsonArray)
|
|
|
+ {
|
|
|
+ PersonInfo personInfo;
|
|
|
+ personInfo.PersonID = it["personId"].get<std::string>();
|
|
|
+ personInfo.PersonName = it["personName"].get<std::string>();
|
|
|
+ alarmInfo.vecPersonInfo.push_back(personInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (const nJson::parse_error& e)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ catch (const nJson::type_error& e)
|
|
|
+ {
|
|
|
+ SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 判断时间是否长时间没有更新,默认的是600秒,超过这个时间Redis还未更新,可能是超脑挂了
|
|
|
+ *
|
|
|
+ * @param strTime
|
|
|
+ * @return true
|
|
|
+ * @return false
|
|
|
+ */
|
|
|
+ bool isEventTimeVaild(const std::string& strTime)
|
|
|
+ {
|
|
|
+ /* 获取当前时间 */
|
|
|
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
|
|
+ /* 字符串转成时间 */
|
|
|
+ std::istringstream iss(strTime);
|
|
|
+ std::tm tmEvent = {};
|
|
|
+ iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
|
|
|
+ /* 时间差 */
|
|
|
+ std::chrono::system_clock::time_point eventTime = std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
|
|
|
+ std::chrono::duration<double> diff = now - eventTime;
|
|
|
+ // SPDLOG_LOGGER_DEBUG(m_logger, "now:{} eventTime: {} 时间差:{}秒",now, eventTime, diff);
|
|
|
+ if(diff.count() > 600)
|
|
|
+ {
|
|
|
+ // SPDLOG_LOGGER_ERROR(m_logger, "Redis数据长时间没有更新,EventTime:{}", strTime);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /* 计算与当前时间的时间差,返回秒 */
|
|
|
+int timeDiffWithNow(const std::string& strTime)
|
|
|
+{
|
|
|
+ auto now = std::chrono::system_clock::now();
|
|
|
+
|
|
|
+ auto eventTime = strTimeToChrono(strTime);
|
|
|
+ std::chrono::duration<double> diff = now - eventTime;
|
|
|
+
|
|
|
+ return diff.count();
|
|
|
+}
|
|
|
+
|
|
|
+/* 字符串时间转换成std::chrono时间点 */
|
|
|
+std::chrono::system_clock::time_point strTimeToChrono(const std::string& strTime)
|
|
|
+{
|
|
|
+ std::istringstream iss(strTime);
|
|
|
+ std::tm tmEvent = {};
|
|
|
+ iss >> std::get_time(&tmEvent, "%Y-%m-%d %H:%M:%S");
|
|
|
+
|
|
|
+ return std::chrono::system_clock::from_time_t(std::mktime(&tmEvent));
|
|
|
+}
|
|
|
+
|
|
|
+/* 时间点转换成字符串 */
|
|
|
+std::string chronoToStrTime(const std::chrono::system_clock::time_point& timePoint)
|
|
|
+{
|
|
|
+ std::time_t time = std::chrono::system_clock::to_time_t(timePoint);
|
|
|
+ std::tm tmEvent = *std::localtime(&time);
|
|
|
+ char buf[64] = {0};
|
|
|
+ std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tmEvent);
|
|
|
+
|
|
|
+ return std::string(buf);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|