Prechádzať zdrojové kódy

V0.2.1
1、添加了配置文件相关功能
2、添加了写入报警信息数据库的功能
3、梳理了人员在岗、直播间离岗在岗等算法功能

Apple 6 mesiacov pred
rodič
commit
5f06302a13

+ 46 - 10
SecurePlayAuxServer/GlobalInfo/GlobalInfo.cpp

@@ -2,6 +2,8 @@
 
 #include <QSettings>
 
+#include "spdlog/spdlog.h"
+
 /* ====================================================================================
  * *******************************    全局变量定义    **********************************
  * ====================================================================================*/
@@ -316,6 +318,9 @@ RoomActionInfo* ListRoomActionInfo::findActionIDInList(const int chnID, const in
  * **************************    GlobalConfig成员函数    ******************************
  * ====================================================================================*/
 
+/* 创建实例 */
+GlobalConfig g_config;
+
 GlobalConfig::GlobalConfig()
 {
 
@@ -324,23 +329,54 @@ GlobalConfig::GlobalConfig()
 /* 读取配置文件 */
 bool GlobalConfig::readConfig(const QString& strConfigFile)
 {
+    if(strConfigFile.isEmpty())
+    {
+        SPDLOG_ERROR("读取配置文件失败! 配置文件名为空");
+        return false;
+    }
+    SPDLOG_DEBUG("读取配置文件: {}", strConfigFile.toStdString());
     QSettings settings(strConfigFile, QSettings::IniFormat);
     settings.setIniCodec("UTF-8");
 
-    AppPeopleOnWork = settings.value("APPPEPOLEONWORK").toString().toInt();         /* 离岗时间 */
-    AppBadthing = settings.value("APPBADTHING").toString().toInt();                 /* 违禁物品出现的时间 */
-    AppBadMan = settings.value("APPBADMAN").toString().toInt();                     /* 非法入侵 */
-    AppTired = settings.value("APPTIRED").toString().toInt();                       /* 疲劳检测时间 */
-    AppPeopleCont = settings.value("APPPEOPLECONT").toString().toInt();             /* 人员聚集时间 */
-    AppPlayPhone = settings.value("APPPLAYPHONE").toString().toInt();               /* 玩手机识别 */
-    AppMouse = settings.value("APPMOUSE").toString().toInt();                       /* 手势识别 */
-    AppMask = settings.value("APPMASK").toString().toInt();                         /* 戴口罩识别 */
+    settings.beginGroup("System");
+    AppPeopleOnWork = settings.value("APPPEPOLEONWORK", 300).toInt();         /* 离岗时间 */
+    AppBadthing = settings.value("APPBADTHING", 50).toInt();                 /* 违禁物品出现的时间 */
+    AppBadMan = settings.value("APPBADMAN", 50).toInt();                     /* 非法入侵 */
+    AppTired = settings.value("APPTIRED", 50).toInt();                       /* 疲劳检测时间 */
+    AppPeopleCont = settings.value("APPPEPOLECONT", 50).toInt();             /* 人员聚集时间 */
+    AppPlayPhone = settings.value("APPPLAYPHONE", 50).toInt();               /* 玩手机识别 */
+    AppMouse = settings.value("APPMOUSE", 50).toInt();                       /* 手势识别 */
+    AppMask = settings.value("APPMASK", 5).toInt();                         /* 戴口罩识别 */
 
-    CheckSet = settings.value("CHECKSET").toString().toInt();                       /* 服务端多久检测一次配置 */
-    EventTimeValid = settings.value("EVENTTIMEVALID").toString().toInt();           /* 事件时间有效期 */
+    CheckSet = settings.value("CHECKSET", 300).toInt();                       /* 服务端多久检测一次配置 */
+    EventTimeValid = settings.value("EventTimeValid", 300).toInt();           /* 事件时间有效期 */
 
     Key = settings.value("Key").toString().toStdString();                           /* Key */
     Secret = settings.value("Secret").toString().toStdString();                     /* Secret */
 
+    settings.endGroup();
+
+    if(Key.empty() || Secret.empty())
+    {
+        SPDLOG_ERROR("读取配置文件失败! Key或Secret为空");
+        return false;
+    }
+
     return true;
 }
+
+
+/* 打印读取到的值 */
+void GlobalConfig::printValue()
+{
+    SPDLOG_INFO("APPPEPOLEONWORK:   {}", AppPeopleOnWork);
+    SPDLOG_INFO("APPBADTHING:       {}", AppBadthing);
+    SPDLOG_INFO("APPBADMAN:         {}", AppBadMan);
+    SPDLOG_INFO("APPTIRED:          {}", AppTired);
+    SPDLOG_INFO("APPPEOPLECONT:     {}", AppPeopleCont);
+    SPDLOG_INFO("APPPLAYPHONE:      {}", AppPlayPhone);
+    SPDLOG_INFO("APPMOUSE:          {}", AppMouse);
+    SPDLOG_INFO("APPMASK:           {}", AppMask);
+    SPDLOG_INFO("CHECKSET:          {}", CheckSet);
+    SPDLOG_INFO("EventTimeValid:    {}", EventTimeValid);
+}

+ 26 - 1
SecurePlayAuxServer/GlobalInfo/GlobalInfo.h

@@ -172,6 +172,7 @@ struct AlarmInfo
     
     int RoomID;                 /* 房间ID */
     int ChannelID;              /* 通道ID */
+    int State;                  /* 状态 */
     int OnWork;                 /* 是否在工作 */
     std::string ActionID;       /* 算法ID */
     std::string StartTime;      /* 报警开始时间 */
@@ -183,8 +184,29 @@ struct AlarmInfo
     std::string ActionDes;      /* 算法描述信息 */
     std::string FaceIDList;     /* 人脸ID列表 */
     std::string FaceNameList;   /* 人脸名称列表 */
-    std::string BboxList;       /* Bbox列表,应该图片中的报警位置 */
+    std::string BboxList;       /* Bbox列表,应该图片中的报警位置 */
     std::vector<PersonInfo> vecPersonInfo;    /* 人员信息 */
+
+    AlarmInfo() {
+        Is_Alarm = false;
+        AlarmID = 0;
+        DeviceID = 0;
+        RoomID = 0;
+        ChannelID = 0;
+        State = 0;
+        OnWork = 0;
+        StartTime = "";
+        EndTime = "";
+        EventTime = "";
+        PicUrl = "";
+        ImageInfo = "";
+        AppID = "";
+        ActionID = "";
+        ActionDes = "";
+        FaceIDList = "";
+        FaceNameList = "";
+        BboxList = "";
+    }
 };
 
 
@@ -405,6 +427,8 @@ public:
 
     /* 读取配置文件 */
     bool readConfig(const QString& strConfigFile);
+    /* 打印读取到的值 */
+    void printValue();
     
     int AppPeopleOnWork;        /* 离岗时间 */
     int AppBadthing;            /* 违禁物品出现的时间 */
@@ -422,6 +446,7 @@ public:
     std::string Secret;         /* Secret */
  };
 
+extern GlobalConfig g_config;
 
 
 

+ 205 - 17
SecurePlayAuxServer/SPAServer.cpp

@@ -6,6 +6,7 @@
 // #include "CurlFtp.h"
 #include "ThreadPool/ThreadPool.h"
 
+#include <QApplication>
 #include <QVector>
 
 
@@ -18,6 +19,16 @@ SPAServer::SPAServer()
         return;
     }
 
+    /* 读取全局的配置文件 */
+    QString strConfigFile = QApplication::applicationDirPath() + "/config.ini";
+    if(!g_config.readConfig(strConfigFile))
+    {
+        /* 读取配置文件失败,直接退出程序 */
+        return;
+    }
+    g_config.printValue();
+    
+
     m_threadRunning = true;
     /* 初始化WebAPI */
     m_toEQMDataBase.initWebApi("http://192.1.3.133:31000/v6/", "", "4c2f9fc91c22dd98331e47af2e2964f4");
@@ -46,7 +57,7 @@ void SPAServer::startServer()
     info.vecAction.push_back("OD210_026_005246_001-IZRTKyEx");
     m_keyContraband = "OD210_026_005246_001-IZRTKyEx";
     // CPPTP.add_task(&SPAServer::threadFromRedis, this, info);
-    threadFromRedis(info);
+    // threadFromRedis(info);
 }
 
 
@@ -393,7 +404,10 @@ void SPAServer::threadFromRedis(const CameraThreadInfo& info)
         for(const auto& it : vecKey)
         {
             SPDLOG_LOGGER_INFO(m_logger, "读取Redis信息, Key: {}", it);
-            fromRedis.getRedisString(it, strRetValue);
+            if( !fromRedis.getRedisString(it, strRetValue) )
+            {
+                continue;
+            }
             SPDLOG_LOGGER_TRACE(m_logger, "Redis Value:\n{}", strRetValue);
             /* 解析数据 */
             AlarmInfo alarmInfo;
@@ -543,8 +557,174 @@ void SPAServer::parseRedisData(const std::string& strData, AlarmInfo& alarmInfo)
 
 }
 
+/**
+ * @brief 解析Redis的基础通用数据,不包含bBoxes数组数据
+ * 
+ * @param strData Redis返回的源数据,JSON格式
+ * @param alarmInfo 解析出来的数据
+ */
+void SPAServer::parseRedisBaseData(const std::string& strData, AlarmInfo& alarmInfo)
+{
+    try
+    {
+        nJson json0;
+        json0 = nJson::parse(strData);
+        alarmInfo.AlarmID = json0["alarmId"].get<int>();
+        alarmInfo.ChannelID = json0["channel"].get<int>();
+        alarmInfo.PicUrl = json0["picUrl"].get<std::string>();
+        alarmInfo.ImageInfo = json0["imageInfo"].get<std::string>();
+        
+        /* 解析时间,需要将时间中的“T”换成空格 */
+        alarmInfo.StartTime = json0["beginTime"].get<std::string>();
+        std::replace(alarmInfo.StartTime.begin(), alarmInfo.StartTime.end(), 'T', ' ');
+        alarmInfo.EndTime = json0["endTime"].get<std::string>();
+        std::replace(alarmInfo.EndTime.begin(), alarmInfo.EndTime.end(), 'T', ' ');
+        alarmInfo.EventTime = json0["eventTime"].get<std::string>();
+        std::replace(alarmInfo.EventTime.begin(), alarmInfo.EventTime.end(), 'T', ' ');
+        
+    }
+    catch (const nJson::parse_error& e)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
+        return;
+    }
+    catch (const nJson::type_error& e)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
+        return;
+    }
+}
+
+/**
+ * @brief 解析Redis的bBoxes数据,这个内容可能根据算法ID不同,内容不同
+ * 
+ * @param strData 
+ * @param alarmInfo 
+ */
+void SPAServer::parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo)
+{
+    try
+    {
+        nJson json0;
+        json0 = nJson::parse(strData);
+        /* 判断bBoxes有无数据,有数据就解析,没数据就直接返回了 */
+        nJson json1 = json0["bBoxes"];
+        
+        std::string labelList;              /* 记录违禁品 */
+        std::string bboxList;               /* 记录bbox */
+        if(!json1.empty())
+        {
+            for(auto& it0 : json1)
+            {
+                /* 如果status是true,就不是报警,直接跳过 */
+                bool status = it0["status"].get<bool>();
+                if(status)
+                {
+                    continue;
+                }
+                /* 这一条Box数据报警了将其内容存储起来 */
+                alarmInfo.Is_Alarm = true;
+                /* 解析label,违禁品关键字,先判断这个是不是违禁品检测的算法ID */
+                if(alarmInfo.ActionID == m_keyContraband)
+                {
+                    /* 解析报警,取出报警类型 */
+                    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;
+                    }
+                }
+                /* 解析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();
+                }
+                bboxList += strBbox + "|";
+            }
+            /* 去掉最后一个“|” */
+            if(!labelList.empty())
+            {
+                labelList.pop_back();
+            }
+            if(!bboxList.empty())
+            {
+                bboxList.pop_back();
+            }
+            SPDLOG_LOGGER_DEBUG(m_logger, "违禁品列表:{}", labelList);
+            SPDLOG_LOGGER_DEBUG(m_logger, "bbox列表:{}", bboxList);
+        }
+        
+        /* 如果有报警的Box,解析出报警的说明 */
+        if(alarmInfo.Is_Alarm)
+        {
+            /* 添加报警信息的提示信息 */
+            alarmInfo.BboxList = bboxList;
+            /* 违禁品报警信息,违禁品列表不是空的,就添加补充的文字 */
+            if( (alarmInfo.ActionID == m_keyContraband) && !labelList.empty() )
+            {
+                alarmInfo.ActionDes = fmt::format("出现违禁品[{}]告警", labelList);
+                SPDLOG_LOGGER_INFO(m_logger, "{}", alarmInfo.ActionDes);
+            }else {
+                /* 其他报警信息,直接获取 */
+                alarmInfo.ActionDes = json0["actionDes"].get<std::string>();
+            }
+            /* 判断有没有报警数据 */
+            if(alarmInfo.ImageInfo.empty())
+            {
+                SPDLOG_LOGGER_WARN(m_logger, "有报警区域,但是没有图片信息");
+                return;
+            }
+            /* 如果是人员报警,就存储人员报警信息 */
+            if(alarmInfo.ActionID == m_KeyFace)
+            {
+                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.vecPersonInfo.push_back(personInfo);
+                }
+            }
+        }
+
+        
+    }
+    catch (const nJson::parse_error& e)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
+        return;
+    }
+    catch (const nJson::type_error& e)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger, "解析Redis数据失败:{}, 错误ID:{}", e.what(), e.id);
+        return;
+    }
+
+}
+
 
-/* 判断时间是否长时间没有更新 */
+/**
+ * @brief 判断时间是否长时间没有更新,默认的是600秒,超过这个时间Redis还未更新,可能是超脑挂了
+ * 
+ * @param strTime 
+ * @return true 
+ * @return false 
+ */
 bool SPAServer::isEventTimeVaild(const std::string& strTime)
 {
     /* 获取当前时间 */
@@ -572,8 +752,8 @@ bool SPAServer::isEventTimeVaild(const std::string& strTime)
         2、 将算法信息加入到不同的列表中
             需要多个摄像机配合的加入到m_runListRoomActionInfo列表
             不需要多个摄像机配合的加入到m_runListActionInfo列表
-        3、 每次刷新都会清空算法的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,就会创建新的ActionInfo
-            那么RunState的状态是INIT,需要开启新的线程
+        3、 每次刷新都会清空ActionInfo或者RoomActionInfo的摄像机列表,但是不会动其他基本信息,如果是列表中没有对应的信息,
+            就会创建新的ActionInfo,那么RunState的状态是INIT,需要开启新的线程
             如果刷新完成后,算法对应的摄像机列表为空,那么对应的线程就会停止运行,将RunState设置为STOP,本线程的下一轮
             循环就会删除这个ActionInfo
 
@@ -588,11 +768,12 @@ void SPAServer::threadRoomCamera()
     while (m_threadRunning)
     {
         /* 先获取EQM数据库信息,取出房间和摄像机关联信息 */
-
+        m_mutexActionInfo.lock();
+        toEQMDataBase->getActionInfo(m_listActionInfo);
         /* 取出每个房间的所有算法,int是RoomID,string是Action */
-        std::multimap<int, std::string> mapCameraActionID;
+        // std::multimap<int, std::string> mapCameraActionID;
         m_mutexRunRAI.lock();
-        m_mutexActionInfo.lock();
+        
         /* 先清理已经退出的线程所用到的Action或者RoomAction */
         m_runListRoomActionInfo.clearStopRoomAction();
         m_runListActionInfo.clearStopAction();
@@ -638,7 +819,8 @@ void SPAServer::threadRoomCamera()
                 }
             }
         }
-        /* 这个容器用于不关联的算法信息,每个设备上的每个算法是一个线程 */
+        /* 这个容器用于不关联的算法信息,每个设备上的每个算法是一个线程
+         * ActionInfo.RunState = RUN_STATE_INIT ,就是新增的算法,需要创建新的线程 */
         for(const auto& it0 : m_runListActionInfo.getData())
         {
             /* 违禁物品识别,不需要多个摄像机融合判断,多少个报警都直接上报 */
@@ -694,7 +876,7 @@ bool SPAServer::insertCameraToAction(RoomActionInfo* pRAInfo, std::list<RoomCame
     return true;
 }
 
-/* 更新房间、算法需要的摄像机个数 */
+/* 更新房间、算法需要的摄像机个数,从内存中更新 */
 bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAInfo)
 {
     std::lock_guard<std::mutex> look(m_mutexRunRAI);
@@ -710,7 +892,7 @@ bool SPAServer::updateRoomActionCameraCount(std::shared_ptr<RoomActionInfo> pRAI
     return true;
 }
 
-/* 更新算法的摄像机ID */
+/* 更新算法的摄像机ID,这里是从内存中的数组里获取 */
 bool SPAServer::updateActionCameraID(std::shared_ptr<ActionInfo> pInfo)
 {
     pInfo->CameraID = -1;
@@ -843,10 +1025,13 @@ void SPAServer::threadActPersonNumber(RoomActionInfo* RAInfo)
 }
 
 /**
- * @brief 报警判断条件:机房内出现摄像头的违禁物品识别算法输出结果包含指定违规内容时,记为报警行为,直接
-          展示报警结果
+ * @brief 违禁物品识别
+            报警判断条件:机房内出现摄像头的违禁物品识别算法输出结果包含指定违规内容时,记为报警行为,直接
+            展示报警结果
+            这里应该是不区分违禁物品是什么,只要有违禁物品就报警。如果一个违禁物品消失之前又出现了第二个违禁物品,
+            两个违禁物品都消失后,这次报警才会结束。
  * 
- * @param info 
+ * @param info 线程信息
  */
 void SPAServer::threadActContraband(ActionInfo* info)
 {
@@ -876,7 +1061,8 @@ void SPAServer::threadActContraband(ActionInfo* info)
         }
         /* 解析数据 */
         AlarmInfo alarmInfo;
-        parseRedisData(strRetValue, alarmInfo);
+        parseRedisBaseData(strRetValue, alarmInfo);
+        parseRedisBBoxesData(strRetValue, alarmInfo);
         /* 判断事件的时效性,超过多少秒不更新就可能是超脑挂了 */
         if(isEventTimeVaild(alarmInfo.EventTime))
         {
@@ -884,6 +1070,7 @@ void SPAServer::threadActContraband(ActionInfo* info)
             continue;
         }
         /* 判断有无报警记录,写入到EQM数据库 */
+
     }
     /* 设置线程退出的状态 */
     setThreadState(pActInfo, RunTimeState::RUN_STATE_STOP);
@@ -891,9 +1078,10 @@ void SPAServer::threadActContraband(ActionInfo* info)
 }
 
 /**
- * @brief  1、野猫、宠物识别:报警判断条件:机房内出现摄像头的宠物识别算法输出报警结果时,记为报警行为,直接
+ * @brief 非法入侵检测
+            1、野猫、宠物识别:报警判断条件:机房内出现摄像头的宠物识别算法输出报警结果时,记为报警行为,直接
               展示报警结果
-           2、无权限人员识别:报警判断条件:当判断出区域非法入侵行为时,依据人脸识别结果,判断是否为人脸库人
+            2、无权限人员识别:报警判断条件:当判断出区域非法入侵行为时,依据人脸识别结果,判断是否为人脸库人
               员,非人脸库的人员时判断为非法入侵行为(背影需要报警需要结合区域人员检测算法判断)
  * 
  * @param info 

+ 6 - 0
SecurePlayAuxServer/SPAServer.h

@@ -7,6 +7,7 @@
 
 /**
  * 安播辅助提示系统服务类
+ *      写入EQM数据库的报警逻辑
  * 
  */
 class SPAServer
@@ -32,8 +33,13 @@ private:
 
     /* 从Redis获取数据线程函数,这个是摄像机线程 */
     void threadFromRedis(const CameraThreadInfo& info);
+
     /* 解析Redis基础数据 */
     void parseRedisData(const std::string& strData, AlarmInfo& alarmInfo);
+    /* 解析Redis的基础通用数据,不包含bBoxes数组数据 */
+    void parseRedisBaseData(const std::string& strData, AlarmInfo& alarmInfo);
+    /* 解析Redis的bBoxes数据, */
+    void parseRedisBBoxesData(const std::string& strData, AlarmInfo& alarmInfo);
     /* 判断时间是否长时间没有更新 */
     bool isEventTimeVaild(const std::string& strTime);
 

+ 1 - 1
SecurePlayAuxServer/communication/FromRedis.cpp

@@ -91,7 +91,7 @@ bool FromRedis::getRedisString(const std::string& key, std::string& value)
     }
     if(reply->type != REDIS_REPLY_STRING)
     {
-        FMTLOG_ERROR( "Get redis data failed, type is not string, type: {}, error str: {}", reply->type, reply->str);
+        FMTLOG_ERROR( "Get redis data failed, type is not string, type: {}", reply->type);
         freeReplyObject(reply);
         return false;
     }

+ 42 - 0
SecurePlayAuxServer/communication/ToEQMDataBase.cpp

@@ -801,3 +801,45 @@ bool ToEQMDataBase::getRoomCameraInfo(std::list<RoomCameraInfo>& vecInfo)
 }
 
 
+/* 写入报警信息 */
+bool ToEQMDataBase::insertAlarmInfo(const AlarmInfo& alarmInfo)
+{
+    if(m_httpApi == nullptr)
+    {
+        SPDLOG_LOGGER_ERROR(m_logger,"WebApi is nullptr");
+        return false;
+    }
+    nJson json0;
+    json0["opName"] = "SPSS_InsertToAlarmInfo";
+    nJson json1;
+    json1["AlarmID"] = alarmInfo.AlarmID;
+    json1["StartTime"] = alarmInfo.StartTime;
+    json1["CreateTime"] = alarmInfo.EventTime;
+    json1["EndTime"] = alarmInfo.EndTime;
+    json1["bBox"] = alarmInfo.BboxList;
+    json1["PicUrl"] = alarmInfo.PicUrl;
+    json1["AppID"] = alarmInfo.AppID;
+    json1["ActionID"] = alarmInfo.ActionID;
+    json1["ActionDes"] = alarmInfo.ActionDes;
+    json1["CamerID"] = alarmInfo.DeviceID;
+    json1["RoomID"] = alarmInfo.RoomID;
+    json1["chnID"] = alarmInfo.ChannelID;
+    json1["Stat"] = alarmInfo.State;
+    json0["FaceIDList"] = alarmInfo.FaceIDList;
+    json0["FaceNameList"] = alarmInfo.FaceNameList;
+    json0["OnWork"] = alarmInfo.OnWork;
+
+    json0["paramList"] = json1;
+    QString strCmd = QString::fromStdString(json0.dump());
+    QString strRet;
+    auto ret = m_httpApi->DBQDoInterface(enDBOperatorType::EDBOT_Insert, strCmd, strRet);
+    if(ret < 0)
+    {
+        SPDLOG_LOGGER_DEBUG(m_logger,"插入报警信息失败:{}, 错误信息:{}",ret,m_httpApi->DoGetLastError(&ret).toStdString());
+        return false;
+    }
+    SPDLOG_LOGGER_DEBUG(m_logger,"插入报警信息成功!");
+
+    return true;
+}
+

+ 3 - 0
SecurePlayAuxServer/communication/ToEQMDataBase.h

@@ -44,6 +44,9 @@ public:
 
     /* 获取摄像机和房间关联信息 */
     bool getRoomCameraInfo(std::list<RoomCameraInfo>& vecInfo);
+
+    /* 写入报警信息 */
+    bool insertAlarmInfo(const AlarmInfo& alarmInfo);
     
 
 private:

+ 2 - 2
SecurePlayAuxServer/main.cpp

@@ -30,9 +30,9 @@ int main(int argc, char* argv[])
     CPPTP.setThreadMaxNum(256);
 
     SPAServer server;
-    server.startServer();
+    // server.startServer();
 
-    return app.exec();
+    // return app.exec();
 }
 
 

+ 2 - 0
json.json

@@ -367,6 +367,7 @@
   "taskId": 1,
   "taskName": "1"
 }
+
 /* 117数据,应该和要读取的一样 */
 {
   "actionDes": "",
@@ -558,6 +559,7 @@
     }
   ]
 }
+
 /* 图片识别 */
 {
   "code": 0,

+ 12 - 0
安播辅助服务程序说明.md

@@ -121,3 +121,15 @@
 1. 逻辑详情见[安播辅助提示系统需求文档](https://alidocs.dingtalk.com/i/nodes/20eMKjyp81pbx3nQUAEOAlnGJxAZB1Gv?utm_scene=person_space)
 2. 这里不在是一个摄像机一个线程了,而是根据任务分配线程,如违禁物品每个摄像机对应的Action都可以检测,那么每个Redis Key就是一个线程;检测人员在岗需要房间内的多个摄像机联合起来判断,那么这个房间内的整个摄像机都是对应的Action都在一个线程中。
 
+## 报警算法逻辑
+### 写入EQM数据库报警信息
+1. 出现报警时会创建一条报警信息,直接写入到数据库,只有开始时间
+2. 根据设置的规定时间继续检测(如违禁品出现10秒才算报警,防止误报警),在规定时间内报警消失,就删除这次报警信息
+3. 超过了规定时间,报警消失,更新开始创建的那条信息的结束时间
+
+
+### 人员在岗信息
+1. 人员在岗主要是给客户端实时信息
+2. 创建一个最新的记录在`tWorkOnInfo`表中,不断地更新这条数据的人数和人员信息
+3. 如果所有人都离岗了,这条信息的人数就清零
+4. 最新的在岗信息清零后,人员回来,就重新创建一条新的数据