123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- #include "UniversalFunc.h"
- #include "spdlog/spdlog.h"
- #include "GlobalVariable.h"
- #include "GlobalConfig.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);
- // SPDLOG_DEBUG("解析Redis数据: \n{}", json0.dump(4));
- alarmInfo.AlarmID = json0["alarmId"].get<int>();
- alarmInfo.ActionID = json0["actionId"].get<std::string>();
- alarmInfo.ActionDes = json0["actionDes"].is_null() ? "" : json0["actionDes"].get<std::string>();
- // alarmInfo.ImageInfo = json0["picUrl"].is_null() ? "" : json0["picUrl"].get<std::string>();
- alarmInfo.ImageInfo = json0["imageInfo"].is_null() ? "" : json0["imageInfo"].get<std::string>();
-
- /* 解析时间,需要将时间中的“T”换成空格 */
- std::string startTime = json0["beginTime"].get<std::string>();
- std::replace(startTime.begin(), startTime.end(), 'T', ' ');
- std::string endTime = json0["endTime"].get<std::string>();
- std::replace(endTime.begin(), endTime.end(), 'T', ' ');
- std::string eventTime = json0["eventTime"].get<std::string>();
- std::replace(eventTime.begin(), eventTime.end(), 'T', ' ');
- alarmInfo.StartTime = strToDateTime(startTime);
- alarmInfo.EndTime = strToDateTime(endTime);
- alarmInfo.EventTime = strToDateTime(eventTime);
- }
- 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;
- }
- catch (...)
- {
- SPDLOG_ERROR("解析Redis数据失败,其他错误!");
- 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 JsonBBoxes = json0["bBoxes"] .is_null() ? nJson::array() : json0["bBoxes"];
-
- std::string labelList; /* 记录违禁品 */
- std::list<std::string> listBbox; /* 记录bbox */
- if(!JsonBBoxes.empty())
- {
- for(auto& it0 : JsonBBoxes)
- {
- /* 如果status是true,就不是报警,直接跳过 */
- bool status = it0["status"].get<bool>();
- if(status)
- {
- continue;
- }
- /* 这一条Box数据报警了将其内容存储起来 */
- alarmInfo.Is_Alarm = true;
- /* 解析bbox,在图像中方框的未知 */
- nJson bbox = it0["bbox"].is_null() ? nJson::array() : 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);
- /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
- if(alarmInfo.ActionID == GVariable.ActContraband())
- {
- /* 解析报警,取出报警类型,label是报警说明,如“玩手机的人”
- * 这里主要用于读取违禁品名称 */
- 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;
- }
- }
-
- }
- /* 去掉最后一个“|” */
- if(!labelList.empty())
- {
- labelList.pop_back();
- }
- // SPDLOG_DEBUG("label列表:{}", labelList);
-
- }
- /* 如果有报警的Box,解析出报警的说明 */
- if(alarmInfo.Is_Alarm)
- {
- /* 添加报警信息的提示信息 */
- alarmInfo.listBbox = listBbox;
- /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
- if( (alarmInfo.ActionID == GVariable.ActContraband()) && !labelList.empty() )
- {
- alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
- SPDLOG_DEBUG("{}", alarmInfo.ActionDes);
- }else {
- /* 其他报警信息,直接获取 */
- alarmInfo.ActionDes = json0["actionDes"].get<std::string>();
- }
- /* 判断有没有报警数据 */
- if(alarmInfo.ImageInfo.empty())
- {
- SPDLOG_WARN("有报警区域,但是没有图片信息");
- return;
- }
- /* 如果是人员报警,就存储人员报警信息 */
- if(alarmInfo.ActionID == GVariable.ActFaceIdentify())
- {
- 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.listPersonInfo.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;
- }
- catch (...)
- {
- SPDLOG_ERROR("解析Redis数据失败,其他错误!");
- return;
- }
- }
- /* 解析Redis的其他数据,人员计数版,主要是BBoxes和PersonList */
- bool parseOtherDataPersonCount(const std::string& strData, AlarmInfo& alarmInfo)
- {
- try
- {
- nJson json0;
- json0 = nJson::parse(strData);
- /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
- nJson JsonBBoxes = json0["bBoxes"] .is_null() ? nJson::array() : json0["bBoxes"];
-
- std::list<std::string> listBbox; /* 记录bbox */
- if(JsonBBoxes.empty())
- {
- // SPDLOG_WARN("没有bBoxes数据");
- return false;
- }
- /* 解析bBoxes JSON数组 */
- for(const auto& it0 : JsonBBoxes)
- {
- bool status = it0["status"].get<bool>();
- /* 如果status是true,就不是报警,直接跳过 */
- if(status)
- {
- continue;
- }
- /* 这一条Box数据报警了将其内容存储起来 */
- alarmInfo.Is_Alarm = true;
- /* 解析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);
- }
- /* 如果有报警的Box,解析出报警的说明 */
- if(alarmInfo.Is_Alarm)
- {
- /* 添加报警信息的提示信息 */
- alarmInfo.listBbox = listBbox;
- /* 其他报警信息,直接获取(已经在基础解析中获取了) */
- // alarmInfo.ActionDes = json0["actionDes"].get<std::string>();
-
- /* 判断有没有报警图片 */
- if(alarmInfo.ImageInfo.empty())
- {
- SPDLOG_WARN("有报警区域,但是没有图片信息");
- return false;
- }
- /* 如果是人员报警,就存储人员报警信息 */
- // 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.listPersonInfo.push_back(personInfo);
- // }
- }
- }
- catch (const nJson::parse_error& e)
- {
- SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
- return false;
- }
- catch (const nJson::type_error& e)
- {
- SPDLOG_ERROR("解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
- return false;
- }
- catch (...)
- {
- SPDLOG_ERROR("解析Redis数据失败,其他错误!");
- return false;
- }
- return true;
- }
- /* 将字符串转换成QDateTime */
- QDateTime strToDateTime(const std::string& strTime)
- {
- /* 将字符串转换成QDateTime,带有小数点 */
- QDateTime eventTime = QDateTime::fromString(QString::fromStdString(strTime), "yyyy-MM-dd hh:mm:ss.zzz");
- if(eventTime.isNull())
- {
- /* 尝试不带小数点的格式 */
- eventTime = QDateTime::fromString(QString::fromStdString(strTime), "yyyy-MM-dd hh:mm:ss");
- if(eventTime.isNull())
- {
- SPDLOG_WARN("时间格式错误:{}", strTime);
- return QDateTime::fromString("2000-01-01 00:00:00", "yyyy-MM-dd hh:mm:ss");
- }
- }
- return eventTime;
- }
- /**
- * @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.%z");
- if(iss.fail())
- {
- SPDLOG_WARN("时间格式错误:{}", strTime);
- return false;
- }
- /* 时间差 */
- 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;
- }
- /* 判断redis数据是否长时间没有更新 */
- bool isEventTimeVaild(const QDateTime& nowTime, const std::string& strTime)
- {
- /* 将字符串转换成QDateTime,带有小数点 */
- QDateTime eventTime = QDateTime::fromString(QString::fromStdString(strTime), "yyyy-MM-dd hh:mm:ss.zzz");
- if(eventTime.isNull())
- {
- SPDLOG_WARN("时间格式错误:{}", strTime);
- return false;
- }
- /* 判断时间差 */
- qint64 diff = nowTime.toSecsSinceEpoch() - eventTime.toSecsSinceEpoch();
- if(diff > 600)
- {
- // SPDLOG_WARN("Redis数据长时间没有更新,nowTime: {}, EventTime:{}", nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), 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.zzz");
- 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);
- }
- /* 通过应用ID获取应用名称 */
- std::string getAppFunctionName(const AppFunction appID)
- {
- std::string strRet;
- switch(appID)
- {
- case AppFunction::APP_OnWork:
- strRet = "人员在岗识别";
- break;
- case AppFunction::APP_Contraband:
- strRet = "违禁物品识别";
- break;
- case AppFunction::APP_Illegal:
- strRet = "区域非法入侵检测";
- break;
- case AppFunction::APP_Fatigue:
- strRet = "疲劳检测识别";
- break;
- case AppFunction::APP_Regional:
- strRet = "区域人员统计";
- break;
- case AppFunction::APP_Mouse:
- strRet = "老鼠识别";
- break;
- case AppFunction::APP_PlayPhone:
- strRet = "玩手机识别";
- break;
- case AppFunction::APP_NoMask:
- strRet = "未戴口罩识别";
- break;
- case AppFunction::APP_AllDown:
- strRet = "摔倒识别";
- break;
- default:
- strRet = "未知功能";
- break;
- }
- return strRet;
- }
- /* 获取应用ID在EQM数据库中的编号,按位运算的编号 */
- int getAppFunctionID(const AppFunction appID)
- {
- int nRet = 0;
- switch(appID)
- {
- case AppFunction::APP_OnWork:
- nRet = 0x01;
- break;
- case AppFunction::APP_Contraband:
- nRet = 0x02;
- break;
- case AppFunction::APP_Illegal:
- nRet = 0x04;
- break;
- case AppFunction::APP_Fatigue:
- nRet = 0x08;
- break;
- case AppFunction::APP_Regional:
- nRet = 0x10;
- break;
- case AppFunction::APP_Mouse:
- nRet = 0x20;
- break;
- case AppFunction::APP_PlayPhone:
- nRet = 0x40;
- break;
- case AppFunction::APP_NoMask:
- nRet = 0x80;
- break;
- case AppFunction::APP_AllDown:
- nRet = 0x100;
- break;
- default:
- nRet = 0x00;
- break;
- }
- return nRet;
- }
- /* 根据EQM数据库中的编号,转换成本地的AppID */
- AppFunction getAppFunctionID(int nID)
- {
- AppFunction appID = AppFunction::APP_NONE;
- switch(nID)
- {
- case 0x01:
- appID = AppFunction::APP_OnWork;
- break;
- case 0x02:
- appID = AppFunction::APP_Contraband;
- break;
- case 0x04:
- appID = AppFunction::APP_Illegal;
- break;
- case 0x08:
- appID = AppFunction::APP_Fatigue;
- break;
- case 0x10:
- appID = AppFunction::APP_Regional;
- break;
- case 0x20:
- appID = AppFunction::APP_Mouse;
- break;
- case 0x40:
- appID = AppFunction::APP_PlayPhone;
- break;
- case 0x80:
- appID = AppFunction::APP_NoMask;
- break;
- case 0x100:
- appID = AppFunction::APP_AllDown;
- break;
- default:
- appID = AppFunction::APP_NONE;
- break;
- }
- return appID;
- }
- /* 根据数字获取周几字符串,范围1-7 */
- std::string getWeekDayString(int nWeek)
- {
- std::string strRet;
- switch(nWeek)
- {
- case 1:
- strRet = "周一";
- break;
- case 2:
- strRet = "周二";
- break;
- case 3:
- strRet = "周三";
- break;
- case 4:
- strRet = "周四";
- break;
- case 5:
- strRet = "周五";
- break;
- case 6:
- strRet = "周六";
- break;
- case 7:
- strRet = "周日";
- break;
- default:
- strRet = "未知";
- break;
- }
- return strRet;
- }
|