master
parent
d4c76462fa
commit
97b4e8a36b
|
|
@ -19,7 +19,6 @@ find_package(HCNet CONFIG REQUIRED)
|
||||||
find_package(ICU REQUIRED COMPONENTS uc)
|
find_package(ICU REQUIRED COMPONENTS uc)
|
||||||
find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") # 使用时要先于 windows.h 包含
|
find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") # 使用时要先于 windows.h 包含
|
||||||
find_path(CPPCODEC_INCLUDE_DIRS "cppcodec/base32_crockford.hpp")
|
find_path(CPPCODEC_INCLUDE_DIRS "cppcodec/base32_crockford.hpp")
|
||||||
#find_library(WS2_32_LIB NAMES ws2_32)
|
|
||||||
set(SOURCE_DIRS
|
set(SOURCE_DIRS
|
||||||
src/common
|
src/common
|
||||||
src/vidicon
|
src/vidicon
|
||||||
|
|
@ -45,7 +44,6 @@ set(LINK_DIRS
|
||||||
src
|
src
|
||||||
)
|
)
|
||||||
set(LIBRARIES
|
set(LIBRARIES
|
||||||
# ${WS2_32_LIB}
|
|
||||||
openssl::libssl
|
openssl::libssl
|
||||||
openssl::libcrypto
|
openssl::libcrypto
|
||||||
mqtt_cpp_iface::mqtt_cpp_iface
|
mqtt_cpp_iface::mqtt_cpp_iface
|
||||||
|
|
@ -78,5 +76,5 @@ target_compile_definitions(${PROJECT_NAME} PUBLIC
|
||||||
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO # 启用日志宏
|
SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO # 启用日志宏
|
||||||
CPPHTTPLIB_OPENSSL_SUPPORT # httplib 支持 openssl
|
CPPHTTPLIB_OPENSSL_SUPPORT # httplib 支持 openssl
|
||||||
MQTT_STD_VARIANT
|
MQTT_STD_VARIANT
|
||||||
_WIN32_WINNT=0x0601
|
_WIN32_WINNT=0x0A00
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
"name": "测试",
|
"name": "测试",
|
||||||
"delay": 0,
|
"delay": 0,
|
||||||
"daemon": false,
|
"daemon": false,
|
||||||
|
"embedMqtt": true,
|
||||||
"httpSvr": {
|
"httpSvr": {
|
||||||
"port": 11000
|
"port": 11000
|
||||||
},
|
},
|
||||||
|
|
@ -94,7 +95,10 @@
|
||||||
{
|
{
|
||||||
"sn": "1",
|
"sn": "1",
|
||||||
"name": "地磅",
|
"name": "地磅",
|
||||||
|
"delay": 5,
|
||||||
"sample": 20,
|
"sample": 20,
|
||||||
|
"retries": 30,
|
||||||
|
"weight": 200.0,
|
||||||
"port": "COM2",
|
"port": "COM2",
|
||||||
"baudRate": 9600,
|
"baudRate": 9600,
|
||||||
"byteSize": 8,
|
"byteSize": 8,
|
||||||
|
|
@ -114,7 +118,7 @@
|
||||||
{
|
{
|
||||||
"sn": "1",
|
"sn": "1",
|
||||||
"name": "摄像头",
|
"name": "摄像头",
|
||||||
"ip": "",
|
"ip": "127.0.0.1",
|
||||||
"port": 8000,
|
"port": 8000,
|
||||||
"username": "",
|
"username": "",
|
||||||
"passwd": ""
|
"passwd": ""
|
||||||
|
|
|
||||||
|
|
@ -52,17 +52,11 @@ namespace zsy
|
||||||
{
|
{
|
||||||
std::jthread t([recognizeResult,name,sn]
|
std::jthread t([recognizeResult,name,sn]
|
||||||
{
|
{
|
||||||
LOGGER_INFO("正在处理车牌识别结果:{} {}", name, sn);
|
LOGGER_INFO("正在处理车牌识别结果:{}、{}、{}", recognizeResult->license, name, sn);
|
||||||
RecognizeProcessor::process(recognizeResult);
|
RecognizeProcessor::process(recognizeResult);
|
||||||
LOGGER_INFO("车牌识别结果处理完成");
|
LOGGER_INFO("车牌识别结果处理完成");
|
||||||
});
|
});
|
||||||
t.detach();
|
t.detach();
|
||||||
/*Application::threadPool->submit([recognizeResult,name,sn]
|
|
||||||
{
|
|
||||||
LOGGER_INFO("正在处理车牌识别结果:{} {}", name, sn);
|
|
||||||
RecognizeProcessor::process(recognizeResult);
|
|
||||||
LOGGER_INFO("车牌识别结果处理完成");
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
} catch (std::exception &e)
|
} catch (std::exception &e)
|
||||||
{
|
{
|
||||||
|
|
@ -177,77 +171,4 @@ namespace zsy
|
||||||
return std::make_tuple(false, nullptr, "", "");
|
return std::make_tuple(false, nullptr, "", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void GenericBarrier::resolveRecognizeResult(const std::string &license, const std::string &imageFile)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LOGGER_INFO("车牌识别结果处理中,设备名称:{}", config.name);
|
|
||||||
// 播放语音 1
|
|
||||||
std::thread t1([sn = config.sn,name = config.name]
|
|
||||||
{
|
|
||||||
size_t found = name.find("前置");
|
|
||||||
|
|
||||||
if (found != std::string::npos)
|
|
||||||
{
|
|
||||||
Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 上传车头照
|
|
||||||
auto imageFileDecode = SysUtil::base64_decode(imageFile);
|
|
||||||
const std::shared_ptr<std::istream> imageFileStream = std::make_shared<std::istringstream>(imageFileDecode, std::ios_base::in | std::ios_base::binary);
|
|
||||||
auto photoId = Snowflake::genIdStr();
|
|
||||||
auto now = std::chrono::system_clock::now();
|
|
||||||
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
|
|
||||||
|
|
||||||
std::tm *localTime = std::localtime(¤tTime);
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::put_time(localTime, "%Y%m%d");
|
|
||||||
|
|
||||||
std::string date = ss.str();
|
|
||||||
auto [carFrontUrlSucc,carFrontUrl] = Application::oss->upload(date + "/" + "front_" + photoId + ".jpg", *imageFileStream);
|
|
||||||
// 上报 1
|
|
||||||
auto reportPassResult = Application::reportSvr->reportPass(license, config.sn, carFrontUrl);
|
|
||||||
if (!(reportPassResult.code == 0 && (reportPassResult.data.type == 1 || reportPassResult.data.type == 2)))
|
|
||||||
{
|
|
||||||
LOGGER_INFO("不处理:{}", config.name);
|
|
||||||
t1.join();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上报结果不为 0,播放语音 2 并读地磅,拍车斗并上传
|
|
||||||
std::thread t2([sn = config.sn]
|
|
||||||
{
|
|
||||||
Application::deviceHolder->getSoundColumn(sn)->play("正在称重,请稍后");
|
|
||||||
});
|
|
||||||
double weight = Application::deviceHolder->getPlatformScale(config.sn)->reading();
|
|
||||||
auto photographPath = Application::deviceHolder->getVidicon(config.sn)->photograph();
|
|
||||||
auto [carBodyUrlSucc,carBodyUrl] = Application::oss->upload(date + "/" + "body_" + photoId + ".jpg", photographPath);
|
|
||||||
if (!photographPath.empty())
|
|
||||||
{
|
|
||||||
auto pathPtr = SysUtil::ch_vlt(photographPath.c_str());
|
|
||||||
if (std::remove(pathPtr.get()) != 0)
|
|
||||||
{
|
|
||||||
auto [_,code,msg] = SysUtil::getError();
|
|
||||||
LOGGER_ERROR("临时照片删除失败:{},错误码:{},错误信息:{}", photographPath, code, msg);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
LOGGER_ERROR("临时照片删除成功:{}", photographPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上报 2
|
|
||||||
Application::reportSvr->report(license, config.sn, weight, carFrontUrl, carBodyUrl, reportPassResult.data.orderNo);
|
|
||||||
t1.join();
|
|
||||||
t2.join();
|
|
||||||
} catch (std::exception &e)
|
|
||||||
{
|
|
||||||
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
LOGGER_ERROR("未知异常,车牌识别结果处理失败");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} // zsy
|
} // zsy
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include "daily_and_size_sink.h"
|
#include "daily_and_size_sink.h"
|
||||||
|
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include "utils/date_util.h"
|
|
||||||
|
#include "date_util.h"
|
||||||
|
|
||||||
namespace zsy
|
namespace zsy
|
||||||
{
|
{
|
||||||
|
|
@ -70,25 +70,9 @@ namespace zsy
|
||||||
if (std::regex_match(filename, match, file_pattern))
|
if (std::regex_match(filename, match, file_pattern))
|
||||||
{
|
{
|
||||||
std::string date_str = match[1].str();
|
std::string date_str = match[1].str();
|
||||||
|
std::chrono::sys_days date;
|
||||||
std::istringstream tstr(date_str);
|
std::istringstream tstr(date_str);
|
||||||
int year, month, day;
|
tstr >> std::chrono::parse("%F", date);
|
||||||
char dash1, dash2;
|
|
||||||
|
|
||||||
// 解析字符串(格式:YYYY-MM-DD)
|
|
||||||
std::istringstream iss(date_str);
|
|
||||||
if (!(iss >> year >> dash1 >> month >> dash2 >> day) || dash1 != '-' || dash2 != '-')
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("无效的日期格式,需为 YYYY-MM-DD");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::year_month_day ymd(std::chrono::year{year},
|
|
||||||
std::chrono::month{(unsigned) month}, std::chrono::day{(unsigned) day});
|
|
||||||
if (!ymd.ok())
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("无效的日期");
|
|
||||||
}
|
|
||||||
std::chrono::sys_days date{ymd};
|
|
||||||
|
|
||||||
if (date < cutoff_time)
|
if (date < cutoff_time)
|
||||||
{
|
{
|
||||||
std::filesystem::remove(entry.path());
|
std::filesystem::remove(entry.path());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "date_util.h"
|
#include "date_util.h"
|
||||||
|
|
||||||
|
#include "HCNetSDK.h"
|
||||||
|
|
||||||
namespace zsy
|
namespace zsy
|
||||||
{
|
{
|
||||||
std::string DateUtil::format(const std::string &pattern, const TimePoint dt)
|
std::string DateUtil::format(const std::string &pattern, const TimePoint dt)
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,42 @@
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "common/date_util.h"
|
#include "common/date_util.h"
|
||||||
#include "common/snowflake.h"
|
#include "common/snowflake.h"
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
namespace zsy
|
namespace zsy
|
||||||
{
|
{
|
||||||
Test::Test()
|
Test::Test() : type(0)
|
||||||
{
|
{
|
||||||
|
Application::httpSvr->getEndpoint("/type", [this](const httplib::Request &req, httplib::Response &res)
|
||||||
|
{
|
||||||
|
std::string type = req.get_param_value("type");
|
||||||
|
if (type.empty())
|
||||||
|
{
|
||||||
|
res.set_content("未指定类型:0-->前置、1-->进、2-->出", "application/json");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->type = std::stoi(type);
|
||||||
|
|
||||||
|
res.set_content("已改为" + type, "application/json");
|
||||||
|
});
|
||||||
|
|
||||||
Application::httpSvr->postEndpoint("/api/site/report-car-pass", [this](const httplib::Request &req, httplib::Response &res)
|
Application::httpSvr->postEndpoint("/api/site/report-car-pass", [this](const httplib::Request &req, httplib::Response &res)
|
||||||
{
|
{
|
||||||
|
auto type = this->type;
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
std::string data = R"({
|
res.set_content( fmt::format(
|
||||||
"code": 0,
|
R"({{
|
||||||
"msg": "",
|
"code": 0,
|
||||||
"data": {
|
"msg": "",
|
||||||
"car_number": "",
|
"data": {{
|
||||||
"type": 2,
|
"car_number": "",
|
||||||
"order_no": "",
|
"type": {},
|
||||||
"err_msg": "",
|
"order_no": "",
|
||||||
"scene": "",
|
"err_msg": "",
|
||||||
"no_weight": false
|
"scene": "",
|
||||||
}
|
"no_weight": false
|
||||||
})";
|
}}
|
||||||
res.set_content(data, "application/json");
|
}})", type), "application/json");
|
||||||
});
|
});
|
||||||
Application::httpSvr->postEndpoint("/api/site/report-v2", [this](const httplib::Request &req, httplib::Response &res)
|
Application::httpSvr->postEndpoint("/api/site/report-v2", [this](const httplib::Request &req, httplib::Response &res)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#ifndef TEST_H
|
#ifndef TEST_H
|
||||||
#define TEST_H
|
#define TEST_H
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
namespace zsy
|
namespace zsy
|
||||||
{
|
{
|
||||||
class Test
|
class Test
|
||||||
{
|
{
|
||||||
|
int type;
|
||||||
public:
|
public:
|
||||||
Test();
|
Test();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,14 @@ namespace zsy
|
||||||
// 0-->不可用、1-->可用
|
// 0-->不可用、1-->可用
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
std::shared_mutex status_mtx;
|
std::shared_mutex status_mtx;
|
||||||
std::unique_ptr<httplib::Server> svr;
|
|
||||||
std::unique_ptr<std::thread> svrThread;
|
std::unique_ptr<std::thread> svrThread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::unique_ptr<httplib::Server> svr;
|
||||||
explicit HttpSvr(const nlohmann::json &config);
|
explicit HttpSvr(const nlohmann::json &config);
|
||||||
|
|
||||||
template<typename Func>
|
template<typename Func>
|
||||||
|
requires std::invocable<Func, const httplib::Request&, httplib::Response&>
|
||||||
void postEndpoint(std::string path, Func &&handler)
|
void postEndpoint(std::string path, Func &&handler)
|
||||||
{
|
{
|
||||||
std::shared_lock lock(status_mtx);
|
std::shared_lock lock(status_mtx);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace zsy
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOGGER_ERROR("MQTT:{} 正在连接...", config.clientId);
|
LOGGER_INFO("MQTT:{} 正在连接...", config.clientId);
|
||||||
ioc = std::make_shared<boost::asio::io_context>();
|
ioc = std::make_shared<boost::asio::io_context>();
|
||||||
cli = MQTT_NS::make_sync_client(*ioc, config.server, config.port);
|
cli = MQTT_NS::make_sync_client(*ioc, config.server, config.port);
|
||||||
cli->set_keep_alive_sec(30);
|
cli->set_keep_alive_sec(30);
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,6 @@ namespace zsy
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOGGER_INFO("正在读取地磅数据,设备名称:{}", config.name);
|
LOGGER_INFO("正在读取地磅数据,设备名称:{}", config.name);
|
||||||
/*if (status != 1)
|
|
||||||
{
|
|
||||||
LOGGER_INFO("无法称重,地磅状态:{}", status);
|
|
||||||
return 0.0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
int retry_count = 0;
|
int retry_count = 0;
|
||||||
while ((serialPort->status.load() == 3 || serialPort->readStatus.load() == 3) && retry_count < 10)
|
while ((serialPort->status.load() == 3 || serialPort->readStatus.load() == 3) && retry_count < 10)
|
||||||
|
|
@ -113,11 +108,9 @@ namespace zsy
|
||||||
if (serialPort->status.load() == 3 || serialPort->readStatus.load() == 3)
|
if (serialPort->status.load() == 3 || serialPort->readStatus.load() == 3)
|
||||||
{
|
{
|
||||||
LOGGER_ERROR("无法称重,串口异常,重试失败");
|
LOGGER_ERROR("无法称重,串口异常,重试失败");
|
||||||
/*status = 1;*/
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*status = 2;*/
|
|
||||||
LOGGER_INFO("正在称重...");
|
LOGGER_INFO("正在称重...");
|
||||||
if (config.delay > 0) std::this_thread::sleep_for(std::chrono::milliseconds(config.delay * 1000));
|
if (config.delay > 0) std::this_thread::sleep_for(std::chrono::milliseconds(config.delay * 1000));
|
||||||
auto processor = static_cast<GenericPlatformScaleProcessor *>(serialPort->processor);
|
auto processor = static_cast<GenericPlatformScaleProcessor *>(serialPort->processor);
|
||||||
|
|
@ -125,17 +118,18 @@ namespace zsy
|
||||||
while (processor->steady.load() < config.sample || processor->weight.load() <= config.weight)
|
while (processor->steady.load() < config.sample || processor->weight.load() <= config.weight)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
LOGGER_INFO("第 {} 次称重", count);
|
||||||
|
|
||||||
if (count >= config.retries)
|
if (count >= config.retries)
|
||||||
{
|
{
|
||||||
LOGGER_ERROR("称重失败,连续 {} 次未稳定或磅重低于阈值 {} KG,当前磅重:{} KG", count, config.weight, processor->weight.load());
|
LOGGER_ERROR("称重失败,连续 {} 次未稳定或磅重低于阈值 {} KG,当前磅重:{} KG", count, config.weight, processor->weight.load());
|
||||||
/*status = 1;*/
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
|
||||||
}
|
}
|
||||||
auto res = processor->weight.load();
|
auto res = processor->weight.load();
|
||||||
LOGGER_INFO("称重完成:{} KG", res);
|
LOGGER_INFO("称重完成:{} KG", res);
|
||||||
/*status = 1;*/
|
|
||||||
return res;
|
return res;
|
||||||
} catch (std::exception &e)
|
} catch (std::exception &e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ namespace zsy
|
||||||
{
|
{
|
||||||
Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临");
|
Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临");
|
||||||
});
|
});
|
||||||
|
t.detach();
|
||||||
}
|
}
|
||||||
t.detach();
|
|
||||||
|
|
||||||
// 上报 1
|
// 上报 1
|
||||||
auto reportPassResult = Application::reportSvr->reportPass(license, sn);
|
auto reportPassResult = Application::reportSvr->reportPass(license, sn);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
### 车牌识别上报
|
||||||
|
POST http://localhost:11000/plateRecognize
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
< ./test.json
|
||||||
|
|
||||||
|
### 修改进出场
|
||||||
|
GET http://localhost:11000/type?type=2
|
||||||
|
|
||||||
|
### 开门
|
||||||
|
GET http://localhost:11000/opendoor?sn=1
|
||||||
|
|
||||||
|
### 称重
|
||||||
|
GET http://localhost:11000/weight?sn=1
|
||||||
|
|
||||||
|
### 播放语音
|
||||||
|
GET http://localhost:11000/play?sn=1
|
||||||
|
|
||||||
|
### 拍照
|
||||||
|
GET http://localhost:11000/photo?sn=1
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"AlarmInfoPlate": {
|
||||||
|
"serialno": "4",
|
||||||
|
"result": {
|
||||||
|
"PlateResult": {
|
||||||
|
"imageFile": "iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAIAAADwlwNsAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAAAXdEVYdFVzZXIgQ29tbWVudABTY3JlZW5zaG9093UNRwAAAMhJREFUGJVj/P//PwNewIRfGknF29PrFu2+g00FC5T+++vnj2+fP33+jCTHzMnLxQpXwcDAwPDy3Ia1F5H40pYJrqooKqQs4ny0MWxh3L5tOwMDA8Pv909f/OSVleCDinMpWNtp8DEwMDCwCMhIcTEwMDBISSnCtX17dP7+2x8MDBAVirp64ugGv/x85T6Gb3EDlo2zZmET54U7mRF7qP/69ZeNjRliywcGhjt7Fuy+ycDA8PfGtrkbL/5iYPh2ddeyVUdeQhQDABokQPRTGLjWAAAAAElFTkSuQmCC",
|
||||||
|
"license": "皖F25510"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue