#include "FuncBase.h" #include "GlobalConfig.h" #include "UniversalFunc.h" #include "FromRedis.h" #include "FromWebAPI.h" FuncBase::FuncBase() { m_fromRedis = std::make_shared(); m_fromWebAPI = std::make_shared(); } FuncBase::~FuncBase() { if(m_fromRedis != nullptr) { m_fromRedis.reset(); m_fromRedis = nullptr; } if(m_fromWebAPI != nullptr) { m_fromWebAPI.reset(); m_fromWebAPI = nullptr; } if(m_logger != nullptr) { m_logger.reset(); m_logger = nullptr; } } /* 任务线程 */ void FuncBase::thread_task() { /* 先做一些通用的初始化 */ if(m_logger == nullptr) { m_logger = spdlog::get("SPAServer"); if(m_logger == nullptr) { SPDLOG_ERROR("SPAServer logger is nullptr"); return; } } /* 线程功能信息 */ if(m_funcThreadInfo.appFunction == AppFunction::APP_NONE) { SPDLOG_LOGGER_ERROR(m_logger, "未设置线程功能信息"); return; } SPDLOG_LOGGER_INFO(m_logger, "---------------------- 开启频道: [{}:{}] “{}”功能 ----------------------", m_funcThreadInfo.strChannelName, m_funcThreadInfo.ChannelID, m_funcThreadInfo.strFunctionName); for(auto& room : m_funcThreadInfo.listRoomCamActInfo) { for(auto& cam : room.mapCameraAction) { for(auto& act : cam.second) { SPDLOG_LOGGER_DEBUG(m_logger, "房间ID: {}, 摄像机ID: {}, 算法ID: {}", room.RoomID, cam.first, act); } } } /* 设置线程的全局运行状态 */ GThreadInfo.setThreadState(m_funcThreadInfo, RunTimeState::RUN_STATE_RUN); /* 设置线程运行状态 */ m_bRunning = true; /* 设置初始化字符串 */ m_baseLog = fmt::format("★ 频道[{}] 功能线程[{}] ", m_funcThreadInfo.strChannelName, m_funcThreadInfo.strFunctionName); /* 执行线程功能,会一直阻塞,直到退出 */ task(); /* 设置线程退出的状态,设置成 RUN_STATE_EXITCOMPLET ,就会被管理线程回收 */ GThreadInfo.setThreadState(m_funcThreadInfo, RunTimeState::RUN_STATE_EXITCOMPLET); SPDLOG_LOGGER_INFO(m_logger, "{} 退出", m_baseLog); m_bRunning = false; } /* 设置功能信息 */ void FuncBase::setFuncThreadInfo(FuncThreadInfo* pFuncAct) { m_funcThreadInfo = *pFuncAct; } void FuncBase::setFuncThreadInfo(FuncThreadInfo& FuncAct) { m_funcThreadInfo = FuncAct; } /* 获取该实例的功能 */ AppFunction FuncBase::getApp() { return m_funcThreadInfo.appFunction; } /* 获取线程运行状态 */ bool FuncBase::getThreadRunning() const { return m_bRunning; } /* 初始化数据接口 */ bool FuncBase::initDataInterface() { /* 初始化WebAPI */ if(!m_fromWebAPI->initWebApi(GConfig.webapiUrl(), GConfig.webapiKey(), GConfig.webapiAppType())) { SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化WebAPI失败, 退出线程", m_baseLog); return false; }else { SPDLOG_LOGGER_INFO(m_logger, "{} 初始化WebAPI成功", m_baseLog); } /* 初始化Redis */ m_fromRedis->setRedisIPAndPort(GConfig.redisIP(), GConfig.redisPort()); m_fromRedis->setRedisPassword(GConfig.redisPWD()); if(!m_fromRedis->connectRedis()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 连接Redis失败, 退出线程", m_baseLog); return false; }else { SPDLOG_LOGGER_INFO(m_logger, "{} 连接Redis成功", m_baseLog); } return true; } /* 读取Redis数据 */ void FuncBase::readRedisData(ListAlarmInfo& listAlarmInfo) { /* 清空报警信息 */ listAlarmInfo.clearAlarmInfo(); for(const auto& roomInfo : m_funcThreadInfo.listRoomCamActInfo) { for(const auto& it : roomInfo.mapCameraAction) { for(const auto& act : it.second) { std::string strKey = std::to_string(it.first) + ":" + act; std::string strRetValue; if(!m_fromRedis->getRedisString(strKey, strRetValue)) { SPDLOG_LOGGER_WARN(m_logger, "读取Redis数据失败, Key: {}", strKey); continue; } /* 解析数据 */ AlarmInfo newAlarmInfo; newAlarmInfo.ChannelID = m_funcThreadInfo.ChannelID; newAlarmInfo.RoomID = roomInfo.RoomID; newAlarmInfo.appFunction = m_funcThreadInfo.appFunction; newAlarmInfo.ActionID = act; parseRedisBaseData(strRetValue, newAlarmInfo); parseOtherDataPersonCount(strRetValue, newAlarmInfo); /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */ if(!isEventTimeVaild(newAlarmInfo.EventTime)) { SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey, m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), newAlarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString()); continue; } listAlarmInfo.addAlarmInfo(newAlarmInfo); printRawDataInfo(roomInfo, strKey, newAlarmInfo); } } } } /* 更新检测时间范围,一定时间更新一次,不是每次都更新 */ bool FuncBase::updateDetectTime(DetectPeriodInfo& periodInfo) { /* 从数据库获取监测时间,10秒钟获取一次 */ if(periodInfo.lastTime.secsTo(m_nowTime) > 10) { periodInfo.lastTime = m_nowTime; /* 获取监测时间 */ if(!m_fromWebAPI->getFuncDetectTime(m_funcThreadInfo.ChannelID, m_funcThreadInfo.appFunction, m_periodInfo)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 获取检测时间失败", m_baseLog); return false; } } return true; } /* 判断是否在检测时间内,重载版,会自动打印日志 */ bool FuncBase::isInDetectTime(const DetectPeriodInfo& periodInfo) { /* 刷新当前时间 */ m_nowTime = QDateTime::currentDateTime(); /* 先更新检测时间段 */ if(!updateDetectTime(m_periodInfo)) { return false; } /* 判断是按照天还是按周执行 */ if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_ALL) { /* 所有时段都可以检测 */ return true; } else if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_DAY) { /* 按天检测 */ QTime st = periodInfo.listWeekTime.front().StartTime.time(); QTime et = periodInfo.listWeekTime.front().EndTime.time(); if(st.isValid() && et.isValid()) { if(m_nowTime.time() >= st && m_nowTime.time() <= et) { return true; } } } else if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_WEEK) { /* 按周检测 */ for(const auto& it : periodInfo.listWeekTime) { /* 其他星期几 */ if(it.WeekDay == m_nowTime.date().dayOfWeek()) { if(it.StartTime.time() <= m_nowTime.time() && it.EndTime.time() >= m_nowTime.time()) { return true; } } } } /* 拼接时间段,如果时按周计算,会有好多个时间段 */ std::string dectectTime = "检测时间: "; if(periodInfo.PeriodType == Enum_PeriodType::PERIOD_WEEK) { dectectTime += fmt::format("按周检测\n"); for(const auto& it : periodInfo.listWeekTime) { dectectTime += fmt::format("{} [{} - {}] \n", getWeekDayString(it.WeekDay), it.StartTime.toString("hh:mm:ss").toStdString(), it.EndTime.toString("hh:mm:ss").toStdString()); } } else if(Enum_PeriodType::PERIOD_DAY == periodInfo.PeriodType) { dectectTime += fmt::format("按天检测 [{} - {}]", periodInfo.listWeekTime.front().StartTime.toString("hh:mm:ss").toStdString(), periodInfo.listWeekTime.front().EndTime.toString("hh:mm:ss").toStdString()); } SPDLOG_LOGGER_DEBUG(m_logger, "{} 不在检测时间段内, {}", m_baseLog, dectectTime); return false; } /* 判断报警数据有效时间,超过600秒可能是超脑那边挂了 */ bool FuncBase::isEventTimeVaild(const QDateTime& eventTime) { /* 判断时间差 */ qint64 diff = m_nowTime.toSecsSinceEpoch() - eventTime.toSecsSinceEpoch(); if(diff > 600) { return false; } return true; } /* 打印一些原始数据信息 */ void FuncBase::printRawDataInfo(const RoomCamActInfo& roomInfo, const std::string& strKey, const AlarmInfo& alarmInfo) { SPDLOG_LOGGER_DEBUG(m_logger, "{:<40} 报警数据: {}, 房间ID: {}, 报警时间: {}, bBox数目: {}, Person数目: {}", m_baseLog, strKey, roomInfo.RoomID, alarmInfo.EventTime.toString("yyyy-MM-dd hh:mm:ss").toStdString(), alarmInfo.listBbox.size(), alarmInfo.listPersonInfo.size()); }