#include "FuncRegionalPerson.h" #include "FromWebAPI.h" #include "FromRedis.h" #include "GlobalConfig.h" #include "GlobalVariable.h" #include "UniversalFunc.h" #include "bundled/core.h" #include "spdlog.h" #include PersonCountRuleInfo::PersonCountRuleInfo() { isUpdate = false; noRule = false; ChannelID = -1; // week = 0; // RuleType = Enum_PeriodType::PERIOD_ALL; LiveMinEnable = false; LiveMaxEnable = false; DicMinEnable = false; DicMaxEnable = false; LiveDicMinEnable = false; LiveDicMaxEnable = false; LiveMin = 0; LiveMax = 0; DicMin = 0; DicMax = 0; LiveDicMin = 0; LiveDicMax = 0; RuleName = ""; } PersonCountRuleInfo& PersonCountRuleInfo::operator=(PersonCountRuleInfo& other) { if(this != &other) { ChannelID = other.ChannelID; // week = other.week; // RuleType = other.RuleType; // PeriodName = other.PeriodName; // StartTime = other.StartTime; // EndTime = other.EndTime; LiveMinEnable = other.LiveMinEnable; LiveMaxEnable = other.LiveMaxEnable; DicMinEnable = other.DicMinEnable; DicMaxEnable = other.DicMaxEnable; LiveDicMinEnable = other.LiveDicMinEnable; LiveDicMaxEnable = other.LiveDicMaxEnable; LiveMin = other.LiveMin; LiveMax = other.LiveMax; DicMin = other.DicMin; DicMax = other.DicMax; LiveDicMin = other.LiveDicMin; LiveDicMax = other.LiveDicMax; RuleName = other.RuleName; } return *this; } /* 对比规则需不需要更新 */ bool PersonCountRuleInfo::equals(const PersonCountRuleInfo& other) const { if (ChannelID != other.ChannelID) { return false; } if (LiveMinEnable != other.LiveMinEnable || LiveMaxEnable != other.LiveMaxEnable || DicMinEnable != other.DicMinEnable || DicMaxEnable != other.DicMaxEnable || LiveDicMinEnable != other.LiveDicMinEnable || LiveDicMaxEnable != other.LiveDicMaxEnable) { return false; } if (LiveMin != other.LiveMin || LiveMax != other.LiveMax || DicMin != other.DicMin || DicMax != other.DicMax || LiveDicMin != other.LiveDicMin || LiveDicMax != other.LiveDicMax) { return false; } return true; } RoomPeopleInfo::RoomPeopleInfo() { RoomID = -1; RoomType = Enum_RoomType::ROOM_NONE; RoomName = ""; MaxNum = 0; imagePath = ""; StartTime = GVariable.nullTime; EventTime = GVariable.nullTime; listBbox.clear(); } RoomPeopleInfo::RoomPeopleInfo(const RoomPeopleInfo& other) { RoomID = other.RoomID; RoomType = other.RoomType; RoomName = other.RoomName; MaxNum = other.MaxNum; imagePath = other.imagePath; StartTime = other.StartTime; EventTime = other.EventTime; listBbox = other.listBbox; } RoomPeopleInfo& RoomPeopleInfo::operator=(const RoomPeopleInfo& other) { if (this != &other) { RoomID = other.RoomID; RoomType = other.RoomType; RoomName = other.RoomName; MaxNum = other.MaxNum; imagePath = other.imagePath; StartTime = other.StartTime; EventTime = other.EventTime; listBbox = other.listBbox; } return *this; } AlarmBuffer::AlarmBuffer() { // isMax = false; // isInsertDB = false; ChannelID = -1; RoomID = -1; RoomType = Enum_RoomType::ROOM_NONE; PeopleNum = 0; PKID = 0; AlarmTime = QDateTime(); imagePath = ""; actionDecs = ""; } AlarmBuffer::AlarmBuffer(const AlarmBuffer& other) { // isMax = other.isMax; // isInsertDB = other.isInsertDB; ChannelID = other.ChannelID; RoomID = other.RoomID; RoomType = other.RoomType; PeopleNum = other.PeopleNum; PKID = other.PKID; AlarmTime = other.AlarmTime; imagePath = other.imagePath; actionDecs = other.actionDecs; } AlarmBuffer& AlarmBuffer::operator=(const AlarmBuffer& other) { if (this != &other) { // isMax = other.isMax; // isInsertDB = other.isInsertDB; ChannelID = other.ChannelID; RoomID = other.RoomID; RoomType = other.RoomType; PeopleNum = other.PeopleNum; PKID = other.PKID; AlarmTime = other.AlarmTime; imagePath = other.imagePath; actionDecs = other.actionDecs; } return *this; } FuncRegionalPersonCount::FuncRegionalPersonCount() { m_logger = spdlog::get("SPAServer"); if(m_logger == nullptr) { SPDLOG_ERROR("SPAServer logger is nullptr"); return; } } FuncRegionalPersonCount::~FuncRegionalPersonCount() { m_listSrcAlarm.clearAlarmInfo(); } void FuncRegionalPersonCount::task() { /* 初始化WebAPI和Redis */ if(!initDataInterface()) { SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据接口失败", m_baseLog); return; } /* 先结束之前未结束的报警 */ autoEndAlarm(); while (m_bRunning) { std::this_thread::sleep_for(std::chrono::milliseconds(GVariable.ThreadSleepMS())); /* 更新线程信息,并判断是否需要退出 */ GThreadInfo.updateFuncInfo(m_funcThreadInfo); if( (m_funcThreadInfo.appFunction == AppFunction::APP_NONE) || (m_funcThreadInfo.RunState == RunTimeState::RUN_STATE_STOP) ) { break; } /* 判断是否在检测时间段内 */ if(!isInDetectTime(m_periodInfo)) { /* 判断报警是否已经结束,没有结束就结束报警 */ autoEndAlarm(); continue; } /* 更新报警规则 */ if(!getPersonCountRuleInfo()) { /* 判断是不是无报警规则了 */ if(m_personCountRule.noRule) { SPDLOG_LOGGER_ERROR(m_logger, "{} 没有报警规则,退出功能检测线程", m_baseLog); /* 判断报警是否已经结束,没有结束就结束报警 */ autoEndAlarm(); return; } continue; } if(m_personCountRule.isUpdate) { /* 报警规则更新了,结束报警 */ autoEndAlarm(); } /* 更新房间列表 */ updateRoomList(); if(m_listRoomCamAct.empty()) { SPDLOG_LOGGER_ERROR(m_logger, "★ 频道[{}][{}],{},房间列表为空", m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName, getAppFunctionName(m_funcThreadInfo.appFunction)); /* 判断报警是否已经结束,没有结束就结束报警 */ autoEndAlarm(); continue; } /* ----------------------------------------------------------------------- * 读取Redis数据 * ----------------------------------------------------------------------- */ readRedisData(); // SPDLOG_LOGGER_DEBUG(m_logger, "房间数目: {}, 报警条目数目: {}", m_listRoomCamAct.size(), m_pListAlarm->listAlarmInfo.size()); // SPDLOG_LOGGER_DEBUG(m_logger, "报警人数: {}", m_pListAlarm->listAlarmInfo.front()->listBbox.size()); /************ 挨个房间检测人数,取出每个房间内人数的最大值 ************/ for(const auto& RoomInfo : m_listRoomCamAct) { /* 取出房间内的最大值 */ RoomPeopleInfo peopleInfo; peopleInfo.RoomID = RoomInfo.RoomID; peopleInfo.RoomType = RoomInfo.RoomType; peopleInfo.RoomName = RoomInfo.strRoomName; /* 获取该房间内最大人数 */ getRoomMaxNum(RoomInfo.RoomID, peopleInfo); m_mapRoomPeople.insert(std::make_pair(RoomInfo.RoomID, peopleInfo)); } /************ 单独判断每个房间内人数的最大值和最小值 ************/ for(const auto& it : m_mapRoomPeople) { // SPDLOG_LOGGER_DEBUG(m_logger, "房间:{} 人数: {}", it.second.RoomName, it.second.MaxNum); /* 处理房间内的人数最大值 */ handleRoomMaxNum(it.second); /* 处理房间内人数最小值 */ handleRoomMinNum(it.second); } /************ 检测频率直播间 + 导播间房间的人数 ************/ int liveDicMaxNum = 0; std::string strImagePath = ""; for(const auto& it : m_mapRoomPeople) { /* 直播间 + 导播间 */ if(it.second.RoomType == Enum_RoomType::ROOM_LIVE || it.second.RoomType == Enum_RoomType::ROOM_DIC) { liveDicMaxNum += it.second.MaxNum; strImagePath = it.second.imagePath; } } RoomPeopleInfo liveDicMaxNumInfo; liveDicMaxNumInfo.RoomID = 0; liveDicMaxNumInfo.RoomType = Enum_RoomType::ROOM_LIVEDIC; liveDicMaxNumInfo.MaxNum = liveDicMaxNum; liveDicMaxNumInfo.imagePath = strImagePath; liveDicMaxNumInfo.RoomName = "直播间+导播间"; liveDicMaxNumInfo.StartTime = m_nowTime; liveDicMaxNumInfo.EventTime = m_nowTime; /* 处理直播间+导播间人数最大值 */ handleRoomMaxNum(liveDicMaxNumInfo); handleRoomMinNum(liveDicMaxNumInfo); } } /* 读取Redis数据 */ void FuncRegionalPersonCount::readRedisData() { m_listSrcAlarm.clearAlarmInfo(); for(const auto& roomInfo : m_listRoomCamAct) { 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; } m_listSrcAlarm.addAlarmInfo(newAlarmInfo); printRawDataInfo(roomInfo, strKey, newAlarmInfo); } } } } /* 获取该频率的人员计数规则 */ bool FuncRegionalPersonCount::getPersonCountRuleInfo() { std::list listRule; if(!m_fromWebAPI->getPersonCountRuleInfo(listRule)) { SPDLOG_LOGGER_ERROR(m_logger, "获取《人员计数》报警规则失败"); return false; } if(listRule.size() == 0) { SPDLOG_LOGGER_ERROR(m_logger, "★ 频道[{}][{}],{},未配置人员计数规则", m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName, getAppFunctionName(m_funcThreadInfo.appFunction)); return false; } /* 获取这个频率的报警信息 */ bool isFind = false; m_personCountRule.noRule = false; m_personCountRule.isUpdate = false; for(auto& it : listRule) { if(it.ChannelID == m_funcThreadInfo.ChannelID) { isFind = true; /* 判断规则是否有更新 */ if(!it.equals(m_personCountRule)) { /* 规则有更新 */ m_personCountRule = it; m_personCountRule.isUpdate = true; SPDLOG_LOGGER_INFO(m_logger, "{} 报警规则有更新", m_baseLog); } break; } } if(!isFind) { SPDLOG_LOGGER_ERROR(m_logger, "频率:{}《人员计数》无报警规则", m_funcThreadInfo.ChannelID); m_personCountRule.noRule = true; return false; } return true; } /* 更新房间列表 */ void FuncRegionalPersonCount::updateRoomList() { /* 清空房间列表 */ m_listRoomCamAct.clear(); for(const auto& it : m_funcThreadInfo.listRoomCamActInfo) { /* 只添加直播间和导播间 */ if(it.RoomType == Enum_RoomType::ROOM_LIVE || it.RoomType == Enum_RoomType::ROOM_DIC) { m_listRoomCamAct.push_back(it); } } } /* 自动结束报警 */ void FuncRegionalPersonCount::autoEndAlarm() { /* 判断报警是否已经结束,没有结束就结束报警 */ if(m_mapAlarmBuffer.empty()) { SPDLOG_LOGGER_INFO(m_logger, "{} 报警已经结束", m_baseLog); return; } /* 结束该频率人员计数的所有报警 */ if(!m_fromWebAPI->endPersonCountAlarm(m_funcThreadInfo.ChannelID, m_funcThreadInfo.appFunction)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 结束报警失败", m_baseLog); return; } /* 清空报警列表 */ clearAlarmBufferMap(); SPDLOG_LOGGER_INFO(m_logger, "{} 结束报警,已清空报警缓存", m_baseLog); } /* 取出一个房间内的最大人数 */ bool FuncRegionalPersonCount::getRoomMaxNum(int roomID, RoomPeopleInfo& roomInfo) { roomInfo.imagePath.clear(); for(auto it : m_listSrcAlarm.listAlarmInfo) { if(it->RoomID == roomID) { /* 取出最大人数 */ int num = it->listBbox.size(); if(num > roomInfo.MaxNum) { roomInfo.MaxNum = num; roomInfo.imagePath = it->ImageInfo; roomInfo.StartTime = it->StartTime; roomInfo.EventTime = it->EventTime; roomInfo.listBbox = it->listBbox; } if(roomInfo.imagePath.empty()) { roomInfo.imagePath = it->ImageInfo; roomInfo.StartTime = it->StartTime; roomInfo.EventTime = it->EventTime; roomInfo.listBbox = it->listBbox; } } } return true; } /* 处理房间内的人数最大值 */ void FuncRegionalPersonCount::handleRoomMaxNum(const RoomPeopleInfo& peopleInfo) { std::string roomName = ""; int maxNum = 0; /* 判断当前房间是否开启了最大人员检测功能 */ if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVE) { if(!m_personCountRule.LiveMaxEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间最大人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "直播间"; } else { roomName = peopleInfo.RoomName; } maxNum = m_personCountRule.LiveMax; } else if(peopleInfo.RoomType == Enum_RoomType::ROOM_DIC) { if(!m_personCountRule.DicMaxEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 导播间最大人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "导播间"; } else { roomName = peopleInfo.RoomName; } maxNum = m_personCountRule.DicMax; } else if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC) { if(!m_personCountRule.LiveDicMaxEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间+导播间最大人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "直播间+导播间"; } else { roomName = peopleInfo.RoomName; } maxNum = m_personCountRule.LiveDicMax; } else { SPDLOG_LOGGER_WARN(m_logger, "{} 房间类型错误", m_baseLog); return; } /* 查找房间信息 */ RoomCamActInfo roomInfo; if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC) { /* 创造一个摄像机和算法信息 */ std::list listAct; listAct.push_back("0"); roomInfo.mapCameraAction.insert(std::make_pair(0, listAct)); } else { if(!findRoomInfo(peopleInfo.RoomID, roomInfo)) { SPDLOG_LOGGER_ERROR(m_logger, "房间ID:{},房间信息不存在", peopleInfo.RoomID); return; } } /* 开启了最大人数的检测,判断是否超过最大人数 */ if(peopleInfo.MaxNum > maxNum) { /* 超过了最大人数,判断是否已经加入了内存缓冲区 */ AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID); if(alarmBuffer != nullptr) { /* 更新时间,这里只更新时间吗?最大人数和图片不更新吗? */ alarmBuffer->AlarmTime = m_nowTime; }else { /* 没有加入缓冲区,先写入数据库,再加入缓冲区 */ AlarmInfo alarmInfo; alarmInfo.ChannelID = m_funcThreadInfo.ChannelID; alarmInfo.appFunction = m_funcThreadInfo.appFunction; alarmInfo.RoomID = peopleInfo.RoomID; alarmInfo.DeviceID = roomInfo.mapCameraAction.begin()->first; alarmInfo.ImageInfo = peopleInfo.imagePath; alarmInfo.ActionID = roomInfo.mapCameraAction.begin()->second.front(); alarmInfo.StartTime = peopleInfo.StartTime; alarmInfo.EventTime = peopleInfo.EventTime; alarmInfo.listBbox = peopleInfo.listBbox; alarmInfo.Is_Alarm = true; alarmInfo.ActionDes = fmt::format("{}人数为{},已超过最大人数{}限制", roomName, peopleInfo.MaxNum, maxNum); for(auto& it : roomInfo.mapCameraAction) { alarmInfo.listBbox.push_back(GConfig.getCameraName(it.first)); } int pkid = 0; if(!m_fromWebAPI->insertAlarmInfo(alarmInfo, pkid)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 写入报警信息失败", m_baseLog); return; } SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},超过最大人数{},报警开始,已写入数据库", m_baseLog, roomName, maxNum); /* 将报警信息写入缓存中 */ // alarmBuffer.isMax = true; // alarmBuffer.isInsertDB = true; AlarmBuffer* alarmBuffer = new AlarmBuffer(); if(alarmBuffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 创建报警缓冲区失败", m_baseLog); return; } alarmBuffer->ChannelID = m_funcThreadInfo.ChannelID; alarmBuffer->RoomID = peopleInfo.RoomID; alarmBuffer->PKID = pkid; alarmBuffer->RoomType = peopleInfo.RoomType; alarmBuffer->PeopleNum = peopleInfo.MaxNum; alarmBuffer->AlarmTime = m_nowTime; alarmBuffer->imagePath = peopleInfo.imagePath; alarmBuffer->actionDecs = alarmInfo.ActionDes; m_mapAlarmBuffer.insert(std::make_pair(peopleInfo.RoomID, alarmBuffer)); } }else { /* 未超过最大人数,判断是否已经写入的数据库,如果已经写入了数据库,就结束报警 */ AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID); if(alarmBuffer != nullptr) { /* 已写入数据库,结束报警,但是需要注意,人数少于一定时间后才结束报警,不会立马结束 */ if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > GVariable.AppPeopleCount_LessTime) { SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},超过最大人数{},报警结束", m_baseLog, roomName, maxNum); /* 结束报警 */ if(!m_fromWebAPI->endAlarmInfoByPKID(alarmBuffer->PKID, m_nowTime)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 结束超过最大人数报警失败,PKID: {}", m_baseLog, alarmBuffer->PKID); return; } /* 删除报警缓冲区 */ m_mapAlarmBuffer.erase(peopleInfo.RoomID); delete alarmBuffer; alarmBuffer = nullptr; } } } } /* 处理房间内人数最小值 */ void FuncRegionalPersonCount::handleRoomMinNum(const RoomPeopleInfo& peopleInfo) { std::string roomName = ""; int minNum = 0; /* 判断当前房间是否开启了最少人员检测功能 */ if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVE) { if(!m_personCountRule.LiveMinEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间最少人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "直播间"; } else { roomName = peopleInfo.RoomName; } minNum = m_personCountRule.LiveMin; } else if(peopleInfo.RoomType == Enum_RoomType::ROOM_DIC) { if(!m_personCountRule.DicMinEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 导播间最少人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "导播间"; } else { roomName = peopleInfo.RoomName; } minNum = m_personCountRule.DicMin; } else if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC) { if(!m_personCountRule.LiveDicMinEnable) { // SPDLOG_LOGGER_DEBUG(m_logger, "{} 直播间+导播间最少人数检测功能未开启", m_baseLog); return; } /* 判断有没有名称 */ if(peopleInfo.RoomName.empty()) { roomName = "直播间+导播间"; } else { roomName = peopleInfo.RoomName; } minNum = m_personCountRule.LiveDicMin; } else { SPDLOG_LOGGER_WARN(m_logger, "{} 房间类型错误", m_baseLog); return; } /* 查找房间信息 */ RoomCamActInfo roomInfo; if(peopleInfo.RoomType == Enum_RoomType::ROOM_LIVEDIC) { /* 创造一个摄像机和算法信息 */ std::list listAct; listAct.push_back("0"); roomInfo.mapCameraAction.insert(std::make_pair(0, listAct)); } else { if(!findRoomInfo(peopleInfo.RoomID, roomInfo)) { SPDLOG_LOGGER_ERROR(m_logger, "房间ID:{},房间信息不存在", peopleInfo.RoomID); return; } } /* 开启了最小人数的检测,判断是否小于最少人数 如果小于,不会立刻写入数据库,先存储到缓存中,经过一定时间后再写入数据库 */ if(peopleInfo.MaxNum < minNum) { /* 小于最少人数,判断是否已经加入了内存缓冲区 */ AlarmBuffer* alarmBuffer = findAlarmBuffer(peopleInfo.RoomID); if(alarmBuffer != nullptr) { /* 已经存在缓存中了,判断是否已经写入数据库 */ if(alarmBuffer->PKID == 0) { /* 还未写入数据库,判断是否超过时间 */ // if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > 2) if(alarmBuffer->AlarmTime.secsTo(m_nowTime) > GVariable.AppPeopleCount_LessTime) { /* 超过时间,写入数据库 */ AlarmInfo alarmInfo; alarmInfo.ChannelID = m_funcThreadInfo.ChannelID; alarmInfo.appFunction = m_funcThreadInfo.appFunction; alarmInfo.RoomID = peopleInfo.RoomID; alarmInfo.DeviceID = roomInfo.mapCameraAction.begin()->first; alarmInfo.ImageInfo = peopleInfo.imagePath; alarmInfo.ActionID = roomInfo.mapCameraAction.begin()->second.front(); alarmInfo.StartTime = peopleInfo.StartTime; alarmInfo.EventTime = peopleInfo.EventTime; alarmInfo.listBbox = peopleInfo.listBbox; alarmInfo.Is_Alarm = true; alarmInfo.ActionDes = fmt::format("{}人数为{},已低于最小人数{}限制", roomName, peopleInfo.MaxNum, minNum); for(auto& it : roomInfo.mapCameraAction) { alarmInfo.listBbox.push_back(GConfig.getCameraName(it.first)); } int pkid = 0; if(!m_fromWebAPI->insertAlarmInfo(alarmInfo, pkid)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 写入报警信息失败", m_baseLog); return; } SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},已低于最小人数{}限制,已写入数据库", m_baseLog, roomName, peopleInfo.MaxNum, minNum); /* 更新报警缓冲区 */ alarmBuffer->PKID = pkid; } } }else { AlarmBuffer* alarmBuffer = new AlarmBuffer(); if(alarmBuffer == nullptr) { SPDLOG_LOGGER_ERROR(m_logger, "{} 创建报警缓冲区失败", m_baseLog); return; } /* 将报警信息写入缓存中 */ alarmBuffer->ChannelID = m_funcThreadInfo.ChannelID; alarmBuffer->RoomID = peopleInfo.RoomID; alarmBuffer->PKID = 0; alarmBuffer->RoomType = peopleInfo.RoomType; alarmBuffer->PeopleNum = peopleInfo.MaxNum; alarmBuffer->AlarmTime = m_nowTime; alarmBuffer->imagePath = peopleInfo.imagePath; m_mapAlarmBuffer.insert(std::make_pair(peopleInfo.RoomID, alarmBuffer)); SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},已低于最小人数{}限制,已写入缓存", m_baseLog, roomName, peopleInfo.MaxNum, minNum); } }else { /* 不小于最少人数 */ auto alarmBuffer = findAlarmBuffer(peopleInfo.RoomID); if(alarmBuffer != nullptr) { /* 判断是否已经写入数据库 */ if(alarmBuffer->PKID != 0) { /* 已经写入数据库,结束报警 */ if(!m_fromWebAPI->endAlarmInfoByPKID(alarmBuffer->PKID, m_nowTime)) { SPDLOG_LOGGER_ERROR(m_logger, "{} 结束低于最小人数报警失败,PKID: {}", m_baseLog, alarmBuffer->PKID); return; } SPDLOG_LOGGER_INFO(m_logger, "{} 房间: {},人数为{},结束低于最小人数{}报警", m_baseLog, roomName, peopleInfo.MaxNum, minNum); /* 删除报警缓冲区 */ m_mapAlarmBuffer.erase(peopleInfo.RoomID); delete alarmBuffer; alarmBuffer = nullptr; } } } } /* 根据房间ID查找报警缓冲区 */ AlarmBuffer* FuncRegionalPersonCount::findAlarmBuffer(int roomID) { if(m_mapAlarmBuffer.empty()) { return nullptr; } for(auto& it : m_mapAlarmBuffer) { if(it.first == roomID) { return it.second; } } return nullptr; } /* 根据房间ID查找房间信息 */ bool FuncRegionalPersonCount::findRoomInfo(int roomID, RoomCamActInfo& roomInfo) { if(m_listRoomCamAct.empty()) { return false; } for(auto& it : m_listRoomCamAct) { if(it.RoomID == roomID) { roomInfo = it; return true; } } return false; } /* 清空报警列表 */ void FuncRegionalPersonCount::clearAlarmBufferMap() { for(auto& it : m_mapAlarmBuffer) { if(it.second != nullptr) { delete it.second; it.second = nullptr; } } m_mapAlarmBuffer.clear(); }