1、增加视频识别辅助检测来车状态功能。

2、修改RFID数据过滤逻辑。
3、修复存储日志的时的路径问题
This commit is contained in:
Mr.V 2024-04-25 17:53:34 +08:00
parent 1093389040
commit 2cdb0c022a
16 changed files with 308 additions and 80 deletions

View File

@ -115,6 +115,10 @@ aux_source_directory(${PROJECT_SRC_ROOT}/engine/SaveResultEngine SaveResultEngin
include_directories(${PROJECT_SRC_ROOT}/engine/SaveRfidEngine)
aux_source_directory(${PROJECT_SRC_ROOT}/engine/SaveRfidEngine SaveRfidEngine_SRC)
# VideoAuxiliaryEngine
include_directories(${PROJECT_SRC_ROOT}/engine/VideoAuxiliaryEngine)
aux_source_directory(${PROJECT_SRC_ROOT}/engine/VideoAuxiliaryEngine VideoAuxiliaryEngine_SRC)
#
include_directories(
@ -182,6 +186,7 @@ file(
${HttpUpResultEngine_SRC}
${SaveResultEngine_SRC}
${SaveRfidEngine_SRC}
${VideoAuxiliaryEngine_SRC}
)
#

View File

@ -39,7 +39,6 @@ namespace ai_matrix
this->baseConfig_.bTestModel = config_["base"]["test_model"].as<bool>();
this->baseConfig_.iConnectType = config_["base"]["connect_type"].as<int>();
this->baseConfig_.bUpResult = config_["base"]["up_result"].as<bool>();
this->baseConfig_.bUseSocketServer = config_["base"]["use_socket_server"].as<bool>();
this->baseConfig_.bHaveMagnetSteel = config_["base"]["have_magnet_steel"].as<bool>();
this->baseConfig_.strMagnetSteelOrder = config_["base"]["magnet_steel_order"].as<std::string>();
this->baseConfig_.strRfidPath = config_["base"]["rfid_path"].as<std::string>();
@ -61,15 +60,11 @@ namespace ai_matrix
this->ethernetConfig_.strIp = config_["ethernet"]["ip"].as<std::string>();
this->ethernetConfig_.iPort = config_["ethernet"]["port"].as<int>();
// ftp服务器参数
this->ftpConfig_.bIsUse = config_["ftp"]["is_use"].as<bool>();
this->ftpConfig_.strType = config_["ftp"]["type"].as<std::string>();
this->ftpConfig_.strIp = config_["ftp"]["ip"].as<std::string>();
this->ftpConfig_.iPort = config_["ftp"]["port"].as<int>();
this->ftpConfig_.strUsername = config_["ftp"]["username"].as<std::string>();
this->ftpConfig_.strPassword = config_["ftp"]["password"].as<std::string>();
this->ftpConfig_.strPath = config_["ftp"]["path"].as<std::string>();
this->ftpConfig_.iQuitTime = config_["ftp"]["quit_time"].as<int>();
// 视频识别辅助来车状态检测
this->videoAuxiliaryConfig_.bUseVideoAuxiliary = config_["video_auxiliary"]["use_video_auxiliary"].as<bool>();
this->videoAuxiliaryConfig_.strIp = config_["video_auxiliary"]["ip"].as<std::string>();
this->videoAuxiliaryConfig_.iPort = config_["video_auxiliary"]["port"].as<int>();
this->videoAuxiliaryConfig_.iDelayedUpload = config_["video_auxiliary"]["delayed_upload"].as<int>();
// http服务器参数
this->httpServerConfig_.bIsUse = config_["http_server"]["is_use"].as<bool>();
@ -214,14 +209,14 @@ namespace ai_matrix
this->ethernetConfig_ = ethernetConfig;
}
FtpConfig Config::getFtpConfig() const
VideoAuxiliaryConfig Config::getVideoAuxiliaryConfig() const
{
return this->ftpConfig_;
return this->videoAuxiliaryConfig_;
}
void Config::setFtpConfig(const FtpConfig ftpConfig)
void Config::setVideoAuxiliaryConfig(const VideoAuxiliaryConfig videoAuxiliaryConfig)
{
this->ftpConfig_ = ftpConfig;
this->videoAuxiliaryConfig_ = videoAuxiliaryConfig;
}
HttpServerConfig Config::getHttpServerConfig() const

View File

@ -31,8 +31,6 @@ namespace ai_matrix
int iConnectType;
// 是否上传识别结果
bool bUpResult;
// 是否使用外部接口辅助开关识别
bool bUseSocketServer;
// 是否存在磁钢
bool bHaveMagnetSteel;
// 火车进厂的磁钢顺序
@ -96,25 +94,17 @@ namespace ai_matrix
std::string strPassword;
};
// FTP服务器参数
struct FtpConfig
// 视频识别辅助来车状态检测
struct VideoAuxiliaryConfig
{
// 使用状态
bool bIsUse;
// 上传方式 [ftp,sftp]
std::string strType;
// 是否使用外部接口辅助开关识别
bool bUseVideoAuxiliary;
// 服务器IP
std::string strIp;
// 服务器端口
// 端口
int iPort;
// 服务器用户名
std::string strUsername;
// 服务器密码
std::string strPassword;
// 上传地址
std::string strPath;
// X秒后自动断开时间
int iQuitTime;
// 延迟上传的节数
int iDelayedUpload;
};
class Config final
@ -153,8 +143,8 @@ namespace ai_matrix
HttpServerConfig getHttpServerConfig() const;
void setHttpServerConfig(const HttpServerConfig httpServerConfig);
// 获取FTP服务器参数
FtpConfig getFtpConfig() const;
void setFtpConfig(const FtpConfig ftpConfig);
VideoAuxiliaryConfig getVideoAuxiliaryConfig() const;
void setVideoAuxiliaryConfig(const VideoAuxiliaryConfig videoAuxiliaryConfig);
YAML::Node config_;
@ -187,7 +177,7 @@ namespace ai_matrix
HttpServerConfig httpServerConfig_;
// ftp服务器参数
FtpConfig ftpConfig_;
VideoAuxiliaryConfig videoAuxiliaryConfig_;
//定义一个嵌套类,负责释放内存,操作系统自动完成,不用担心内存泄露
class GarbageCollector

View File

@ -23,6 +23,7 @@ namespace ai_matrix
}
return ins;
}
/**
*
* inParam : std::string strDirPath :

View File

@ -164,4 +164,8 @@ namespace ai_matrix
}
return false; // 遍历完成未发现非字母数字字符返回false
}
bool StringUtil::is_digits(const std::string &str) {
return all_of(str.begin(), str.end(), ::isdigit);
}
}

View File

@ -10,6 +10,7 @@
#include <mutex>
#include <set>
#include <sstream>
#include <bits/stdc++.h>
namespace ai_matrix
{
@ -37,6 +38,9 @@ namespace ai_matrix
// 判断字符串中是否含有 字母和数字 之外的字符
bool containsNonAlphaNum(const std::string &str);
// 判断字符串中是否仅含有数字
// 检查函数
bool is_digits(const std::string& str);
private:
StringUtil() = default;

View File

@ -105,9 +105,12 @@ int BaseSocket::Read()
int BaseSocket::Monitor()
{
memset(chbuffer, 0x00, sizeof(chbuffer));
chbuffer[0] = 0x30;
int len = send(nSocketId, chbuffer, (sizeof(chbuffer) - 1), 0);
// memset(chbuffer, 0x00, sizeof(chbuffer));
// chbuffer[0] = 0x30;
// int len = send(nSocketId, chbuffer, (sizeof(chbuffer) - 1), 0);
std::string heart = "matrixai";
int len = send(nSocketId, heart.c_str(), (sizeof(heart) - 1), 0);
if(nConnectId < 0 || len == 0) bRun = false;
return len;
}

View File

@ -77,6 +77,13 @@ typedef struct
std::string strNowTime;
} TrainInfo;
typedef struct
{
std::string strComeTime;
int iDirection;
bool bComeTrain;
} ComeTrainInfo;
// 定义日期结构体
typedef struct Date
{

View File

@ -8,8 +8,6 @@ base:
connect_type: 0
# 是否上传识别结果
up_result: false
# 是否使用外部接口辅助开关识别
use_socket_server: false
# 是否存在磁钢
have_magnet_steel: true
# 火车进厂的磁钢顺序
@ -65,22 +63,12 @@ http_server:
# 接口密码
password: "d55b0f642e817eea24725d2f2a31dd08"
# FTP服务器参数
ftp:
# 启用状态
is_use: false
# 通讯类型 [ftp, sftp]
type: "ftp"
# 服务器IP
ip: "192.168.2.211"
# 端口
port: 21
# 用户名
username: "matrixai"
# 密码
password: "123"
# 上传地址
path: ""
# X秒后自动断开时间
quit_time: 120
# 视频识别辅助来车状态检测
video_auxiliary:
# 是否使用外部接口辅助开关识别
use_video_auxiliary: false
# IP
ip: "172.18.0.1"
# 端口号
port: 7003

View File

@ -10,10 +10,12 @@ engines:
HttpUpResultEngine: 0
SaveResultEngine: 0
DelExpiredEngine: 0
VideoAuxiliaryEngine: 0
#engine连接
connects:
GetRfidEngine_0_0: "DealRfidEngine_0_0 1024"
VideoAuxiliaryEngine_0_0: "DealRfidEngine_0_1 1024"
DealRfidEngine_0_0: "SaveRfidEngine_0_0 1024"
DealRfidEngine_0_1: "HttpUpResultEngine_0_0 1024"
DealRfidEngine_0_2: "SaveResultEngine_0_0 1024"

View File

@ -14,6 +14,7 @@ APP_ERROR DealRfidEngine::Init()
strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->videoAuxiliaryConfig_ = Config::GetIns()->getVideoAuxiliaryConfig();
this->initParam();
@ -32,6 +33,24 @@ APP_ERROR DealRfidEngine::Process()
int iRet = APP_ERR_OK;
while (!isStop_)
{
if (this->videoAuxiliaryConfig_.bUseVideoAuxiliary)
{
//pop端口1
std::shared_ptr<void> pVoidData1 = nullptr;
iRet = inputQueMap_[strPort1_]->pop(pVoidData1);
if (nullptr != pVoidData1)
{
std::shared_ptr<ComeTrainInfo> pComeTrainInfo = std::static_pointer_cast<ComeTrainInfo>(pVoidData1);
this->videoHasTrain_ = pComeTrainInfo->bComeTrain;
this->identifyFlagUpdate();
if (this->iVDirection_ == 0 && pComeTrainInfo->iDirection != 0)
{
LogInfo << "视频辅助检测来车状态 判定 来车方向:" << (pComeTrainInfo->iDirection > -1 ? (pComeTrainInfo->iDirection > 0 ? "需识别" : "待定") : "无需上传");
this->iVDirection_ = pComeTrainInfo->iDirection;
}
}
}
//pop端口0
std::shared_ptr<void> pVoidData0 = nullptr;
iRet = inputQueMap_[strPort0_]->pop(pVoidData0);
@ -45,7 +64,6 @@ APP_ERROR DealRfidEngine::Process()
this->tmpRfid_.append(pRfidData->strRfid);
LogDebug << "原文:" << this->tmpRfid_;
if (this->tmpRfid_.substr(this->tmpRfid_.size()-1,1) != "&")
{
continue;
@ -55,7 +73,6 @@ APP_ERROR DealRfidEngine::Process()
std::vector<std::string> vecRfidSub = StringUtil::getins()->split(this->tmpRfid_, "@");
// LogDebug << "--" << vecRfidSub.size();
this->tmpRfid_ = "";
auto split_lambda = [=](std::string strFirst, std::string strOther){
@ -63,8 +80,6 @@ APP_ERROR DealRfidEngine::Process()
{
this->rfidHasTrain_ = false;
LogInfo << "RFID-火车离开了";
// 关功放信号
// 需要结合 “来车状态”广播消息,确认是否真的车离开了;
this->identifyFlagUpdate();
}
else
@ -90,21 +105,19 @@ APP_ERROR DealRfidEngine::Process()
for (const auto & i : vecRfidSub)
{
if (i.empty()) continue;
if (i.size() == 26 || i.size() == 24)
{
// 车厢信息
std::string strTrainInfo = i.substr(0, 14);
std::string strTrainInfo = i.substr(1, 13);
if (this->vecTrain_.empty() || !Utils::getins()->contains_vec(this->vecTrain_, strTrainInfo))
{
bool isNoCarriage = false;
int carT = StringUtil::getins()->string2int(strTrainInfo.substr(3, 2), isNoCarriage);
// 判断是否是车头 车头的第14位是 K或H (慎重)
if (!StringUtil::getins()->is_digits(i.substr(14, 1))) continue;
// 过滤掉车号中有非数字的
if (!StringUtil::getins()->is_digits(strTrainInfo.substr(strTrainInfo.size() -7, 7))) continue;
if (isNoCarriage && carT >= 10) continue;
// 因信号不稳定 增加一行过滤 出现文字中带有字母及数字以外的字符时,过滤
if (StringUtil::getins()->containsNonAlphaNum(strTrainInfo)) continue;
// 因信号不稳定 增加一行过滤 出现读到的数据里 空格替代了实际字符的情况
if (StringUtil::getins()->trim(strTrainInfo.substr(7, 7)).size() < 7) continue;
vecTrain_.emplace_back(strTrainInfo);
int train_order = vecTrain_.size();
LogInfo << "" << train_order << "" << strTrainInfo;
@ -114,11 +127,24 @@ APP_ERROR DealRfidEngine::Process()
this->rfidSourceInfo_ = "";
std::shared_ptr<TrainInfo> pTrainInfo = std::make_shared<TrainInfo>();
TrainInfo tmpTrainInfo;
this->makeTrainInfo(rfidinfo, pTrainInfo);
queueTmpTrainInfo_.Push(pTrainInfo);
if (this->needIdentify_) {
// 上传识别结果
iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainInfo));
if (this->iVDirection_ < 0)
{
queueTmpTrainInfo_.Clear();
}
if (this->iVDirection_ > 0)
{
while (!queueTmpTrainInfo_.IsEmpty())
{
queueTmpTrainInfo_.Pop(pTrainInfo);
// 上传识别结果
iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainInfo));
}
}
}
// 存储识别结果
iRet = outputQueMap_[strPort2_]->push(std::static_pointer_cast<void>(pTrainInfo));
@ -170,6 +196,8 @@ void DealRfidEngine::initParam() {
this->videoHasTrain_ = false;
// RFID识别有火车标志
this->rfidHasTrain_ = false;
//
this->iVDirection_ = 0;
}
/**
@ -181,7 +209,6 @@ void DealRfidEngine::identifyFlagUpdate() {
if (!this->needIdentify_)
{
LogInfo << "--- 来车了 ---";
// this->mkRfidLog();
this->vecTrain_.clear();
this->needIdentify_ = true;
this->trainTime_ = TimeUtil::getins()->getDateTime();
@ -202,8 +229,11 @@ void DealRfidEngine::identifyFlagUpdate() {
void DealRfidEngine::makeTrainInfo(const std::string rfidinfo, std::shared_ptr<TrainInfo> pTrainInfo) {
std::string info = this->vecTrain_.back();
int order = this->vecTrain_.size();
info = info.substr(1,info.size() - 1);
if (order > this->videoAuxiliaryConfig_.iDelayedUpload && this->iVDirection_ == 0)
{
this->iVDirection_ = 1;
}
if (!this->videoAuxiliaryConfig_.bUseVideoAuxiliary) this->iVDirection_ = 1;
if (this->trainTime_.empty()) this->trainTime_ = TimeUtil::getins()->getDateTime();
pTrainInfo->strCarriageType = StringUtil::getins()->trim(info.substr(0, 6));

View File

@ -9,9 +9,11 @@
#include "Config.h"
#include "EngineBase.h"
#include "EngineFactory.h"
#include "CommandParser.h"
#include "TimeUtil.h"
#include "StringUtil.h"
#include "Utils.h"
#include "BlockingQueue.h"
class DealRfidEngine : public ai_matrix::EngineBase
{
@ -34,6 +36,8 @@ private:
// 核心配置
ai_matrix::BaseConfig baseConfig_;
// 视频辅助来车状态检测配置
ai_matrix::VideoAuxiliaryConfig videoAuxiliaryConfig_;
// 临时存储的接收数据
std::string tmpRfid_;
// 识别方向正确标志
@ -42,10 +46,14 @@ private:
bool videoHasTrain_;
// RFID识别有火车标志
bool rfidHasTrain_;
// 视频识别判定的方向 0暂未确认方向 1需要识别 -1 不需要识别
int iVDirection_;
// RFID源数据
std::string rfidSourceInfo_;
// 本列车识别结果(临时存储)
std::vector<std::string> vecTrain_;
// 本列车识别结果临时队列
BlockingQueue<std::shared_ptr<TrainInfo>> queueTmpTrainInfo_;
void identifyFlagUpdate();
void initParam();

View File

@ -41,7 +41,7 @@ APP_ERROR GetRfidEngine::Process()
if (this->iConnectType == AEI_SOCKET_TYPE)
{
LogInfo << "服务端IP" << this->ethernetConfig_.strIp << " 端口:" << this->ethernetConfig_.iPort;
LogInfo << "RFID服务端IP" << this->ethernetConfig_.strIp << " 端口:" << this->ethernetConfig_.iPort;
this->baseScoket_.Open();
this->baseScoket_.SetPort(this->ethernetConfig_.iPort, this->ethernetConfig_.strIp);
this->baseScoket_.Init();
@ -63,7 +63,7 @@ APP_ERROR GetRfidEngine::Process()
{
LogError << "通讯类型设置异常!";
}
LogInfo << "开启通讯...";
LogInfo << "RFID开启通讯...";
while (!isStop_)
{

View File

@ -41,18 +41,18 @@ APP_ERROR SaveRfidEngine::Process()
try {
if (pRfidInfo->strTrainTime == "") continue;
std::string strTrainPath = this->baseConfig_.strResultPath + "/" + TimeUtil::getins()->getDate() + "/";
std::string strTrainPath = this->baseConfig_.strRfidPath + "/" + TimeUtil::getins()->getDate() + "/";
//1. 创建保存路径 (固定路径/YYYY-MM-DD/hh-mm-ss/iDataSoure/)
//1. 创建保存路径
if (!FileUtil::getins()->CreateDirPath(strTrainPath))
{
LogError << "结果目录:" << strTrainPath << " 创建失败!";
return false;
}
std::string strLogName = this->baseConfig_.strRfidPath + "/" + pRfidInfo->strTrainTime + "_source.log";
std::string strLogName = pRfidInfo->strTrainTime + "_source.log";
strLogName = StringUtil::getins()->replace_all_distinct(strLogName, ":", "-");
strLogName = StringUtil::getins()->replace_all_distinct(strLogName, " ", "T");
std::string strLogPath = strTrainPath + strLogName;
std::string strLogPath = strTrainPath + "/" + strLogName;
std::ofstream fs(strLogPath, std::ios::app);
if (!fs)

View File

@ -0,0 +1,145 @@
#include "VideoAuxiliaryEngine.h"
using namespace ai_matrix;
VideoAuxiliaryEngine::VideoAuxiliaryEngine() {}
VideoAuxiliaryEngine::~VideoAuxiliaryEngine() {}
APP_ERROR VideoAuxiliaryEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
this->videoAuxiliaryConfig_ = Config::GetIns()->getVideoAuxiliaryConfig();
this->carType_ = "0";
LogInfo << "VideoAuxiliaryEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR VideoAuxiliaryEngine::DeInit()
{
this->baseScoket_.Close();
LogInfo << "VideoAuxiliaryEngine DeInit ok";
return APP_ERR_OK;
}
APP_ERROR VideoAuxiliaryEngine::Process()
{
int iRet = APP_ERR_OK;
if (!this->videoAuxiliaryConfig_.bUseVideoAuxiliary)
{
return APP_ERR_OK;
}
this->baseScoket_.Open();
this->baseScoket_.SetPort(this->videoAuxiliaryConfig_.iPort, this->videoAuxiliaryConfig_.strIp);
this->baseScoket_.Init();
LogInfo << "视频辅助 服务端IP" << this->videoAuxiliaryConfig_.strIp << " 端口:" << this->videoAuxiliaryConfig_.iPort;
LogInfo << "开启通讯...";
while (!isStop_)
{
char chbuffer[AEI_COMM_BUFFER_SIZE] = {0};
int nRevSize = 0;
memset(chbuffer, 0x00, sizeof(chbuffer));
if (!this->baseScoket_.bRuning())
{
LogError << "TCP 连接失败,重启中 ...";
usleep(20 * 1000 * 1000); // 20秒后重试
this->baseScoket_.Close();
this->baseScoket_.Open();
this->baseScoket_.Init();
continue;
}
nRevSize = this->baseScoket_.Read();
if (nRevSize <= 0)
{
this->baseScoket_.Monitor();
continue;
}
else
{
memcpy(chbuffer, this->baseScoket_.chbuffer, nRevSize);
}
this->dealSocketInfo(chbuffer);
}
return APP_ERR_OK;
}
bool VideoAuxiliaryEngine::getOrder(const std::string &recv, Json::Value &order)
{
Json::CharReaderBuilder readerBuilder;
std::shared_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
JSONCPP_STRING errs;
if (!reader->parse(recv.data(), recv.data() + recv.size(), &order, &errs))
return false;
if (order.isArray()) {
if (!order.empty()) order = order[0];
return true;
}
return true;
}
void VideoAuxiliaryEngine::dealSocketInfo(const std::string &info) {
std::string vedioInfo = info;
StringUtil::getins()->replace_all_distinct(vedioInfo, "}{", "}&{");
std::vector<std::string> vecJson = StringUtil::getins()->split(vedioInfo, "&");
for (int i = 0; i < vecJson.size(); ++i)
{
Json::Value feedBack;
if (!this->getOrder(vecJson[i], feedBack))
{
LogWarn << "接收到视频识别反馈的来车状态信息未能解析成JSON格式。";
continue;
}
std::shared_ptr<ComeTrainInfo> pComeTrainInfo = std::make_shared<ComeTrainInfo>();
std::string tmpCarType = feedBack.get("type", "").asString();
int iDirection = feedBack.get("direction", 0).asInt();
if (tmpCarType != this->carType_)
{
if (this->carType_ == "0")
{
// 来车
pComeTrainInfo->bComeTrain = true;
pComeTrainInfo->iDirection = 0;
if (iDirection != 0) pComeTrainInfo->iDirection = iDirection;
outputQueMap_[strPort0_]->push(pComeTrainInfo);
this->carType_ = tmpCarType;
}
else if (this->carType_ == "1")
{
// 无车
pComeTrainInfo->bComeTrain = false;
pComeTrainInfo->iDirection = 0;
outputQueMap_[strPort0_]->push(pComeTrainInfo);
this->carType_ = tmpCarType;
}
else
{
LogWarn << "视频辅助检测来车状态,反馈的来车状态无法识别";
continue;
}
if (tmpCarType == this->carType_ && iDirection != 0)
{
pComeTrainInfo->bComeTrain = true;
pComeTrainInfo->iDirection = iDirection;
outputQueMap_[strPort0_]->push(pComeTrainInfo);
}
}
}
}

View File

@ -0,0 +1,46 @@
/**
*
* */
#ifndef VIDEOAUXILIARYENGINE_H
#define VIDEOAUXILIARYENGINE_H
#include "AppCommon.h"
#include "EngineBase.h"
#include "EngineFactory.h"
#include "Config.h"
#include "TimeUtil.h"
#include "StringUtil.h"
#include "BaseSocket.h"
#include "BaseComPort.h"
#include "json/json.h"
#define AEI_SOCKET_TYPE 0
#define AEI_COM_TYPE 1
class VideoAuxiliaryEngine : public ai_matrix::EngineBase
{
public:
VideoAuxiliaryEngine();
~VideoAuxiliaryEngine();
APP_ERROR Init() override;
APP_ERROR DeInit() override;
APP_ERROR Process() override;
private:
std::string strPort0_;
ai_matrix::VideoAuxiliaryConfig videoAuxiliaryConfig_;
BaseSocket baseScoket_;
std::string carType_;
bool getOrder(const std::string &recv, Json::Value &order);
void dealSocketInfo(const std::string &info);
};
ENGINE_REGIST(VideoAuxiliaryEngine)
#endif