123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666 |
- #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 <string>
- PersonCountRuleInfo::PersonCountRuleInfo()
- {
- 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;
- }
- EndAlarmParam::EndAlarmParam()
- {
- ChannelID = -1;
- AppID = AppFunction::APP_NONE;
- CameraID = -1;
- insertAlarmNum = 0;
- }
- EndAlarmParam::EndAlarmParam(const EndAlarmParam& other)
- {
- ChannelID = other.ChannelID;
- AppID = other.AppID;
- CameraID = other.CameraID;
- insertAlarmNum = other.insertAlarmNum;
- }
- EndAlarmParam& EndAlarmParam::operator=(const EndAlarmParam& other)
- {
- if(this != &other)
- {
- ChannelID = other.ChannelID;
- AppID = other.AppID;
- CameraID = other.CameraID;
- insertAlarmNum = other.insertAlarmNum;
- }
- return *this;
- }
- bool EndAlarmParam::operator==(const EndAlarmParam& other)
- {
- if(this == &other)
- {
- return true;
- }
- if(ChannelID != other.ChannelID)
- {
- return false;
- }
- if(AppID != other.AppID)
- {
- return false;
- }
- if(CameraID != other.CameraID)
- {
- return false;
- }
- if(insertAlarmNum != other.insertAlarmNum)
- {
- return false;
- }
- return true;
- }
- RoomPeopleInfo::RoomPeopleInfo()
- {
- RoomID = -1;
- RoomType = Enum_RoomType::ROOM_NONE;
- RoomName = "";
- MaxNum = 0;
- imagePath = "";
- }
- RoomPeopleInfo::RoomPeopleInfo(const RoomPeopleInfo& other)
- {
- RoomID = other.RoomID;
- RoomType = other.RoomType;
- RoomName = other.RoomName;
- MaxNum = other.MaxNum;
- imagePath = other.imagePath;
- }
- RoomPeopleInfo& RoomPeopleInfo::operator=(const RoomPeopleInfo& other)
- {
- if (this != &other) {
- RoomID = other.RoomID;
- RoomType = other.RoomType;
- RoomName = other.RoomName;
- MaxNum = other.MaxNum;
- imagePath = other.imagePath;
- }
- 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;
- }
- m_pListAlarm = new ListAlarmInfo();
- if(m_pListAlarm == nullptr)
- {
- SPDLOG_ERROR("FuncRegionalPersonDetection m_pListAlarm is nullptr");
- return;
- }
- }
- FuncRegionalPersonCount::~FuncRegionalPersonCount()
- {
- if(m_pListAlarm != nullptr)
- {
- delete m_pListAlarm;
- m_pListAlarm = nullptr;
- }
- }
- void FuncRegionalPersonCount::task()
- {
- /* 初始化WebAPI和Redis */
- if(!initDataInterface())
- {
- SPDLOG_LOGGER_ERROR(m_logger, "{} 初始化数据接口失败", m_baseLog);
- return;
- }
- 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(m_personCountRule))
- {
- /* 判断报警是否已经结束,没有结束就结束报警 */
- autoEndAlarm();
- continue;
- }
- /* 更新房间列表 */
- updateRoomList();
- if(m_listRoomCamAct.empty())
- {
- SPDLOG_LOGGER_ERROR(m_logger, "★ 频道[{}][{}],{},房间列表为空",
- m_funcThreadInfo.ChannelID, m_funcThreadInfo.strChannelName,
- getAppFunctionName(m_funcThreadInfo.appFunction));
- /* 判断报警是否已经结束,没有结束就结束报警 */
- autoEndAlarm();
- continue;
- }
-
- /* -----------------------------------------------------------------------
- * 读取Redis数据
- * ----------------------------------------------------------------------- */
- m_pListAlarm->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 alarmInfo;
- parseRedisBaseData(strRetValue, alarmInfo);
- parseOtherDataPersonCount(strRetValue, alarmInfo);
- /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
- if(!isEventTimeVaild(m_nowTime, alarmInfo.EventTime))
- {
- SPDLOG_LOGGER_WARN(m_logger, "Redis Key:{} 数据长时间没有更新,nowTime: {}, EventTime:{}",strKey,
- m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString(), alarmInfo.EventTime);
- continue;
- }
- m_pListAlarm->addAlarmInfo(alarmInfo);
- }
- }
- }
- /************ 挨个房间检测人数,取出每个房间内人数的最大值 ************/
- for(const auto& RoomInfo : m_listRoomCamAct)
- {
- /* 取出房间内的最大值 */
- RoomPeopleInfo peopleInfo;
- peopleInfo.RoomID = RoomInfo.RoomID;
- peopleInfo.RoomType = RoomInfo.RoomType;
- peopleInfo.RoomName = RoomInfo.strRoomName;
- /* 获取该房间内最大人数 */
- getRoomMaxNum(RoomInfo.RoomID, peopleInfo.MaxNum, peopleInfo.imagePath);
- m_mapRoomPeople.insert(std::make_pair(RoomInfo.RoomID, peopleInfo));
- }
-
- /************ 单独判断每个房间内人数的最大值和最小值 ************/
- for(const auto& it : m_mapRoomPeople)
- {
- /* 处理房间内的人数最大值 */
- handleRoomMaxNum(it.second);
- }
- /************ 检测频率直播间 + 导播间房间的人数 ************/
- }
- }
- /* 获取该频率的人员计数规则 */
- bool FuncRegionalPersonCount::getPersonCountRuleInfo(PersonCountRuleInfo& personCountRuleInfo)
- {
- std::list<PersonCountRuleInfo> 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;
- }
- /* 获取这个频率的报警信息 */
- m_personCountRule.ChannelID = -1;
- for(auto& it : listRule)
- {
- if(it.ChannelID == m_funcThreadInfo.ChannelID)
- {
- m_personCountRule = it;
- break;
- }
- }
- if(m_personCountRule.ChannelID == -1)
- {
- SPDLOG_LOGGER_ERROR(m_logger, "频率:{}《人员计数》无报警规则", m_funcThreadInfo.ChannelID);
- return false;
- }
- return true;
- }
- /* 判断是否在检测时间段内 */
- // bool FuncRegionalPersonCount::isInPeriodTime()
- // {
- // /* 所有时段 */
- // if(m_personCountRule.RuleType == Enum_PeriodType::PERIOD_ALL)
- // {
- // return true;
- // }
- // /* 按天检测 */
- // else if(m_personCountRule.RuleType == Enum_PeriodType::PERIOD_DAY)
- // {
- // if(m_personCountRule.StartTime <= m_nowTime && m_personCountRule.EndTime >= m_nowTime)
- // {
- // /* 在检测时间内 */
- // return true;
- // } else {
- // /* 不在检测时间内 */
- // return false;
- // }
- // }
- // /* 按周检测 */
- // else if (m_personCountRule.RuleType == Enum_PeriodType::PERIOD_WEEK)
- // {
- // if(m_personCountRule.week != m_nowTime.date().dayOfWeek())
- // {
- // /* 一周日期不相等 */
- // return false;
- // }
- // /* 判断周日期是否相等 */
- // if(m_personCountRule.StartTime.time() <= m_nowTime.time() && m_personCountRule.EndTime.time() >= m_nowTime.time())
- // {
- // return true;
- // } else {
- // /* 不在检测时间内 */
- // 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()
- {
- EndAlarmParam alarmParam;
- alarmParam.ChannelID = m_funcThreadInfo.ChannelID;
- alarmParam.AppID = m_funcThreadInfo.appFunction;
- /* 判断报警是否已经结束,没有结束就结束报警 */
- if(findAlarmEnd(alarmParam))
- {
- SPDLOG_LOGGER_DEBUG(m_logger, "频率:{}《人员计数》报警已经结束", m_funcThreadInfo.strChannelName);
- return;
- }
- if(!m_fromWebAPI->endPersonCountAlarm(alarmParam))
- {
- SPDLOG_LOGGER_ERROR(m_logger, "频率:{}《人员计数》结束报警失败", m_funcThreadInfo.strChannelName);
- return;
- }
- /* 记录已经结束报警的信息,限制一下记录列表的大小 */
- if(m_listEndAlarmPara.size() > 1024)
- {
- m_listEndAlarmPara.clear();
- }
- m_listEndAlarmPara.push_back(alarmParam);
-
- }
- /* 查找是否已经结束了报警 */
- bool FuncRegionalPersonCount::findAlarmEnd(EndAlarmParam& alarmParam)
- {
- if(m_listEndAlarmPara.empty())
- {
- return false;
- }
- for(auto& it : m_listEndAlarmPara)
- {
- if(it == alarmParam)
- {
- return true;
- }
- }
- return false;
- }
- /* 取出一个房间内的最大人数 */
- bool FuncRegionalPersonCount::getRoomMaxNum(int roomID, int& maxNum, std::string& strImagePath)
- {
- strImagePath.clear();
- for(auto it : m_pListAlarm->listAlarmInfo)
- {
- if(it->RoomID == roomID)
- {
- /* 取出最大人数 */
- int num = it->listPersonInfo.size();
- if(num > maxNum)
- {
- maxNum = num;
- strImagePath = it->ImageInfo;
- }
- if(strImagePath.empty())
- {
- strImagePath = it->ImageInfo;
- }
- }
- }
- 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_ALL)
- {
- 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(!findRoomInfo(peopleInfo.RoomID, roomInfo))
- {
- SPDLOG_LOGGER_ERROR(m_logger, "房间ID:{},房间信息不存在", peopleInfo.RoomID);
- return;
- }
- /* 开启了最大人数的检测,判断是否超过最大人数 */
- if(peopleInfo.MaxNum > maxNum)
- {
- /* 超过了最大人数,判断是否已经加入了内存缓冲区 */
- AlarmBuffer alarmBuffer;
- if(findAlarmBuffer(peopleInfo.RoomID, alarmBuffer))
- {
- /* 更新时间,这里只更新时间吗?最大人数和图片不更新吗? */
- 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.EventTime = m_nowTime.toString("yyyy-MM-dd hh:mm:ss.zzz").toStdString();
- 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;
- }
- /* 将报警信息写入缓存中 */
- alarmBuffer.isMax = true;
- // alarmBuffer.isInsertDB = true;
- 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;
- if(findAlarmBuffer(peopleInfo.RoomID, alarmBuffer))
- {
- /* 已写入数据库,结束报警,但是需要注意,人数少于一定时间后才结束报警,不会立马结束 */
- 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);
- }
- }
- }
- }
- /* 根据房间ID查找报警缓冲区 */
- bool FuncRegionalPersonCount::findAlarmBuffer(int roomID, AlarmBuffer& alarmBuffer)
- {
- if(m_mapAlarmBuffer.empty())
- {
- return false;
- }
- for(auto& it : m_mapAlarmBuffer)
- {
- if(it.first == roomID)
- {
- alarmBuffer = it.second;
- return true;
- }
- }
- return false;
- }
- /* 根据房间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;
- }
|