123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #include "FuncOrdinary.h"
- #include "GlobalVariable.h"
- #include "FromRedis.h"
- #include "FromWebAPI.h"
- #include "UniversalFunc.h"
- #include "GlobalConfig.h"
- FuncOrdinary::FuncOrdinary()
- {
- m_logger = spdlog::get("SPAServer");
- if(m_logger == nullptr)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "SPAServer logger is nullptr");
- return;
- }
- }
- FuncOrdinary::~FuncOrdinary()
- {
- m_listSrcAlarm.clearAlarmInfo();
- m_listAlarmBuffer.clearAlarmInfo();
- }
- /* 任务线程 */
- void FuncOrdinary::task()
- {
- /* 初始化WebAPI和Redis接口 */
- if(!initDataInterface())
- {
- return;
- }
- /* 保存上次获取时间段的时间 */
- QDateTime lastTime = QDateTime::fromString("2025-05-07 00:00:00", "yyyy-MM-dd hh:mm:ss");
- while (GThreadInfo.getRunning())
- {
- /* 休眠设置的时间 */
- std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS));
- /* 从全局的信息块中更新功能信息,如是否需要退出线程,主要是更新摄像机关联的算法信息 */
- GThreadInfo.updateFuncInfo(m_funcThreadInfo);
- /* 如果线程的运行状态为停止 */
- if(m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP)
- {
- /* 退出线程 */
- break;
- }
- /* 判断是否在检测时间段内 */
- if(!isInDetectTime(m_periodInfo))
- {
- continue;
- }
- // SPDLOG_LOGGER_DEBUG(m_logger, "{} 在检测时间段内", m_baseLog);
- /* ========================= 读取Redis数据 ========================= */
- readRedisData(m_listSrcAlarm);
- // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据成功, 报警数据数目: {}", m_listAlarm.listAlarmInfo.size());
-
- // continue;
- /* ========================= 处理报警数据 ========================= */
- for(auto newAlarm : m_listSrcAlarm.listAlarmInfo)
- {
- /* 找到该报警相关的房间信息 */
- auto roomInfo = m_funcThreadInfo.findRoomInfo(newAlarm->RoomID);
- if(roomInfo.RoomID == -1)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 房间ID: {} 不存在", m_baseLog, newAlarm->RoomID);
- continue;
- }
- /* 创建基础日志信息 */
- std::string tmpBaseLog = fmt::format("{} 房间: {}, 摄像机ID: {}, 算法ID: {}", m_baseLog, roomInfo.strRoomName, newAlarm->DeviceID, newAlarm->ActionID);
- /* -------------------------------------------------------------------------------
- * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
- * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
- * 报警数据的结束时间,并清空pAlarmInfo
- * ------------------------------------------------------------------------------- */
- /* 找出数组中与当前报警ID相同的的报警信息 */
- auto pAlarmInfo = m_listAlarmBuffer.findAlarmInfo(*newAlarm);
- /* 没有找到报警记录,就新建一个 */
- if(pAlarmInfo == nullptr)
- {
- /* 判断这条记录有没有报警,没有就不做任何处理 */
- if(!newAlarm->Is_Alarm)
- {
- // SPDLOG_LOGGER_TRACE(m_logger, "{}, 没有报警,直接跳过", tmpBaseLog);
- continue;
- }
- /* 新记录有报警,新建报警记录 */
- if(newAlarm->Is_Alarm)
- {
- /* 图片不能是空,如果是空的,就不写入数据库,现在是先加入缓存中 */
- if(!newAlarm->ImageInfo.empty())
- {
- /* 违禁品检测,开始时间是事件时间 */
- newAlarm->StartTime = newAlarm->EventTime;
- newAlarm->EndTime = GVariable.nullTime;
- /* 保存新的报警记录 */
- newAlarm->Is_InsertEQM = false;
- m_listAlarmBuffer.addAlarmInfo(*newAlarm);
- SPDLOG_LOGGER_INFO(m_logger, "{} 新的报警,加入到缓存中", tmpBaseLog);
- }else
- {
- SPDLOG_LOGGER_WARN(m_logger, "{}, 有报警区域, 但是没有图片信息", tmpBaseLog);
- }
- }
- } else
- {
- /* 已有报警记录 */
- /* 更新图片信息 */
- if(!newAlarm->ImageInfo.empty())
- {
- pAlarmInfo->ImageInfo = newAlarm->ImageInfo;
- }
- /* 判断这条记录有无报警 */
- if(newAlarm->Is_Alarm)
- {
- /* 正在报警中,检查是否已经写入到数据库中 */
- if(pAlarmInfo->Is_InsertEQM)
- {
- /* 已经写入到数据库中,不做处理 */
- }else
- {
- /* 判断报警时长间隔是否足够 */
- if(!isOutAlarmTimeVaild(*pAlarmInfo))
- {
- /* 不够报警时间,直接进行下一个循环 */
- continue;
- }
- /* 写入到数据库 */
- pAlarmInfo->Is_InsertEQM = false;
- int pkid = 0;
- if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo, pkid))
- {
- pAlarmInfo->Is_InsertEQM = true;
- pAlarmInfo->PKID = pkid;
- }else {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 写入tAlarmInfo报警数据失败! ", tmpBaseLog);
- }
- SPDLOG_LOGGER_INFO(m_logger, "{}, 报警开始,写入数据库", tmpBaseLog);
- }
-
- } else
- {
- /* 报警结束,先判断有无写入数据库,已经写入,直接结束报警
- * 没有写入数据库,判断时长,如果小于设置的最小间隔,可能是误报警
- * 更新数据库结束时间,结束时间是此时电脑时间 */
- pAlarmInfo->EndTime = m_nowTime;
- /* 判断是否已经写入到数据库中 */
- if(pAlarmInfo->Is_InsertEQM)
- {
- /* 已经写入到数据库中,更新结束时间 */
- m_fromWebAPI->endAlarmInfoByPKID(pAlarmInfo->PKID, m_nowTime);
- }else
- {
- /* 判断报警时长间隔是否足够 */
- if(isOutAlarmTimeVaild(*pAlarmInfo))
- {
- /* 时长足够且没有写入到数据库中,写入到数据库中 */
- m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
- }
- }
- SPDLOG_LOGGER_INFO(m_logger, "{} 报警结束", tmpBaseLog);
- /* 从缓存中删除这个报警信息 */
- m_listAlarmBuffer.deleteAlarmInfo(*pAlarmInfo);
- }
- }
- }
- }
- m_listSrcAlarm.clearAlarmInfo();
- m_listAlarmBuffer.clearAlarmInfo();
- }
- /* old处理方法 */
- void FuncOrdinary::oldTask()
- {
- // /* 读取Redis信息,处理数据,第一层循环是根据房间读取,第二个循环是根据房间内的摄像机读取 */
- // for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
- // {
- // for(const auto& it : roomInfo.mapCameraAction)
- // {
- // for(const auto act : it.second)
- // {
- // /* 读取Redis数据 */
- // std::string strKey = std::to_string(it.first) + ":" + act;
- // std::string strRetValue;
- // if(!m_fromRedis->getRedisString(strKey, strRetValue))
- // {
- // SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
- // std::this_thread::sleep_for(std::chrono::milliseconds(10));
- // continue;
- // }
- // /* 解析数据,先设置基础数据 */
- // AlarmInfo newAlarmInfo;
- // newAlarmInfo.ActionID = act;
- // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
- // parseRedisBaseData(strRetValue, newAlarmInfo);
- // parseRedisBBoxesData(strRetValue, newAlarmInfo);
- // /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
- // if(isEventTimeVaild(newAlarmInfo.EventTime))
- // {
- // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime);
- // std::this_thread::sleep_for(std::chrono::milliseconds(100));
- // continue;
- // }
- // /* -------------------------------------------------------------------------------
- // * 判断有无报警记录,新的报警就先创建一个报警信息,写入报警列表,超过报警的最小误报时间后,
- // * 再写入到EQM的tAlarmInfo表中,正在报警的记录就判断和更新,结束报警就更新tAlarmInfo的
- // * 报警数据的结束时间,并清空pAlarmInfo
- // * ------------------------------------------------------------------------------- */
- // /* 找出数组中与当前报警ID相同的的报警信息 */
- // auto pAlarmInfo = m_listAlarm.findAlarmInfo(newAlarmInfo);
- // /* 没有找到报警记录,就新建一个 */
- // if(pAlarmInfo == nullptr)
- // {
- // /* 新记录有报警,新建报警记录 */
- // if(newAlarmInfo.Is_Alarm)
- // {
- // /* 图片不能是空,如果是空的,就不写入数据库 */
- // if(!newAlarmInfo.ImageInfo.empty())
- // {
- // /* 违禁品检测,开始时间是事件时间 */
- // newAlarmInfo.StartTime = newAlarmInfo.EventTime;
- // newAlarmInfo.EndTime = "";
- // /* 保存新的报警记录 */
- // newAlarmInfo.Is_InsertEQM = false;
- // m_listAlarm.addAlarmInfo(newAlarmInfo);
- // }else
- // {
- // SPDLOG_LOGGER_WARN(m_logger, "频道:{}, 房间:{}, 摄像机:{}, 算法:{}, 有报警区域, 但是没有图片信息", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
- // }
- // }
- // }
- // /* 已有报警记录 */
- // else
- // {
- // /* 更新图片信息 */
- // if(!newAlarmInfo.ImageInfo.empty())
- // {
- // pAlarmInfo->ImageInfo = newAlarmInfo.ImageInfo;
- // }
- // /* 判断是否还在报警中 */
- // if(newAlarmInfo.Is_Alarm)
- // {
- // /* 正在报警中,检查是否已经写入到数据库中 */
- // if(pAlarmInfo->Is_InsertEQM)
- // {
- // /* 已经写入到数据库中,不做处理 */
- // }else
- // {
- // /* 判断报警时长间隔是否足够 */
- // if(!isAlarmTimeVaild(*pAlarmInfo))
- // {
- // /* 不够报警时间,直接进行下一个循环 */
- // continue;
- // }
- // /* 写入到数据库 */
- // pAlarmInfo->Is_InsertEQM = false;
- // if(m_fromWebAPI->insertAlarmInfo(*pAlarmInfo))
- // {
- // pAlarmInfo->Is_InsertEQM = true;
- // }else {
- // SPDLOG_LOGGER_ERROR(m_logger, "写入tAlarmInfo报警数据失败, 频率:{}, 房间:{}, 算法:{} ", m_funcThreadInfo.ChannelID, roomInfo.RoomID, act);
- // }
- // }
-
- // } else
- // {
- // /* 报警结束,判断时长,如果小于设置的最小间隔,可能是误报警
- // * 更新数据库结束时间,结束时间是此时电脑时间 */
- // if(isAlarmTimeVaild(*pAlarmInfo))
- // {
- // pAlarmInfo->EndTime = chronoToStrTime(std::chrono::system_clock::now());
- // /* 判断是否已经写入到数据库中 */
- // if(pAlarmInfo->Is_InsertEQM)
- // {
- // /* 已经写入到数据库中,更新结束时间 */
- // m_fromWebAPI->updateAlarmEndTime(*pAlarmInfo);
- // }else {
- // /* 没有写入到数据库中,写入到数据库中 */
- // m_fromWebAPI->insertAlarmInfo(*pAlarmInfo);
- // }
- // SPDLOG_LOGGER_INFO(m_logger, "频率:{}, 房间:{}, 摄像机:{}, 算法:{}, 报警结束", m_funcThreadInfo.ChannelID, roomInfo.RoomID, it.first, act);
- // }
- // /* 删除这个报警信息 */
- // m_listAlarm.deleteAlarmInfo(*pAlarmInfo);
- // }
- // }
- // }
- // }
- // }
- }
- /* 判断报警时长是否符合不同应用的最小间隔 */
- bool FuncOrdinary::isOutAlarmTimeVaild(const AlarmInfo& info)
- {
- int alarmTime = 0;
- /* 违禁品物品 */
- if(info.appFunction == AppFunction::APP_Contraband)
- {
- alarmTime = GVariable.AppContraband_Time;
- }
- /* 玩手机识别 */
- else if(info.appFunction == AppFunction::APP_PlayPhone)
- {
- alarmTime = GVariable.AppPlayPhone;
- }
- /* 老鼠识别 */
- else if(info.appFunction == AppFunction::APP_Mouse)
- {
- alarmTime = GVariable.AppMouse;
- }
- /* 未戴口罩识别 */
- else if(info.appFunction == AppFunction::APP_NoMask)
- {
- alarmTime = GVariable.AppMask;
- }
- /* 疲劳检测 */
- else if(info.appFunction == AppFunction::APP_Fatigue)
- {
- alarmTime = GVariable.AppTired_Time;
- }
- /* 摔倒识别 */
- else if(info.appFunction == AppFunction::APP_AllDown)
- {
- return true;
- }
- if(info.EventTime.secsTo(m_nowTime) < alarmTime)
- {
- return false;
- }
-
- return true;
- }
- /* 读取Redis数据 */
- // void FuncOrdinary::readRedisData(std::list<AlarmInfo>& listAlarmTemp)
- // {
- // listAlarmTemp.clear();
- // /* 读取Redis数据 */
- // for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo)
- // {
- // for(const auto& cam : roomInfo.mapCameraAction)
- // {
- // for(const auto act : cam.second)
- // {
- // /* 读取Redis数据 */
- // std::string strKey = std::to_string(cam.first) + ":" + act;
- // std::string strRetValue;
- // // SPDLOG_LOGGER_DEBUG(m_logger, "读取Redis数据, Key:{}", strKey);
- // if(!m_fromRedis->getRedisString(strKey, strRetValue))
- // {
- // // SPDLOG_LOGGER_ERROR(m_logger, "读取Redis数据失败, Key:{}", strKey);
- // std::this_thread::sleep_for(std::chrono::milliseconds(10));
- // continue;
- // }
- // /* 解析数据,先设置基础数据 */
- // AlarmInfo newAlarmInfo;
- // newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID;
- // newAlarmInfo.appFunction = m_funcThreadInfo.appFunction;
- // newAlarmInfo.RoomID = roomInfo.RoomID;
- // newAlarmInfo.DeviceID = cam.first;
- // newAlarmInfo.ActionID = act;
-
- // parseRedisBaseData(strRetValue, newAlarmInfo);
- // parseRedisBBoxesData(strRetValue, newAlarmInfo);
- // /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
- // if(!isEventTimeVaild(newAlarmInfo.EventTime))
- // {
- // /* 事件时间超过600秒,可能是超脑挂了 */
- // SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,EventTime:{}",strKey, newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString());
- // std::this_thread::sleep_for(std::chrono::milliseconds(100));
- // continue;
- // }
- // listAlarmTemp.push_back(newAlarmInfo);
-
- // printRawDataInfo(roomInfo, strKey, newAlarmInfo);
- // }
- // }
- // }
- // }
|