Train_Identify/nvidia_ascend_engine/common_engine/DataUploadEngine/ResultToHttpSrvEngine.cpp

446 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ResultToHttpSrvEngine.h"
#include "myutils.h"
ResultToHttpSrvEngine::ResultToHttpSrvEngine() {}
ResultToHttpSrvEngine::~ResultToHttpSrvEngine() {}
APP_ERROR ResultToHttpSrvEngine::Init()
{
strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
strUsername_ = MyYaml::GetIns()->GetStringValue("username");
strPassword_ = MyYaml::GetIns()->GetStringValue("password");
strURL_ = MyYaml::GetIns()->GetStringValue("gc_http_url");
strGetTokenURL_ = MyYaml::GetIns()->GetStringValue("gc_gettoken_url");
strImageSrv_ = MyYaml::GetIns()->GetPathValue("gc_image_srv");
strPoundNo_ = MyYaml::GetIns()->GetStringValue("atlas_poundno");
strFailSavePath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent.csv";
strFailSaveBakPath_ = MyYaml::GetIns()->GetPathValue("gc_result_path") + "httpfailcontent_bak.csv";
LogInfo << "ResultToHttpSrvEngine Init ok";
return APP_ERR_OK;
}
APP_ERROR ResultToHttpSrvEngine::DeInit()
{
LogDebug << "curl_easy_cleanup";
curl_easy_cleanup(pCurl_);
/* 这个处理移动到main中 防止多线程调用
LogDebug << "内存清理";
curl_global_cleanup();
*/
LogInfo << "ResultToHttpSrvEngine DeInit ok";
return APP_ERR_OK;
}
/**
* libcurl回调函数
* inParam : void *pBuffer 回调内容地址
: size_t size 回调单个数据大小
: size_t nmemb 回调数据个数
* outParam: std::string &strResp 返回内容
* return : 回调数据大小
*/
size_t ResultToHttpSrvEngine::WriteCallBack(void *pBuffer, size_t size, size_t nmemb, std::string &strResp)
{
size_t sizes = size * nmemb;
std::string strTemp((char*)pBuffer, sizes);
strResp += strTemp;
return sizes;
}
/**
* 调用http接口获取token
* inParam :
* outParam: std::string &strBladeAuth 返回的token信息
* return : true:成功; false:失败
*/
bool ResultToHttpSrvEngine::GetToken(std::string &strBladeAuth)
{
//1. 获得curl操作符
if (nullptr == pCurl_)
{
LogDebug<<"pCurl_ is null, invoke curl_easy_init";
pCurl_ = curl_easy_init();
if (nullptr == pCurl_)
{
LogError << "curl_easy_init failed !";
return false;
}
}
//2. 设置head, 和表单
//设置head信息
struct curl_slist *pHeaderList = nullptr;
pHeaderList = curl_slist_append(pHeaderList, "Authorization:Basic Y2xpZW50X2VudGVycHJpc2U6Y2xpZW50X2VudGVycHJpc2Vfc2VjcmV0");
//设置表单信息
curl_mime *pMultipart = curl_mime_init(pCurl_);
curl_mimepart *pPart = curl_mime_addpart(pMultipart);
curl_mime_name(pPart, "username");
curl_mime_data(pPart, strUsername_.c_str(), CURL_ZERO_TERMINATED);
pPart = curl_mime_addpart(pMultipart);
curl_mime_name(pPart, "password");
curl_mime_data(pPart, strPassword_.c_str(), CURL_ZERO_TERMINATED);
pPart = curl_mime_addpart(pMultipart);
curl_mime_name(pPart, "tenantId");
curl_mime_data(pPart, "000000", CURL_ZERO_TERMINATED);
pPart = curl_mime_addpart(pMultipart);
curl_mime_name(pPart, "grant_type");
curl_mime_data(pPart, "password", CURL_ZERO_TERMINATED);
curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时)
curl_easy_setopt(pCurl_, CURLOPT_URL, strGetTokenURL_.c_str()); //设置url
curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头
curl_easy_setopt(pCurl_, CURLOPT_MIMEPOST, pMultipart); //设置表单
//curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strBody.c_str()); //设置post内容
//curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post)
curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数
std::string strResponse;
curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数
//3. 执行http请求
CURLcode res = curl_easy_perform(pCurl_);
curl_slist_free_all(pHeaderList); //清除headerlist
curl_mime_free(pMultipart); //清除curl_mime
curl_easy_reset(pCurl_); //重置curl
if (res != CURLE_OK)
{
LogError << " curl_easy_perform fail:" << curl_easy_strerror(res);
return false;
}
//4. 执行成功解析响应内容
Json::CharReaderBuilder readerBuilder;
std::shared_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
Json::Value jvResponse;
JSONCPP_STRING errs;
if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs))
{
LogError << " response content fail " << strResponse;
return false;
}
LogDebug << "GetToken resp:" << strResponse;
strBladeAuth += jvResponse["token_type"].asString();
strBladeAuth += " ";
strBladeAuth += jvResponse["access_token"].asString();
return true;
}
/**
* 列车信息提交http接口
* inParam : Json::Value &jvRequest 提交内容
* outParam:
* return : true:提交成功; false:提交失败
*/
bool ResultToHttpSrvEngine::ResultToHttpSrv(Json::Value &jvRequest)
{
//获取token
std::string strBladeAuth("blade-auth:");
if (!GetToken(strBladeAuth))
{
LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt() << " GetToken fail ";
return false;
}
LogDebug << "strBladeAuth:" << strBladeAuth;
//1. 获得curl操作符
if (nullptr == pCurl_)
{
LogDebug<<"pCurl_ is null, invoke curl_easy_init";
pCurl_ = curl_easy_init();
if (nullptr == pCurl_)
{
LogError << "curl_easy_init failed !";
return false;
}
}
//2. 设置http请求信息
Json::StreamWriterBuilder jswBuilder;
std::string strRequest = Json::writeString(jswBuilder, jvRequest);
LogDebug << "to http:" << strRequest;
std::string strResponse;
struct curl_slist *pHeaderList = nullptr;
pHeaderList = curl_slist_append(pHeaderList, "Accept:application/json");
pHeaderList = curl_slist_append(pHeaderList, "Content-Type:application/json");
pHeaderList = curl_slist_append(pHeaderList, "charset:utf-8");
pHeaderList = curl_slist_append(pHeaderList, strBladeAuth.c_str());
curl_easy_setopt(pCurl_, CURLOPT_CONNECTTIMEOUT, 1); //连接超时(1s连接不上服务器返回超时)
curl_easy_setopt(pCurl_, CURLOPT_URL, strURL_.c_str()); //设置url
curl_easy_setopt(pCurl_, CURLOPT_HTTPHEADER, pHeaderList); //设置报文头
curl_easy_setopt(pCurl_, CURLOPT_POSTFIELDS, strRequest.c_str()); //设置post内容
curl_easy_setopt(pCurl_, CURLOPT_POST, 1); //设置操作为POST(为非0表示post)
curl_easy_setopt(pCurl_, CURLOPT_WRITEFUNCTION, WriteCallBack); //设置回调函数
curl_easy_setopt(pCurl_, CURLOPT_WRITEDATA, &strResponse); //设置回调参数
//3. 执行http请求
CURLcode res = curl_easy_perform(pCurl_);
curl_slist_free_all(pHeaderList); //清除headerlist
curl_easy_reset(pCurl_); //重置curl
if (res != CURLE_OK)
{
LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt()
<< " curl_easy_perform fail:" << curl_easy_strerror(res);
return false;
}
//4. 执行成功解析响应内容
LogInfo << "http resp:" << strResponse;
Json::CharReaderBuilder readerBuilder;
std::shared_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
Json::Value jvResponse;
JSONCPP_STRING errs;
if (!reader->parse(strResponse.data(), strResponse.data() + strResponse.size(), &jvResponse, &errs))
{
LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt()
<< " response content fail " << strResponse;
return false;
}
if (!jvResponse["success"].asBool())
{
LogError << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt()
<< " response fail";
return false;
}
LogInfo << "comeTime:" << jvRequest["comeTime"].asString() << " carriageOrder:" << jvRequest["carriageOrder"].asInt()
<< " post success";
return true;
}
/**
* 处理上传失败的信息
* inParam : N/A
* outParam: N/A
* return : N/A
*/
void ResultToHttpSrvEngine::DealHttpFailInfo()
{
//队列有待处理数据,则先不处理异常数据。
if (inputQueMap_[strPort0_]->getSize() > 0)
{
LogDebug << "have new data to process";
return;
}
//文件不存在不处理
if (access(strFailSavePath_.c_str(), F_OK) == -1)
{
LogDebug << "no exit file:" << strFailSavePath_;
return;
}
bool bAllSucc = true;
std::ifstream inFile(strFailSavePath_.c_str(), std::ios::in);
if (!inFile.is_open())
{
LogError << strFailSavePath_ << " open fail";
return;
}
int iDealCnt = 0;
std::string strLine;
while (getline(inFile, strLine))
{
Json::CharReaderBuilder jsrBuilder;
std::shared_ptr<Json::CharReader> reader(jsrBuilder.newCharReader());
Json::Value jvRequest;
JSONCPP_STRING errs;
if (!reader->parse(strLine.data(), strLine.data() + strLine.size(), &jvRequest, &errs))
{
LogError << "json parse fail content:" << strLine;
return;
}
/*
新数据到达后,异常数据还未开始处理,则直接关闭文件返回。先处理正常数据。
新数据到达后,异常数据处理中,则把异常未处理的数据全部当处理失败写入新文件中。先处理正常数据。
*/
if (inputQueMap_[strPort0_]->getSize() > 0)
{
LogDebug << "Abnormal data processing, have new data to process";
if (0 == iDealCnt)
{
LogDebug << "Abnormal data processing not start";
inFile.close();
return;
}
SaveHttpFailInfo(jvRequest, strFailSaveBakPath_);
bAllSucc = false;
continue;
}
iDealCnt++;
if (!ResultToHttpSrv(jvRequest))
{
LogError << "re http post err:" << strLine;
//SaveHttpFailInfo(jvRequest, strFailSaveBakPath_);
// bAllSucc = false;
continue;
}
}
inFile.close();
if(bAllSucc)
{
//都处理成功,文件删除
remove(strFailSavePath_.c_str());
}
else
{
//部分处理成功,重命名后再次被处理
rename(strFailSaveBakPath_.c_str(), strFailSavePath_.c_str());
}
}
/**
* 保存http上传失败的信息
* inParam : Json::Value &jvRequest http失败信息
* : std::string &strFilePath 保存路径
* outParam: N/A
* return : true(成功);false(失败)
*/
bool ResultToHttpSrvEngine::SaveHttpFailInfo(Json::Value &jvRequest, std::string &strFilePath)
{
std::ofstream outFile;
outFile.open(strFilePath, std::ios::app);
if (!outFile.is_open())
{
LogError << strFilePath << " open fail";
return false;
}
Json::StreamWriterBuilder jswBuilder;
jswBuilder["indentation"] = "";
std::string strRequest = Json::writeString(jswBuilder, jvRequest);
outFile << strRequest << std::endl;
outFile.close();
return true;
}
APP_ERROR ResultToHttpSrvEngine::Process()
{
int iRet = APP_ERR_OK;
if (0 == MyYaml::GetIns()->GetIntValue("gc_http_open"))
{
LogDebug << " gc_http_open value is 0";
return APP_ERR_OK;
}
while (!isStop_)
{
std::shared_ptr<void> pVoidData0 = nullptr;
inputQueMap_[strPort0_]->pop(pVoidData0);
if (nullptr == pVoidData0)
{
usleep(1000); //1ms
//无数据大于1分钟
iNoDataCnt_++;
if (iNoDataCnt_ > (60 * 1000))
{
DealHttpFailInfo();
iNoDataCnt_ = 0;
}
continue;
}
iNoDataCnt_ = 0;
std::shared_ptr<Train> pTrain = std::static_pointer_cast<Train>(pVoidData0);
ai_matrix::DataSourceConfig dataSourceConfig = MyYaml::GetIns()->GetDataSourceConfigById(pTrain->trainNum.iDataSource); //获取摄像机参数
char szCameraNo[4] = {0};
sprintf(szCameraNo, "%03d", pTrain->trainNum.iDataSource + 1);
char szNumImgPath[64] = {0}; //车号最优图片路径
if (!pTrain->trainNum.strBestImg.empty())
{
sprintf(szNumImgPath, "/%03d/%s", pTrain->trainNum.iDataSource + 1, pTrain->trainNum.strBestImg.c_str());
}
char szProImgPath[64] = {0}; //属性最优图片路径
if (!pTrain->trainPro.strBestImg.empty())
{
sprintf(szProImgPath, "/%03d/%s", pTrain->trainPro.iDataSource + 1, pTrain->trainPro.strBestImg.c_str());
}
// char szChkDateImgPath[64] = {0}; //定检期最优图片路径
// if (!pTrain->chkDate.strBestImg.empty())
// {
// sprintf(szChkDateImgPath, "%03d/%s", pTrain->chkDate.iDataSource + 1, pTrain->chkDate.strBestImg.c_str());
// }
// char szContainer1ImgPath[64] = {0}; //集装箱1最优图片路径
// if (!pTrain->container1.strBestImg.empty())
// {
// sprintf(szContainer1ImgPath, "%03d/%s", pTrain->container1.iDataSource + 1, pTrain->container1.strBestImg.c_str());
// }
// char szContainer2ImgPath[64] = {0}; //集装箱2最优图片路径
// if (!pTrain->container2.strBestImg.empty())
// {
// sprintf(szContainer2ImgPath, "%03d/%s", pTrain->container2.iDataSource + 1, pTrain->container2.strBestImg.c_str());
// }
std::string strTime = pTrain->strTrainName;
strTime = MyUtils::getins()->replace_all_distinct(strTime, std::string("-"), std::string(":"));
int iCategory = 0;
if (pTrain->trainNum.iTrainTypeId == 3)
{
iCategory = 0;
}
else if(pTrain->trainNum.iTrainTypeId == 2)
{
iCategory = 1;
}
else if (pTrain->trainNum.iTrainTypeId == 6)
{
iCategory = 2;
}
else if (pTrain->trainNum.iTrainTypeId == 0)
{
iCategory = 3;
}
//组装post信息
Json::Value jvRequest;
Json::Value jvSubObj;
jvSubObj["poundNo"] = strPoundNo_; // 股道号
jvRequest["trainParams"] = jvSubObj;
jvRequest["carriageType"] = pTrain->trainNum.strTrainType; // 车型
jvRequest["carriageNumber"] = pTrain->trainNum.strTrainNum; // 车厢号
jvRequest["carriageOrder"] = pTrain->iCarXH; // 车节号
jvRequest["cameraNumber"] = szCameraNo; // 摄像头编号
jvRequest["carriageTareweight"] = pTrain->trainPro.strSelf; // 皮重
jvRequest["carriageLoad"] = pTrain->trainPro.strLoad; // 载重
jvRequest["carriageVolume"] = pTrain->trainPro.strVolume; // 容积
jvRequest["carriageChangelength"] = pTrain->trainPro.strChange; // 换长
jvRequest["proImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szProImgPath; // 属性图片
jvRequest["numImageName"] = strImageSrv_ + pTrain->strTrainDate + "/" + pTrain->strTrainName + szNumImgPath; // 车号图片
jvRequest["comeTime"] = pTrain->strTrainDate + " " + strTime; // 来车时间
jvRequest["carriageCategory"] = iCategory; // 车厢类别:0敞车,1:漏洞矿车,2:平车,3:车头
jvRequest["isTheLast"] = pTrain->bIsEnd ? 1 : 0; // 是否最后一节: 0:否,1:是
jvRequest["startFrame"] = pTrain->iStartFrameId; //车厢开始帧
jvRequest["endFrame"] = pTrain->iEndFrameId; //车厢结束帧
jvRequest["skipFrame"] = dataSourceConfig.iSkipInterval;
jvRequest["collectTime"] = MyUtils::getins()->Stamp2Time(pTrain->i64EndTimeStamp, true);//车厢切分的时间 //跳帧
if (!ResultToHttpSrv(jvRequest))
{
// SaveHttpFailInfo(jvRequest, strFailSavePath_);
}
//列车结束后再次处理失败的信息
if (pTrain->bIsEnd)
{
DealHttpFailInfo();
}
}
return APP_ERR_OK;
}