更新报警信息上传

This commit is contained in:
Mr.V 2024-07-27 16:12:26 +08:00
parent bb41c419de
commit fdbb34ca5a
21 changed files with 842 additions and 244 deletions

View File

@ -56,8 +56,10 @@ set(SYS_USR_INCLUDE_DIR "/usr/include")
set(SYS_USR_LIB_DIR "/usr/lib")
set(SYS_USR_LOCAL_INCLUDE_DIR "/usr/local/include")
set(SYS_USR_LOCAL_LIB_DIR "/usr/local/lib")
set(X86_LINUX_INCLUDE_DIR "/usr/include/x86_64-linux-gnu")
set(X86_LINUX_LIB_DIR "/usr/lib/x86_64-linux-gnu")
# set(X86_LINUX_INCLUDE_DIR "/usr/include/x86_64-linux-gnu")
# set(X86_LINUX_LIB_DIR "/usr/lib/x86_64-linux-gnu")
set(X86_LINUX_INCLUDE_DIR "/usr/include/aarch64-linux-gnu")
set(X86_LINUX_INCLUDE_DIR "/usr/lib/aarch64-linux-gnu")
#OpenCV
#set(OPENCV_INCLUDE_DIR ${SYS_USR_LOCAL_INCLUDE_DIR}/opencv4)
@ -103,9 +105,9 @@ aux_source_directory(${PROJECT_SRC_ROOT}/engine/DealRfidEngine DealRfidEngine_SR
include_directories(${PROJECT_SRC_ROOT}/engine/GetRfidEngine)
aux_source_directory(${PROJECT_SRC_ROOT}/engine/GetRfidEngine GetRfidEngine_SRC)
# HttpUpResultEngine
include_directories(${PROJECT_SRC_ROOT}/engine/HttpUpResultEngine)
aux_source_directory(${PROJECT_SRC_ROOT}/engine/HttpUpResultEngine HttpUpResultEngine_SRC)
# HttpEngine
include_directories(${PROJECT_SRC_ROOT}/engine/HttpEngine)
aux_source_directory(${PROJECT_SRC_ROOT}/engine/HttpEngine HttpEngine_SRC)
# SaveResultEngine
include_directories(${PROJECT_SRC_ROOT}/engine/SaveResultEngine)
@ -183,7 +185,7 @@ file(
# engine
${DealRfidEngine_SRC}
${GetRfidEngine_SRC}
${HttpUpResultEngine_SRC}
${HttpEngine_SRC}
${SaveResultEngine_SRC}
${SaveRfidEngine_SRC}
${VideoAuxiliaryEngine_SRC}

View File

@ -72,9 +72,12 @@ namespace ai_matrix
this->httpServerConfig_.iPort = config_["http_server"]["http_port"].as<int>();
this->httpServerConfig_.strTokenUrl = config_["http_server"]["token_path"].as<std::string>();
this->httpServerConfig_.strUpResultUrl = config_["http_server"]["up_result_path"].as<std::string>();
this->httpServerConfig_.strDeviceStatusUrl = config_["http_server"]["device_status_url"].as<std::string>();
this->httpServerConfig_.strUserName = config_["http_server"]["username"].as<std::string>();
this->httpServerConfig_.strPassword = config_["http_server"]["password"].as<std::string>();
// 设备报警参数
this->deviceWarnConfig_.iMinTrainSize = config_["device_warn"]["min_train_size"].as<int>();
}
catch (...) //捕获所有异常
{
@ -227,4 +230,12 @@ namespace ai_matrix
void Config::setHttpServerConfig(const HttpServerConfig httpServerConfig) {
this->httpServerConfig_ = httpServerConfig;
}
DeviceWarnConfig Config::getDeviceWarnConfig() const {
return this->deviceWarnConfig_;
}
void Config::setDeviceWarnConfig(const ai_matrix::DeviceWarnConfig deviceWarnConfig) {
this->deviceWarnConfig_ = deviceWarnConfig;
}
}

View File

@ -88,6 +88,8 @@ namespace ai_matrix
std::string strTokenUrl;
// 识别结果上传地址
std::string strUpResultUrl;
// 设备状态上传地址
std::string strDeviceStatusUrl;
// 接口用户名
std::string strUserName;
// 接口密码
@ -107,6 +109,13 @@ namespace ai_matrix
int iDelayedUpload;
};
// 设备报警参数
struct DeviceWarnConfig
{
// 最小识别车节数
int iMinTrainSize;
};
class Config final
{
public:
@ -145,6 +154,9 @@ namespace ai_matrix
// 获取FTP服务器参数
VideoAuxiliaryConfig getVideoAuxiliaryConfig() const;
void setVideoAuxiliaryConfig(const VideoAuxiliaryConfig videoAuxiliaryConfig);
// 获取设备报警参数
DeviceWarnConfig getDeviceWarnConfig() const;
void setDeviceWarnConfig(const DeviceWarnConfig deviceWarnConfig);
YAML::Node config_;
@ -179,6 +191,9 @@ namespace ai_matrix
// ftp服务器参数
VideoAuxiliaryConfig videoAuxiliaryConfig_;
// 设备报警参数
DeviceWarnConfig deviceWarnConfig_;
//定义一个嵌套类,负责释放内存,操作系统自动完成,不用担心内存泄露
class GarbageCollector
{

View File

@ -35,16 +35,16 @@ void BaseSocket::Open()
} else {
struct timeval recvTimersetting;
//接收超时时间固定3
recvTimersetting.tv_sec = 3;
//接收超时时间固定1
recvTimersetting.tv_sec = 1;
recvTimersetting.tv_usec = 0;
//设定接收超时时间
setsockopt(nSocketId, SOL_SOCKET, SO_RCVTIMEO, &recvTimersetting, sizeof(recvTimersetting));
struct timeval sendTimersetting;
//发送超时时间固定3
sendTimersetting.tv_sec = 3;
//发送超时时间固定1
sendTimersetting.tv_sec = 1;
sendTimersetting.tv_usec = 0;
//设定发送超时时间c

View File

@ -60,6 +60,20 @@ extern "C"
#define AEI_COMM_BUFFER_SIZE 2048
typedef struct
{
// 数据网络状态
std::string strNetworkStatus;
// 设备名
std::string strDeviceName;
// 设备编码
std::string strDeviceSn;
// 设备/程序 运行状态
std::string strDeviceRunningStatus;
// 提示信息
std::string strDeviceWarnInfo;
} DeviceStatus;
typedef struct
{
std::string strRfid;

View File

@ -42,9 +42,9 @@ serial:
# 网口通讯
ethernet:
# 串口服务器IP
ip: "172.18.0.1"
ip: "172.22.64.1"
# 端口号
port: 7002
port: 7004
# http 接口
http_server:
@ -58,6 +58,8 @@ http_server:
token_path: "/api/blade-auth/oauth/token"
# 识别结果上传地址
up_result_path: "/api/train-carriage/identification/rfid-save"
# 设备状态上传地址
device_status_url: "/api/blade-train/deviceInfo/save"
# 接口用户名
username: "guest_01"
# 接口密码
@ -66,9 +68,16 @@ http_server:
# 视频识别辅助来车状态检测
video_auxiliary:
# 是否使用外部接口辅助开关识别
use_video_auxiliary: false
use_video_auxiliary: true
# IP
ip: "172.18.0.1"
ip: "172.22.64.1"
# 端口号
port: 7003
port: 7005
# 延迟上传车节数
delayed_upload: 4
# 设备报警参数
device_warn:
# 最小识别车节数
min_train_size: 10

View File

@ -11,11 +11,15 @@ engines:
SaveResultEngine: 0
DelExpiredEngine: 0
VideoAuxiliaryEngine: 0
UpDeviceStatusEngine: 0
#engine连接
connects:
GetRfidEngine_0_0: "DealRfidEngine_0_0 1024"
GetRfidEngine_0_1: "UpDeviceStatusEngine_0_0 1024"
VideoAuxiliaryEngine_0_0: "DealRfidEngine_0_1 1024"
VideoAuxiliaryEngine_0_1: "UpDeviceStatusEngine_0_0 1024"
DealRfidEngine_0_0: "SaveRfidEngine_0_0 1024"
DealRfidEngine_0_1: "HttpUpResultEngine_0_0 1024"
DealRfidEngine_0_2: "SaveResultEngine_0_0 1024"
DealRfidEngine_0_2: "SaveResultEngine_0_0 1024"
DealRfidEngine_0_3: "UpDeviceStatusEngine_0_0 1024"

View File

@ -12,9 +12,11 @@ APP_ERROR DealRfidEngine::Init()
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
strPort2_ = engineName_ + "_" + std::to_string(engineId_) + "_2";
strPort3_ = engineName_ + "_" + std::to_string(engineId_) + "_3";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->videoAuxiliaryConfig_ = Config::GetIns()->getVideoAuxiliaryConfig();
this->deviceWarnConfig_ = Config::GetIns()->getDeviceWarnConfig();
this->initParam();
@ -116,7 +118,7 @@ APP_ERROR DealRfidEngine::Process()
// 判断是否是车头 车头的第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 (!StringUtil::getins()->is_digits(strTrainInfo.substr(strTrainInfo.size() -7, 7))) continue;
vecTrain_.emplace_back(strTrainInfo);
int train_order = vecTrain_.size();
@ -141,8 +143,15 @@ APP_ERROR DealRfidEngine::Process()
while (!queueTmpTrainInfo_.IsEmpty())
{
queueTmpTrainInfo_.Pop(pTrainInfo);
// 上传识别结果
iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainInfo));
if (!Utils::getins()->contains_vec(this->vecLastTrain_, strTrainInfo))
{
// 上传识别结果
iRet = outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pTrainInfo));
}
else
{
LogWarn << "" << train_order << "" << strTrainInfo << " 与上一列车识别的信息重复,不上传";
}
}
}
}
@ -174,9 +183,12 @@ APP_ERROR DealRfidEngine::Process()
split_lambda(strFirst, strOther);
}
}
pRfidData->strTrainTime = this->trainTime_;
std::shared_ptr<RfidInfo> pSaveRfidData = std::make_shared<RfidInfo>();
pSaveRfidData->strRfid = pRfidData->strRfid;
pSaveRfidData->strTime = pRfidData->strTime;
pSaveRfidData->strTrainTime = this->trainTime_;
// 存储原始数据
iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pRfidData));
iRet = outputQueMap_[strPort0_]->push(std::static_pointer_cast<void>(pSaveRfidData));
}
}
return APP_ERR_OK;
@ -188,6 +200,7 @@ APP_ERROR DealRfidEngine::Process()
void DealRfidEngine::initParam() {
this->rfidSourceInfo_ = "";
this->trainTime_ = "";
this->vecLastTrain_ = this->vecTrain_.empty() ? this->vecLastTrain_ : this->vecTrain_;
this->vecTrain_.clear();
this->tmpRfid_ = "";
// 识别方向正确标志
@ -198,6 +211,8 @@ void DealRfidEngine::initParam() {
this->rfidHasTrain_ = false;
//
this->iVDirection_ = 0;
// 清空上一列的信息
queueTmpTrainInfo_.Clear();
}
/**
@ -216,6 +231,19 @@ void DealRfidEngine::identifyFlagUpdate() {
}
else if (!this->rfidHasTrain_ && !this->videoHasTrain_)
{
if (this->vecTrain_.size() < this->deviceWarnConfig_.iMinTrainSize
&& this->iVDirection_ > 0
&& (this->rfidSourceInfo_.size() > 128 || this->vecTrain_.size() > 1))
{
std::shared_ptr<DeviceStatus> pDeviceStatus = std::make_shared<DeviceStatus>();
pDeviceStatus->strDeviceName = "RFID设备";
pDeviceStatus->strDeviceRunningStatus = "异常";
pDeviceStatus->strNetworkStatus = "正常";
pDeviceStatus->strDeviceSn = this->baseConfig_.strTrackName + "股道";
pDeviceStatus->strDeviceWarnInfo = "火车驶过疑似RFID设备故障读取到的车厢号有丢失";
outputQueMap_[strPort3_]->push(std::static_pointer_cast<void>(pDeviceStatus));
}
this->initParam();
LogInfo << "--- 火车离开了 ---";
}

View File

@ -2,8 +2,8 @@
* RFID获取的数据
* */
#ifndef SELECTBESTENGINE_H
#define SELECTBESTENGINE_H
#ifndef DEALRFIDENGINE_H
#define DEALRFIDENGINE_H
#include "AppCommon.h"
#include "Config.h"
@ -30,6 +30,7 @@ private:
std::string strPort0_;
std::string strPort1_;
std::string strPort2_;
std::string strPort3_;
// 来车的时间
std::string trainTime_;
@ -38,6 +39,8 @@ private:
ai_matrix::BaseConfig baseConfig_;
// 视频辅助来车状态检测配置
ai_matrix::VideoAuxiliaryConfig videoAuxiliaryConfig_;
// 设备报警参数
ai_matrix::DeviceWarnConfig deviceWarnConfig_;
// 临时存储的接收数据
std::string tmpRfid_;
// 识别方向正确标志
@ -52,6 +55,8 @@ private:
std::string rfidSourceInfo_;
// 本列车识别结果(临时存储)
std::vector<std::string> vecTrain_;
// 上列车识别结果(临时存储)
std::vector<std::string> vecLastTrain_;
// 本列车识别结果临时队列
BlockingQueue<std::shared_ptr<TrainInfo>> queueTmpTrainInfo_;

View File

@ -10,6 +10,7 @@ GetRfidEngine::~GetRfidEngine() {}
APP_ERROR GetRfidEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->serialConfig_ = Config::GetIns()->getSerialConfig();
this->ethernetConfig_ = Config::GetIns()->getEthernetConfig();
@ -76,10 +77,26 @@ APP_ERROR GetRfidEngine::Process()
if (!this->baseScoket_.bRuning())
{
LogError << "RFID 连接失败,重启中 ...";
usleep(20 * 1000 * 1000); // 20秒后重试
std::shared_ptr<DeviceStatus> pDeviceStatus = std::make_shared<DeviceStatus>();
pDeviceStatus->strDeviceName = "RFID程序";
pDeviceStatus->strDeviceRunningStatus = "正常";
pDeviceStatus->strNetworkStatus = "异常";
pDeviceStatus->strDeviceWarnInfo = "“RFID车号识别”程序无法同RFID设备通讯";
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pDeviceStatus));
usleep(5 * 1000 * 1000); // 20秒后重试
this->baseScoket_.Close();
this->baseScoket_.Open();
this->baseScoket_.Init();
if (this->baseScoket_.bRuning())
{
LogInfo << "RFID 连接成功 ...";
std::shared_ptr<DeviceStatus> pDeviceStatus = std::make_shared<DeviceStatus>();
pDeviceStatus->strDeviceName = "RFID程序";
pDeviceStatus->strDeviceRunningStatus = "正常";
pDeviceStatus->strNetworkStatus = "正常";
pDeviceStatus->strDeviceWarnInfo = "“RFID车号识别”程序同RFID设备通讯连接成功";
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pDeviceStatus));
}
continue;
}
@ -120,7 +137,7 @@ APP_ERROR GetRfidEngine::Process()
if(nRevSize <= 0)
{
usleep(1000 * 1000);
usleep(1 * 1000);
//comporthandle.ttyClose();
} else {
nRevSize = this->baseComPort_.vGetBuffer(chbuffer, (int32_t)sizeof(chbuffer));

View File

@ -30,6 +30,7 @@ public:
private:
std::string strPort0_;
std::string strPort1_;
ai_matrix::BaseConfig baseConfig_;
ai_matrix::SerialConfig serialConfig_;

View File

@ -0,0 +1,229 @@
#include "HttpUpResultEngine.h"
#undef DISABLE_SSH_AGENT
namespace
{
std::map<std::string, std::string> mapAscii = {
{"!", "%21"},
{"#", "%23"},
{"$", "%24"},
{"%", "%25"},
{"&", "%26"},
{"@", "%40"},
{"*", "%2A"}
};
}
HttpUpResultEngine::HttpUpResultEngine() {}
HttpUpResultEngine::~HttpUpResultEngine() {}
APP_ERROR HttpUpResultEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->httpServerConfig_ = Config::GetIns()->getHttpServerConfig();
LogInfo << "HttpUpResultEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR HttpUpResultEngine::DeInit()
{
LogInfo << "HttpUpResultEngine DeInit ok";
return APP_ERR_OK;
}
//bool HttpEngine::upWeb(std::shared_ptr<TrainInfo> pTrainInfo, int retransmission)
//{
// try {
// Json::Value arrayObj; //构建对象
//
// arrayObj["comeTime"] = pTrainInfo->strTrainTime;
// arrayObj["collectTime"] = pTrainInfo->strNowTime;
// arrayObj["carriageNumber"] = pTrainInfo->strCarriageNum;
// arrayObj["carriageType"] = pTrainInfo->strCarriageType;
// arrayObj["carriageOrder"] = pTrainInfo->strOrder;
// arrayObj["steel"] = pTrainInfo->strRfidInfo;
//
// Json::Value trainParams;
// trainParams["poundNo"] = this->baseConfig_.strTrackName;
// arrayObj["trainParams"] = trainParams;
// Json::StreamWriterBuilder writer;
// std::string str = Json::writeString(writer, arrayObj);
//
// LogInfo << "第" << pTrainInfo->strOrder << "节发送web: " << str;
//
// httplib::Client cli(this->httpServerConfig_.strIp, this->httpServerConfig_.iPort);
// cli.set_connection_timeout(0, 300 * 1000);
// cli.set_read_timeout(3,0);
// httplib::Headers header;
// httplib::Params params;
// header.emplace("blade-auth", this->webToken);
// //header.emplace("Content-Type", "application/json");
//
// auto res = cli.Post(this->httpServerConfig_.strUpResultUrl, header, str, "application/json");
// if (res)
// {
// if (res->status == 200)
// {
// LogInfo << "第" << pTrainInfo->strOrder << "节web返回: " << res->body;
// Json::CharReaderBuilder readerBuilder;
// std::istringstream iss(res->body);
// Json::Value root;
// std::string errs;
// bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
// if (parsingSuccessful)
// {
// if (root["success"].asBool())
// {
// return true;
// }
// else
// {
//
// if (root["msg"].asString() == "请求未授权") {
// LogWarn << "第" << pTrainInfo->strOrder << "节因请求未授权而上传识别结果失败重新请求token。";
// if (!this->getToken()) return false;
// return this->upWeb(pTrainInfo);
// }
// LogError << "第" << pTrainInfo->strOrder << "节,识别结果上传失败,原因:" << root["msg"].asString();
// }
// }
// else
// {
// LogError << "第" << pTrainInfo->strOrder << "节识别结果上传失败返回数据解析异常返回数据非json" + res->body;
// }
// }
// else
// {
// LogError << "第" << pTrainInfo->strOrder << "节,识别结果上传失败,原因:" << res->status << " - " << res->body;
// if (res->status == 401) {
// LogWarn << "因请求未授权而上传识别结果失败重新请求token。";
// this->getToken();
// return this->upWeb(pTrainInfo);
// }
// }
// }
// else
// {
// LogError << "第" << pTrainInfo->strOrder << "节,上传数据失败(超时),请检查网络,或者上传地址!计划重新上传次数:" << retransmission;
// if (retransmission > 0) return this->upWeb(pTrainInfo, retransmission-1);
// }
// }
// catch (std::exception &e)
// {
// LogError << "第" << pTrainInfo->strOrder << "节,上传识别结果失败,原因:";
// LogError << e.what();
// }
// return false;
//}
/**
* @brief:Http获取授权
* @param
* @return:
*/
//bool HttpEngine::getToken()
//{
// try
// {
// httplib::Client cli(this->httpServerConfig_.strIp, this->httpServerConfig_.iPort);
// cli.set_connection_timeout(0, 300 * 1000);
// cli.set_read_timeout(0,300*1000);
// httplib::Headers header;
// httplib::Params params;
//
// header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
//
// params.emplace("username", this->httpServerConfig_.strUserName);
// params.emplace("password", this->httpServerConfig_.strPassword);
// params.emplace("tenantId", "000000");
// params.emplace("grant_type", "password");
// auto res = cli.Post(this->httpServerConfig_.strTokenUrl, header, params);
// if (res)
// {
// if (res->status == 200)
// {
// Json::CharReaderBuilder readerBuilder;
// std::istringstream iss(res->body);
// Json::Value root;
// std::string errs;
// bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
//
// if (parsingSuccessful)
// {
// if (!root.get("token_type", "").asString().empty())
// {
// this->webToken = root["token_type"].asString();
// this->webToken.append(" ");
// this->webToken.append(root["access_token"].asString());
// LogInfo << "已获取到web token";
// return true;
// }
// else
// {
// LogError << "获取web token失败原因" << res->body;
// }
// }
// else
// {
// LogError << "获取web token返回数据解析异常返回数据非json。详细" << res->body;
// }
// }
// }
// else
// {
// auto err = res.error();
//// if (err == httplib::Error::Connection) {
//// std::cout << " (连接出错)" << std::endl;
//// }
// LogError << "获取web token失败请检查网络或请求地址。详细" << to_string(err);
// }
// }
// catch (std::exception &e)
// {
// LogError << "获取授权失败,原因:";
// LogError << e.what();
// }
// return false;
//}
APP_ERROR HttpUpResultEngine::Process()
{
int iRet = APP_ERR_OK;
while (!isStop_)
{
std::shared_ptr<void> pVoidData0 = nullptr;
inputQueMap_[strPort0_]->pop(pVoidData0);
if (nullptr == pVoidData0)
{
usleep(1000); //1ms
continue;
}
std::shared_ptr<TrainInfo> pTrainInfo = std::static_pointer_cast<TrainInfo>(pVoidData0);
if (!this->httpServerConfig_.bIsUse) continue;
Json::Value arrayObj; //构建对象
arrayObj["comeTime"] = pTrainInfo->strTrainTime;
arrayObj["collectTime"] = pTrainInfo->strNowTime;
arrayObj["carriageNumber"] = pTrainInfo->strCarriageNum;
arrayObj["carriageType"] = pTrainInfo->strCarriageType;
arrayObj["carriageOrder"] = pTrainInfo->strOrder;
arrayObj["steel"] = pTrainInfo->strRfidInfo;
Json::Value trainParams;
trainParams["poundNo"] = this->baseConfig_.strTrackName;
arrayObj["trainParams"] = trainParams;
if (!ToWeb::getins()->upWeb(arrayObj, 1))
{
// LogError << "第" << pTrainInfo->strOrder + "节,识别结果上传失败!";
}
}
return APP_ERR_OK;
}

View File

@ -2,8 +2,8 @@
* web
* */
#ifndef DATATOFTPSRVENGINE_H
#define DATATOFTPSRVENGINE_H
#ifndef HTTPUPRESULTENGINE_H
#define HTTPUPRESULTENGINE_H
#include "AppCommon.h"
#include "Config.h"
@ -11,6 +11,7 @@
#include "EngineFactory.h"
#include "json/json.h"
#include "httplib.h"
#include "ToWeb.h"
using namespace ai_matrix;
@ -29,7 +30,7 @@ private:
ai_matrix::BaseConfig baseConfig_;
ai_matrix::HttpServerConfig httpServerConfig_;
bool upWeb(std::shared_ptr<TrainInfo> pTrainInfo);
// bool upWeb(std::shared_ptr<TrainInfo> pTrainInfo, int retransmission = 0);
bool getToken();
std::string webToken; //授权信息

242
engine/HttpEngine/ToWeb.cpp Normal file
View File

@ -0,0 +1,242 @@
//
// Created by matrixai on 7/22/24.
//
#include "ToWeb.h"
namespace ai_matrix
{
ToWeb *ToWeb::ins = nullptr;
ToWeb::GarbageCollector ToWeb::gc;
std::mutex ToWeb::mx;
ToWeb *ToWeb::getins()
{
//双层锁,确保线程安全
if (ins == nullptr)
{
std::lock_guard<std::mutex> guard(mx); //防止异常发生不能解锁
if (ins == nullptr)
{
ins = new ToWeb();
}
}
return ins;
}
void ToWeb::setConfig(const HttpServerConfig &httpConfig) {
this->httpConfig_ = httpConfig;
}
bool ToWeb::getToken() {
try
{
httplib::Client cli(this->httpConfig_.strIp, this->httpConfig_.iPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(0,300*1000);
httplib::Headers header;
httplib::Params params;
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", this->httpConfig_.strUserName);
params.emplace("password", this->httpConfig_.strPassword);
params.emplace("tenantId", "000000");
params.emplace("grant_type", "password");
auto res = cli.Post(this->httpConfig_.strTokenUrl, header, params);
if (res)
{
if (res->status == 200)
{
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (!root.get("token_type", "").asString().empty())
{
this->webToken = root["token_type"].asString();
this->webToken.append(" ");
this->webToken.append(root["access_token"].asString());
LogInfo << "已获取到web token";
return true;
}
else
{
LogError << "获取web token失败原因" << res->body;
}
}
else
{
LogError << "获取web token返回数据解析异常返回数据非json。详细" << res->body;
}
}
}
else
{
auto err = res.error();
// if (err == httplib::Error::Connection) {
// std::cout << " (连接出错)" << std::endl;
// }
LogError << "获取web token失败请检查网络或请求地址。详细" << to_string(err);
}
}
catch (std::exception &e)
{
LogError << "获取授权失败,原因:";
LogError << e.what();
}
return false;
}
bool ToWeb::upWeb(const Json::Value &jvRequest, int retransmission) {
try {
if (this->webToken.empty()) this->getToken();
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, jvRequest);
LogInfo << "" << jvRequest["carriageOrder"].asString() << "发送web: " << str;
httplib::Client cli(this->httpConfig_.strIp, this->httpConfig_.iPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(3,0);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->httpConfig_.strUpResultUrl, header, str, "application/json");
if (res)
{
if (res->status == 200)
{
LogInfo << "" << jvRequest["carriageOrder"].asString() << "web返回: " << res->body;
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
LogWarn << "" << jvRequest["carriageOrder"].asString() << "因请求未授权而上传识别结果失败重新请求token。";
if (!this->getToken()) return false;
return this->upWeb(jvRequest, retransmission);
}
LogError << "" << jvRequest["carriageOrder"].asString() << "节,识别结果上传失败,原因:" << root["msg"].asString();
}
}
else
{
LogError << "" << jvRequest["carriageOrder"].asString() << "识别结果上传失败返回数据解析异常返回数据非json" + res->body;
}
}
else
{
LogError << "" << jvRequest["carriageOrder"].asString() << "节,识别结果上传失败,原因:" << res->status << " - " << res->body;
if (res->status == 401) {
LogWarn << "因请求未授权而上传识别结果失败重新请求token。";
this->getToken();
return this->upWeb(jvRequest, retransmission);
}
}
}
else
{
LogError << "" << jvRequest["carriageOrder"].asString() << "节,上传数据失败(超时),请检查网络,或者上传地址!计划重新上传次数:" << retransmission;
if (retransmission > 0) return this->upWeb(jvRequest, --retransmission);
}
}
catch (std::exception &e)
{
LogError << "" << jvRequest["carriageOrder"].asString() << "节,上传识别结果失败,原因:";
LogError << e.what();
}
return false;
}
bool ToWeb::upDeviceStatus(const Json::Value &jvRequest, int retransmission) {
try {
if (this->webToken.empty()) this->getToken();
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, jvRequest);
LogInfo << "设备状态报警发送web: " << str;
httplib::Client cli(this->httpConfig_.strIp, this->httpConfig_.iPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(3,0);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->httpConfig_.strDeviceStatusUrl, header, str, "application/json");
if (res)
{
if (res->status == 200)
{
LogInfo << "设备状态报警web返回: " << res->body;
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
LogWarn << "设备状态报警因请求未授权而上传识别状态失败重新请求token。";
if (!this->getToken()) return false;
return this->upDeviceStatus(jvRequest, retransmission);
}
LogError << "设备状态报警,识别状态上传失败,原因:" << root["msg"].asString();
}
}
else
{
LogError << "设备状态报警识别状态上传失败返回数据解析异常返回数据非json" + res->body;
}
}
else
{
LogError << "设备状态报警,识别状态上传失败,原因:" << res->status << " - " << res->body;
if (res->status == 401) {
LogWarn << "因请求未授权而上传识别状态失败重新请求token。";
this->getToken();
return this->upDeviceStatus(jvRequest, retransmission);
}
}
}
else
{
LogError << "设备状态报警,上传数据失败(超时),请检查网络,或者上传地址!计划重新上传次数:" << retransmission;
if (retransmission > 0) return this->upDeviceStatus(jvRequest, --retransmission);
}
}
catch (std::exception &e)
{
LogError << "设备状态报警,上传识别状态失败,原因:";
LogError << e.what();
}
return false;
}
}

65
engine/HttpEngine/ToWeb.h Normal file
View File

@ -0,0 +1,65 @@
//
// Created by matrixai on 7/22/24.
//
#ifndef TRAIN_RFID_LINUX_TOWEB_H
#define TRAIN_RFID_LINUX_TOWEB_H
#include "Log.h"
#include "Config.h"
#include "json/json.h"
#include "httplib.h"
#include "AppCommon.h"
namespace ai_matrix
{
class ToWeb final
{
public:
static ToWeb *getins();
std::string webToken; //授权信息
HttpServerConfig httpConfig_;
void setConfig(const HttpServerConfig &httpConfig);
bool getToken();
// 列车信息提交http接口
bool upWeb(const Json::Value &jvRequest, int retransmission = 0);
// 上传车号识别状态
bool upDeviceStatus(const Json::Value &jvRequest, int retransmission = 0);
// 获取火车状态(仅程序运行时运行一次)
bool getTrainStatus(const std::string &strPoundNo, Json::Value &jvResponse, int retransmission = 0);
private:
ToWeb() = default;
ToWeb(const ToWeb &) = delete;
ToWeb(ToWeb &&) = delete;
ToWeb &operator=(const ToWeb &) = delete;
ToWeb &operator=(ToWeb &&) = delete;
~ToWeb() = default;
//定义一个嵌套类,负责释放内存,操作系统自动完成,不用担心内存泄露
class GarbageCollector
{
public:
~GarbageCollector()
{
if (ToWeb::ins)
{
delete ToWeb::ins;
ToWeb::ins = nullptr;
}
}
};
static GarbageCollector gc;
static ToWeb *ins;
static std::mutex mx; //锁,保证线程安全
};
}
#endif //TRAIN_RFID_LINUX_TOWEB_H

View File

@ -0,0 +1,104 @@
#include "UpDeviceStatusEngine.h"
#undef DISABLE_SSH_AGENT
namespace
{
std::map<std::string, std::string> mapAscii = {
{"!", "%21"},
{"#", "%23"},
{"$", "%24"},
{"%", "%25"},
{"&", "%26"},
{"@", "%40"},
{"*", "%2A"}
};
}
UpDeviceStatusEngine::UpDeviceStatusEngine() {}
UpDeviceStatusEngine::~UpDeviceStatusEngine() {}
APP_ERROR UpDeviceStatusEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->httpServerConfig_ = Config::GetIns()->getHttpServerConfig();
LogInfo << "UpDeviceStatusEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR UpDeviceStatusEngine::DeInit()
{
LogInfo << "HttpEngine DeInit ok";
return APP_ERR_OK;
}
APP_ERROR UpDeviceStatusEngine::Process()
{
int iRet = APP_ERR_OK;
while (!isStop_)
{
std::shared_ptr<void> pVoidData0 = nullptr;
inputQueMap_[strPort0_]->pop(pVoidData0);
if (nullptr == pVoidData0)
{
usleep(1000); //1ms
continue;
}
std::shared_ptr<DeviceStatus> pDeviceStatus = std::static_pointer_cast<DeviceStatus>(pVoidData0);
if (!this->httpServerConfig_.bIsUse) continue;
Json::Value arrayObj; //构建对象
arrayObj["tainsModule"] = "2";
arrayObj["networkStatus"] = pDeviceStatus->strNetworkStatus;
arrayObj["devName"] = pDeviceStatus->strDeviceName;
arrayObj["devSn"] = this->baseConfig_.strTrackName;
arrayObj["cpuData"] = "";
arrayObj["memoryUsage"] = std::to_string(this->getMemUsagePercent()) + "%";
arrayObj["devRunningStatus"] = pDeviceStatus->strDeviceRunningStatus;
arrayObj["devCheckResult"] = pDeviceStatus->strDeviceWarnInfo;
arrayObj["devIp"] = "";
arrayObj["devAccount"] = "";
Json::Value trainParams;
trainParams["poundNo"] = this->baseConfig_.strTrackName;
arrayObj["trainParams"] = trainParams;
if (!ToWeb::getins()->upDeviceStatus(arrayObj, 1))
{
// LogError << "第" << pTrainInfo->strOrder + "节,识别结果上传失败!";
}
}
return APP_ERR_OK;
}
float UpDeviceStatusEngine::getMemUsagePercent() {
try{
std::ifstream mem_info_stream("/proc/meminfo", std::ios_base::in);
std::string mem_total_key = "MemTotal:";
std::string mem_free_key = "MemFree:";
std::string line;
ulong total = 0, free = 0;
while (std::getline(mem_info_stream, line)) {
if (line.compare(0, mem_total_key.size(), mem_total_key) == 0) {
total = std::strtoul(line.c_str() + mem_total_key.size(), nullptr, 10);
} else if (line.compare(0, mem_free_key.size(), mem_free_key) == 0) {
free = std::strtoul(line.c_str() + mem_free_key.size(), nullptr, 10);
}
if (total != 0 && free != 0) {
break;
}
}
return (total - free) * 100.0 / total;
}
catch (...)
{
return 0;
}
}

View File

@ -0,0 +1,45 @@
/**
* web
* */
#ifndef HTTPUPRESULTENGINE_H
#define HTTPUPRESULTENGINE_H
#include "AppCommon.h"
#include "Config.h"
#include "EngineBase.h"
#include "EngineFactory.h"
#include "json/json.h"
#include "httplib.h"
#include "ToWeb.h"
using namespace ai_matrix;
class UpDeviceStatusEngine : public ai_matrix::EngineBase
{
public:
UpDeviceStatusEngine();
~UpDeviceStatusEngine();
APP_ERROR Init() override;
APP_ERROR DeInit() override;
APP_ERROR Process() override;
private:
std::string strPort0_;
ai_matrix::BaseConfig baseConfig_;
ai_matrix::HttpServerConfig httpServerConfig_;
// bool upWeb(std::shared_ptr<TrainInfo> pTrainInfo, int retransmission = 0);
bool getToken();
// 获取内存使用百分比
float getMemUsagePercent();
std::string webToken; //授权信息
};
ENGINE_REGIST(UpDeviceStatusEngine)
#endif

View File

@ -1,215 +0,0 @@
#include "HttpUpResultEngine.h"
#undef DISABLE_SSH_AGENT
namespace
{
std::map<std::string, std::string> mapAscii = {
{"!", "%21"},
{"#", "%23"},
{"$", "%24"},
{"%", "%25"},
{"&", "%26"},
{"@", "%40"},
{"*", "%2A"}
};
}
HttpUpResultEngine::HttpUpResultEngine() {}
HttpUpResultEngine::~HttpUpResultEngine() {}
APP_ERROR HttpUpResultEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
this->baseConfig_ = Config::GetIns()->getBaseConfig();
this->httpServerConfig_ = Config::GetIns()->getHttpServerConfig();
LogInfo << "HttpUpResultEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR HttpUpResultEngine::DeInit()
{
LogInfo << "HttpUpResultEngine DeInit ok";
return APP_ERR_OK;
}
bool HttpUpResultEngine::upWeb(std::shared_ptr<TrainInfo> pTrainInfo)
{
try {
Json::Value arrayObj; //构建对象
arrayObj["comeTime"] = pTrainInfo->strTrainTime;
arrayObj["collectTime"] = pTrainInfo->strNowTime;
arrayObj["carriageNumber"] = pTrainInfo->strCarriageNum;
arrayObj["carriageType"] = pTrainInfo->strCarriageType;
arrayObj["carriageOrder"] = pTrainInfo->strOrder;
arrayObj["steel"] = pTrainInfo->strRfidInfo;
Json::Value trainParams;
trainParams["poundNo"] = this->baseConfig_.strTrackName;
arrayObj["trainParams"] = trainParams;
Json::StreamWriterBuilder writer;
std::string str = Json::writeString(writer, arrayObj);
LogInfo << "" << pTrainInfo->strOrder << "发送web: " << str;
httplib::Client cli(this->httpServerConfig_.strIp, this->httpServerConfig_.iPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(3,0);
httplib::Headers header;
httplib::Params params;
header.emplace("blade-auth", this->webToken);
//header.emplace("Content-Type", "application/json");
auto res = cli.Post(this->httpServerConfig_.strUpResultUrl, header, str, "application/json");
if (res)
{
if (res->status == 200)
{
LogInfo << "" << pTrainInfo->strOrder << "web返回: " << res->body;
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (root["success"].asBool())
{
return true;
}
else
{
if (root["msg"].asString() == "请求未授权") {
LogWarn << "" << pTrainInfo->strOrder << "因请求未授权而上传识别结果失败重新请求token。";
if (!this->getToken()) return false;
return this->upWeb(pTrainInfo);
}
LogError << "" << pTrainInfo->strOrder << "节,识别结果上传失败,原因:" << root["msg"].asString();
}
}
else
{
LogError << "" << pTrainInfo->strOrder << "识别结果上传失败返回数据解析异常返回数据非json" + res->body;
}
}
else
{
LogError << "" << pTrainInfo->strOrder << "节,识别结果上传失败,原因:" << res->status << " - " << res->body;
if (res->status == 401) {
LogWarn << "因请求未授权而上传识别结果失败重新请求token。";
this->getToken();
return this->upWeb(pTrainInfo);
}
}
}
else
{
LogError << "" << pTrainInfo->strOrder << "节,上传数据失败,请检查网络,或者上传地址!";
}
}
catch (std::exception &e)
{
LogError << "" << pTrainInfo->strOrder << "节,上传识别结果失败,原因:";
LogError << e.what();
}
return false;
}
/**
* @brief:Http获取授权
* @param
* @return:
*/
bool HttpUpResultEngine::getToken()
{
try
{
httplib::Client cli(this->httpServerConfig_.strIp, this->httpServerConfig_.iPort);
cli.set_connection_timeout(0, 300 * 1000);
cli.set_read_timeout(0,300*1000);
httplib::Headers header;
httplib::Params params;
header.emplace("Authorization", "Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
params.emplace("username", this->httpServerConfig_.strUserName);
params.emplace("password", this->httpServerConfig_.strPassword);
params.emplace("tenantId", "000000");
params.emplace("grant_type", "password");
auto res = cli.Post(this->httpServerConfig_.strTokenUrl, header, params);
if (res)
{
if (res->status == 200)
{
Json::CharReaderBuilder readerBuilder;
std::istringstream iss(res->body);
Json::Value root;
std::string errs;
bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
if (parsingSuccessful)
{
if (!root.get("token_type", "").asString().empty())
{
this->webToken = root["token_type"].asString();
this->webToken.append(" ");
this->webToken.append(root["access_token"].asString());
LogInfo << "已获取到web token";
return true;
}
else
{
LogError << "获取web token失败原因" << res->body;
}
}
else
{
LogError << "获取web token返回数据解析异常返回数据非json。详细" << res->body;
}
}
}
else
{
auto err = res.error();
// if (err == httplib::Error::Connection) {
// std::cout << " (连接出错)" << std::endl;
// }
LogError << "获取web token失败请检查网络或请求地址。详细" << to_string(err);
}
}
catch (std::exception &e)
{
LogError << "获取授权失败,原因:";
LogError << e.what();
}
return false;
}
APP_ERROR HttpUpResultEngine::Process()
{
int iRet = APP_ERR_OK;
while (!isStop_)
{
std::shared_ptr<void> pVoidData0 = nullptr;
inputQueMap_[strPort0_]->pop(pVoidData0);
if (nullptr == pVoidData0)
{
usleep(1000); //1ms
continue;
}
std::shared_ptr<TrainInfo> pTrainInfo = std::static_pointer_cast<TrainInfo>(pVoidData0);
if (!this->httpServerConfig_.bIsUse) continue;
if (!this->upWeb(pTrainInfo))
{
// LogError << "第" << pTrainInfo->strOrder + "节,识别结果上传失败!";
}
}
return APP_ERR_OK;
}

View File

@ -10,6 +10,7 @@ VideoAuxiliaryEngine::~VideoAuxiliaryEngine() {}
APP_ERROR VideoAuxiliaryEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";
this->videoAuxiliaryConfig_ = Config::GetIns()->getVideoAuxiliaryConfig();
this->carType_ = "0";
@ -50,11 +51,27 @@ APP_ERROR VideoAuxiliaryEngine::Process()
if (!this->baseScoket_.bRuning())
{
LogError << "TCP 连接失败,重启中 ...";
std::shared_ptr<DeviceStatus> pDeviceStatus = std::make_shared<DeviceStatus>();
pDeviceStatus->strDeviceName = "RFID程序";
pDeviceStatus->strDeviceRunningStatus = "正常";
pDeviceStatus->strNetworkStatus = "异常";
pDeviceStatus->strDeviceWarnInfo = "“RFID车号识别”同“视频车号识别”的通讯断开";
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pDeviceStatus));
usleep(20 * 1000 * 1000); // 20秒后重试
this->baseScoket_.Close();
this->baseScoket_.Open();
this->baseScoket_.Init();
if (this->baseScoket_.bRuning())
{
LogInfo << "TCP 连接成功!";
std::shared_ptr<DeviceStatus> pDeviceStatus = std::make_shared<DeviceStatus>();
pDeviceStatus->strDeviceName = "RFID程序";
pDeviceStatus->strDeviceRunningStatus = "正常";
pDeviceStatus->strNetworkStatus = "正常";
pDeviceStatus->strDeviceWarnInfo = "“RFID车号识别”同“视频车号识别”的通讯连接成功";
outputQueMap_[strPort1_]->push(std::static_pointer_cast<void>(pDeviceStatus));
}
continue;
}

View File

@ -32,6 +32,7 @@ public:
private:
std::string strPort0_;
std::string strPort1_;
ai_matrix::VideoAuxiliaryConfig videoAuxiliaryConfig_;
BaseSocket baseScoket_;

View File

@ -8,6 +8,7 @@
#include "EngineManager.h"
#include "AppCommon.h"
#include "ToWeb.h"
//using namespace ns_https_sn;
using namespace ai_matrix;
@ -48,6 +49,8 @@ int main(int argc, const char *argv[])
return -1;
}
ToWeb::getins()->setConfig(Config::GetIns()->getHttpServerConfig());
//捕获信号
if (signal(SIGINT, SigHandler) == SIG_ERR)
{