修复问题

master
lzq 2025-07-16 18:14:32 +08:00
parent 6e9047b0ae
commit 375ac4fca9
32 changed files with 365 additions and 187 deletions

View File

@ -111,9 +111,9 @@ namespace zsy
LOGGER_INFO("等待..."); LOGGER_INFO("等待...");
std::this_thread::sleep_for(std::chrono::milliseconds(appProperties.delay * 1000)); std::this_thread::sleep_for(std::chrono::milliseconds(appProperties.delay * 1000));
} }
threadPool = std::make_shared<ThreadPool>(); threadPool = std::make_shared<ThreadPool>("通用线程池");
eventManager = std::make_shared<EventManager>(threadPool); eventManager = std::make_shared<EventManager>();
httpSvr = std::make_unique<HttpSvr>(config); httpSvr = std::make_unique<HttpSvr>(config);

View File

@ -4,7 +4,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "application.h" #include "application.h"
#include "common/loging.h" #include "common/logging.h"
namespace zsy { namespace zsy {

View File

@ -1,7 +1,10 @@
#ifndef BARRIER_H #ifndef BARRIER_H
#define BARRIER_H #define BARRIER_H
#include <memory>
#include <string> #include <string>
#include "recognize_data.h"
namespace zsy namespace zsy
{ {
@ -14,7 +17,9 @@ namespace zsy
virtual bool isFront() = 0; virtual bool isFront() = 0;
// virtual void resolveRecognizeResult(const std::string &license, const std::string &imageFile) = 0; virtual std::string sn() = 0;
virtual std::shared_ptr<std::istream> resolvePhoto(const std::string &imageFile) = 0;
}; };
} // zsy } // zsy

View File

@ -3,7 +3,7 @@
#include "application.h" #include "application.h"
#include "recognize_processor.h" #include "recognize_processor.h"
#include "common/date_util.h" #include "common/date_util.h"
#include "common/loging.h" #include "common/logging.h"
#include "common/snowflake.h" #include "common/snowflake.h"
#include "common/sys_util.h" #include "common/sys_util.h"
@ -48,39 +48,14 @@ namespace zsy
LOGGER_INFO("收到车牌识别结果:{}", body); LOGGER_INFO("收到车牌识别结果:{}", body);
auto [succ,recognizeResult] = GenericBarrier::parseRecognizeResult(body); auto [succ,recognizeResult] = GenericBarrier::parseRecognizeResult(body);
if (!succ) if (succ)
{ {
LOGGER_ERROR("车牌识别结果解析失败"); Application::threadPool->submit([recognizeResult]
res.set_content(R"({})", "application/json"); {
return; RecognizeProcessor::process(recognizeResult);
LOGGER_INFO("车牌识别结果处理完成");
});
} }
auto serialno = recognizeResult.alarmInfoPlate.serialno;
auto imageFile = recognizeResult.alarmInfoPlate.result.plateResult.imageFile;
auto license = recognizeResult.alarmInfoPlate.result.plateResult.license;
if (serialno.empty() || imageFile.empty() || license.empty())
{
LOGGER_ERROR("车牌识别结果解析失败");
res.set_content(R"({})", "application/json");
return;
}
if (license.find("") != std::string::npos)
{
LOGGER_WARN("车牌识别失败");
res.set_content(R"({})", "application/json");
return;
}
auto barrier = Application::deviceHolder->getBarrier(serialno);
if (!barrier)
{
LOGGER_ERROR("未找到对应的道闸");
return;
}
std::thread t([front = barrier->isFront(), serialno,license,imageFile]
{
RecognizeProcessor::process(front, serialno, license, imageFile);
});
t.detach();
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what()); LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
@ -137,21 +112,56 @@ namespace zsy
return config.name.find("前置") != std::string::npos; return config.name.find("前置") != std::string::npos;
} }
std::tuple<bool, RecognizeResult> GenericBarrier::parseRecognizeResult(const std::string &jsonStr) std::string GenericBarrier::sn()
{
return config.sn;
}
std::shared_ptr<std::istream> GenericBarrier::resolvePhoto(const std::string &imageFile)
{
auto content = SysUtil::base64_decode(imageFile);
return std::make_shared<std::istringstream>(content, std::ios_base::in | std::ios_base::binary);
}
std::tuple<bool, std::shared_ptr<RecognizeData> > GenericBarrier::parseRecognizeResult(const std::string &jsonStr)
{ {
try try
{ {
auto json = nlohmann::json::parse(jsonStr); auto json = nlohmann::json::parse(jsonStr);
RecognizeResult result = json.get<RecognizeResult>(); RecognizeResult result = json.get<RecognizeResult>();
return std::make_tuple(true, result); auto sn = result.alarmInfoPlate.serialno;
auto barrier = Application::deviceHolder->getBarrier(sn);
if (!barrier)
{
LOGGER_ERROR("未找到对应的道闸");
return std::make_tuple(false, nullptr);
}
auto image_file = result.alarmInfoPlate.result.plateResult.imageFile;
auto license = result.alarmInfoPlate.result.plateResult.license;
if (sn.empty()
|| image_file.empty()
|| license.empty()
|| license.find("") != std::string::npos
)
{
LOGGER_ERROR("车牌识别结果解析失败或车牌为:“无”");
return std::make_tuple(false, nullptr);
}
return std::make_tuple(true, std::make_shared<RecognizeData>(
barrier->isFront(),
sn,
license,
barrier->resolvePhoto(image_file)
));
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("未找到车牌识别结果:{}", e.what()); LOGGER_ERROR("未找到车牌识别结果:{}", e.what());
return std::make_tuple(false, RecognizeResult()); return std::make_tuple(false, nullptr);
}catch (...) }catch (...)
{ {
LOGGER_ERROR("未知异常,未找到车牌识别结果"); LOGGER_ERROR("未知异常,未找到车牌识别结果");
return std::make_tuple(false, RecognizeResult()); return std::make_tuple(false, nullptr);
} }
} }

View File

@ -5,6 +5,8 @@
#include <tuple> #include <tuple>
#include "recognize_data.h"
namespace zsy namespace zsy
{ {
struct DoorReq struct DoorReq
@ -150,9 +152,11 @@ namespace zsy
bool isFront() override; bool isFront() override;
// void resolveRecognizeResult(const std::string &license, const std::string &imageFile) override; std::string sn() override;
static std::tuple<bool, RecognizeResult> parseRecognizeResult(const std::string &jsonStr); std::shared_ptr<std::istream> resolvePhoto(const std::string &imageFile) override;
static std::tuple<bool, std::shared_ptr<RecognizeData> > parseRecognizeResult(const std::string &jsonStr);
}; };
} // zsy } // zsy

View File

@ -0,0 +1,9 @@
#include "recognize_data.h"
namespace zsy
{
RecognizeData::RecognizeData(bool isFront, std::string sn, std::string license, std::shared_ptr<std::istream> imageFile)
: isFront(isFront), sn(sn), license(license), imageFile(imageFile)
{
}
} // zsy

View File

@ -0,0 +1,24 @@
#ifndef RECOGNIZE_DATA_H
#define RECOGNIZE_DATA_H
#include <memory>
#include <string>
namespace zsy
{
struct RecognizeData
{
bool isFront;
std::string sn;
std::string license;
std::shared_ptr<std::istream> imageFile;
RecognizeData(
bool isFront,
std::string sn,
std::string license,
std::shared_ptr<std::istream> imageFile
);
};
} // zsy
#endif //RECOGNIZE_DATA_H

View File

@ -1,30 +1,40 @@
#include "event_manager.h" #include "event_manager.h"
#include "logging.h"
namespace zsy namespace zsy
{ {
EventManager::Event::Event(std::string name, const std::string &data) EventManager::Event::Event(std::string name, const std::string &data)
: name(std::move(name)) : name(std::move(name))
{ {
if (data.empty()) { if (data.empty())
{
this->data = std::nullopt; this->data = std::nullopt;
} else { } else
{
this->data = nlohmann::json::parse(data); this->data = nlohmann::json::parse(data);
} }
} }
EventManager::EventManager(std::shared_ptr<ThreadPool> threadPool) EventManager::EventManager(): threadPool(std::make_shared<ThreadPool>("事件线程池", 4))
: threadPool(threadPool)
{ {
} }
void EventManager::publish(const std::string &name, std::string data) noexcept void EventManager::subscribe(const std::string &name, const EventHandler &handler)
{
std::lock_guard lock(handlersMutex);
auto handlerPtr = std::make_shared<EventHandler>(handler);
handlers[name].push_back(handlerPtr);
}
void EventManager::publish(const std::string &name, const std::string &data) noexcept
{ {
LOGGER_INFO("发布事件:{} {}", name, data); LOGGER_INFO("发布事件:{} {}", name, data);
HandlerList *list = nullptr; HandlerList *list = nullptr;
{ {
std::lock_guard lock(handlersMutex); std::shared_lock lock(handlersMutex);
auto it = handlers.find(name); auto it = handlers.find(name);
if (it != handlers.end()) if (it != handlers.end())
{ {
@ -36,23 +46,18 @@ namespace zsy
} }
} }
for (auto fn_ptr: *list) if (list == nullptr || list->size() == 0)
{ {
/*try return;
{ }
(*fn_ptr.get())(Event(name, data));
} catch (const std::exception &e) threadPool->submit([list, name, data]
{ {
LOGGER_ERROR("事件处理异常:{} {}", name, e.what()); for (auto fn_ptr: *list)
}catch (...)
{
LOGGER_ERROR("事件处理异常:{}", name);
}*/
threadPool->submit([fn = fn_ptr.get(),name,data]
{ {
try try
{ {
(*fn)(Event(name, data)); (*fn_ptr.get())(Event(name, data));
} catch (const std::exception &e) } catch (const std::exception &e)
{ {
LOGGER_ERROR("事件处理异常:{} {}", name, e.what()); LOGGER_ERROR("事件处理异常:{} {}", name, e.what());
@ -60,7 +65,7 @@ namespace zsy
{ {
LOGGER_ERROR("事件处理异常:{}", name); LOGGER_ERROR("事件处理异常:{}", name);
} }
}); }
} });
} }
} // zsy } // zsy

View File

@ -23,21 +23,15 @@ namespace zsy
using EventHandler = std::function<void(const Event &)>; using EventHandler = std::function<void(const Event &)>;
using HandlerList = std::vector<std::shared_ptr<EventHandler> >; using HandlerList = std::vector<std::shared_ptr<EventHandler> >;
EventManager(std::shared_ptr<ThreadPool> threadPool); EventManager();
template<typename Fn> void subscribe(const std::string &name, const EventHandler &handler);
void subscribe(const std::string &name, Fn &&handler)
{
std::lock_guard lock(handlersMutex);
auto handlerPtr = std::make_shared<EventHandler>(std::forward<Fn>(handler));
handlers[name].push_back(handlerPtr);
}
void publish(const std::string &name, std::string data = {}) noexcept; void publish(const std::string &name, const std::string &data = {}) noexcept;
private: private:
std::unordered_map<std::string, HandlerList> handlers; std::unordered_map<std::string, HandlerList> handlers;
std::mutex handlersMutex; std::shared_mutex handlersMutex;
std::shared_ptr<ThreadPool> threadPool; std::shared_ptr<ThreadPool> threadPool;
}; };
} // zsy } // zsy

View File

@ -1,6 +1,6 @@
#ifndef JSON_UTIL_H #ifndef JSON_UTIL_H
#define JSON_UTIL_H #define JSON_UTIL_H
#include "common/loging.h" #include "common/logging.h"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#define PARSE_JSON(field, to) try \ #define PARSE_JSON(field, to) try \

View File

@ -1,20 +1,22 @@
#include "thread_pool.h" #include "thread_pool.h"
#include "loging.h" #include "logging.h"
namespace zsy namespace zsy
{ {
ThreadPool::ThreadPool(size_t threadCount): status(0) ThreadPool::ThreadPool(std::string name, const uint16_t threadCount): name(name), status(0), threadCount(threadCount < 1 ? 1 : threadCount)
{
std::lock_guard lock(status_mtx);
status = 1;
createThread();
}
void ThreadPool::createThread()
{ {
if (threadCount < 1) threadCount = 1;
workers.reserve(threadCount);
{
std::unique_lock lock(status_mtx);
status = 1;
}
for (size_t i = 0; i < threadCount; ++i) for (size_t i = 0; i < threadCount; ++i)
{ {
workers.emplace_back([this](const std::stop_token &st) LOGGER_INFO("创建线程:{}-{} 号", name, i);
threads.emplace_back([this,i](const std::stop_token &st)
{ {
while (!st.stop_requested()) while (!st.stop_requested())
{ {
@ -28,7 +30,7 @@ namespace zsy
if (st.stop_requested() && tasks.empty()) if (st.stop_requested() && tasks.empty())
{ {
LOGGER_INFO("已停止线程"); LOGGER_INFO("线程已停止:{}-{} 号", name, i);
return; return;
} }
task = std::move(tasks.front()); task = std::move(tasks.front());
@ -36,26 +38,47 @@ namespace zsy
} }
try try
{ {
LOGGER_INFO("开始执行任务:{}-{} 号", name, i);
if (task) task(); if (task) task();
LOGGER_INFO("任务执行完成:{}-{} 号", name, i);
} catch (const std::exception &e) } catch (const std::exception &e)
{ {
LOGGER_ERROR("任务执行失败: {}", e.what()); LOGGER_ERROR("任务执行失败{}-{} 号, {}", name, i, e.what());
} }
catch (...) catch (...)
{ {
LOGGER_ERROR("未知异常,任务执行失败"); LOGGER_ERROR("未知异常,任务执行失败{}-{} 号", name, i);
} }
} }
}); });
} }
} }
void ThreadPool::submit(const std::function<void()> &task)
{
addTask(task);
taskCondition.notify_one();
}
void ThreadPool::addTask(const std::function<void()> &task)
{
std::shared_lock status_lock(status_mtx);
if (status != 1)
{
LOGGER_ERROR("线程池未启动");
return;
}
std::unique_lock lock(queueMutex);
tasks.emplace(task);
}
ThreadPool::~ThreadPool() ThreadPool::~ThreadPool()
{ {
std::unique_lock lock(status_mtx); std::lock_guard lock(status_mtx);
status = 2; status = 2;
LOGGER_INFO("正在销毁线程池..."); LOGGER_INFO("正在销毁线程池...");
workers.clear(); threads.clear();
LOGGER_INFO("线程池已销毁"); LOGGER_INFO("线程池已销毁");
} }
} // zsy } // zsy

View File

@ -8,36 +8,29 @@
#include <condition_variable> #include <condition_variable>
#include <shared_mutex> #include <shared_mutex>
#include "loging.h"
namespace zsy namespace zsy
{ {
class ThreadPool class ThreadPool
{ {
std::vector<std::jthread> workers; // 工作线程 std::vector<std::jthread> threads; // 工作线程
std::queue<std::function<void()> > tasks; // 任务队列 std::queue<std::function<void()> > tasks; // 任务队列
mutable std::recursive_mutex queueMutex; // 保护任务队列的互斥锁 mutable std::recursive_mutex queueMutex; // 保护任务队列的互斥锁
std::condition_variable_any taskCondition; // 任务通知条件变量 std::condition_variable_any taskCondition; // 任务通知条件变量
std::string name;
// 0-->不可用1-->已启动2-->已关闭 // 0-->不可用1-->已启动2-->已关闭
uint8_t status; // 线程池停止标志 uint8_t status; // 线程池停止标志
uint16_t threadCount; // 线程池停止标志
std::shared_mutex status_mtx; std::shared_mutex status_mtx;
public: void addTask(const std::function<void()> &task);
explicit ThreadPool(size_t threadCount = std::thread::hardware_concurrency() * 2);
template<typename Fn> void createThread();
void submit(Fn &&task) noexcept
{
std::shared_lock status_lock(status_mtx); public:
if (status != 1) explicit ThreadPool(std::string name,uint16_t threadCount = std::thread::hardware_concurrency() * 2);
{
LOGGER_ERROR("线程池未启动"); void submit(const std::function<void()> &task);
return;
}
std::unique_lock lock(queueMutex);
tasks.emplace(std::forward<Fn>(task));
taskCondition.notify_one();
}
~ThreadPool(); ~ThreadPool();

View File

@ -0,0 +1,12 @@
#include "barrier_controller.h"
#include "application.h"
#include "recognize_processor.h"
#include "barrier/generic_barrier.h"
namespace zsy {
BarrierController::BarrierController()
{
}
} // zsy

View File

@ -0,0 +1,13 @@
#ifndef BARRIER_CONTROLLER_H
#define BARRIER_CONTROLLER_H
namespace zsy {
class BarrierController {
public:
BarrierController();
};
} // zsy
#endif //BARRIER_CONTROLLER_H

View File

@ -116,7 +116,7 @@ namespace zsy
{ {
auto sn = req.get_param_value("sn"); auto sn = req.get_param_value("sn");
auto photograph = Application::deviceHolder->getVidicon(sn)->photograph(); auto photograph = Application::deviceHolder->getVidicon(sn)->photograph();
j["结果"] = photograph; j["结果"] = "";
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("错误", e.what()); LOGGER_ERROR("错误", e.what());

View File

@ -52,10 +52,14 @@ namespace zsy
HttpSvr::~HttpSvr() HttpSvr::~HttpSvr()
{ {
std::unique_lock lock(status_mtx); {
status = 1; std::unique_lock lock(status_mtx);
status = 1;
}
if (svr) if (svr)
{ {
LOGGER_INFO("正在停止 HTTP 服务器");
svr->stop(); svr->stop();
} }
if (svrThread && svrThread->joinable()) if (svrThread && svrThread->joinable())

View File

@ -1,7 +1,7 @@
#include "oss.h" #include "oss.h"
#include <httplib.h> #include <httplib.h>
#include <map> #include <map>
#include "common/loging.h" #include "common/logging.h"
#include "common/sys_util.h" #include "common/sys_util.h"
namespace zsy namespace zsy
@ -11,9 +11,14 @@ namespace zsy
{ {
} }
std::tuple<bool, std::string> OSS::upload(const std::string &objectName, std::istream &file) std::tuple<bool, std::string> OSS::upload(const std::string &objectName, std::shared_ptr<std::istream> file)
{ {
LOGGER_INFO("正在上传文件:{}", objectName); LOGGER_INFO("正在上传文件:{}", objectName);
if (!file)
{
LOGGER_ERROR("文件为空");
return std::make_tuple(false, "");
}
try try
{ {
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
@ -45,7 +50,7 @@ namespace zsy
}; };
std::stringstream buffer; std::stringstream buffer;
buffer << file.rdbuf(); buffer << file->rdbuf();
const std::string &content = buffer.str(); const std::string &content = buffer.str();
// 发送请求 // 发送请求
@ -81,8 +86,8 @@ namespace zsy
LOGGER_INFO("文件上传失败,文件路径为空"); LOGGER_INFO("文件上传失败,文件路径为空");
return std::make_tuple(false, ""); return std::make_tuple(false, "");
} }
std::ifstream file(filePath, std::ios::binary); std::shared_ptr<std::ifstream> file = std::make_shared<std::ifstream>(filePath, std::ios::binary);
if (!file.is_open()) if (!file->is_open())
{ {
auto [_,code,msg] = SysUtil::getError(); auto [_,code,msg] = SysUtil::getError();
LOGGER_INFO("文件上传失败,无法打开文件:{},错误码:{},错误信息:{}", filePath, code, msg); LOGGER_INFO("文件上传失败,无法打开文件:{},错误码:{},错误信息:{}", filePath, code, msg);

View File

@ -8,7 +8,7 @@
#include <fstream> #include <fstream>
#include "oss_properties.h" #include "oss_properties.h"
#include "common/loging.h" #include "common/logging.h"
namespace zsy namespace zsy
@ -30,7 +30,7 @@ namespace zsy
public: public:
OSS(const nlohmann::json &config); OSS(const nlohmann::json &config);
std::tuple<bool, std::string> upload(const std::string &objectName, std::istream &file); std::tuple<bool, std::string> upload(const std::string &objectName, std::shared_ptr<std::istream> file);
std::tuple<bool, std::string> upload(const std::string &objectName, const std::string &filePath); std::tuple<bool, std::string> upload(const std::string &objectName, const std::string &filePath);
}; };

View File

@ -1,61 +1,31 @@
#include "recognize_processor.h" #include "recognize_processor.h"
#include "application.h" #include "application.h"
#include "common/date_util.h" #include "common/date_util.h"
#include "common/loging.h" #include "common/logging.h"
#include "common/sys_util.h" #include "common/sys_util.h"
#include "common/snowflake.h" #include "common/snowflake.h"
namespace zsy namespace zsy
{ {
void RecognizeProcessor::process(bool front, const std::string &sn, const std::string &license, const std::string &imageFile) void RecognizeProcessor::process(std::shared_ptr<RecognizeData> data)
{ {
const std::string &sn = data->sn;
const std::string &license = data->license;
try try
{ {
if (front) if (data->isFront)
{ {
// 播放语音 1 Application::threadPool->submit([sn] { Application::deviceHolder->getSoundColumn(sn)->play("欢迎光临"); });
Application::threadPool->submit([sn]
{
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();
std::string date = DateUtil::format(Ymd);
// 上报 1 // 上报 1
auto reportPassResult = Application::reportSvr->reportPass(license, sn, ""); auto reportPassResult = Application::reportSvr->reportPass(license, sn);
if (!(reportPassResult.code == 0 && (reportPassResult.data.type == 1 || reportPassResult.data.type == 2))) if (!(reportPassResult.code == 0 && (reportPassResult.data.type == 1 || reportPassResult.data.type == 2)))
{ {
LOGGER_INFO("不进行后续处理"); LOGGER_INFO("不进行后续处理");
return; return;
} }
auto [carFrontUrlSucc,carFrontUrl] = Application::oss->upload(date + "/" + "front_" + photoId + ".jpg", *imageFileStream); addition_process(reportPassResult.data.orderNo, data);
// 上报结果 type 不为 0播放语音 2 并读地磅,拍车斗并上传
Application::threadPool->submit([sn]
{
Application::deviceHolder->getSoundColumn(sn)->play("正在称重,请稍后");
});
double weight = Application::deviceHolder->getPlatformScale(sn)->reading();
auto photographPath = Application::deviceHolder->getVidicon(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, sn, weight, carFrontUrl, carBodyUrl, reportPassResult.data.orderNo);
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what()); LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
@ -65,4 +35,26 @@ namespace zsy
LOGGER_ERROR("未知异常,车牌识别结果处理失败"); LOGGER_ERROR("未知异常,车牌识别结果处理失败");
} }
} }
void RecognizeProcessor::addition_process(const std::string &orderNo, std::shared_ptr<RecognizeData> data)
{
const std::string &sn = data->sn;
const std::string &license = data->license;
std::shared_ptr<std::istream> frontImageFile = data->imageFile;
// 上报结果 type 不为 0播放语音 2 并读地磅,拍车斗并上传
Application::threadPool->submit([sn] { Application::deviceHolder->getSoundColumn(sn)->play("正在称重,请稍后"); });
auto weight = Application::deviceHolder->getPlatformScale(sn)->reading();
std::string date = DateUtil::format(Ymd);
auto photoId = Snowflake::genIdStr();
auto bodyImageFile = Application::deviceHolder->getVidicon(sn)->photograph();
auto [carFrontUrlSucc,carFrontUrl] = Application::oss->upload(date + "/" + "front_" + photoId + ".jpg", frontImageFile);
auto [carBodyUrlSucc,carBodyUrl] = Application::oss->upload(date + "/" + "body_" + photoId + ".jpg", bodyImageFile);
// 上报 2
Application::reportSvr->report(license, sn, weight, carFrontUrl, carBodyUrl, orderNo);
}
} // zsy } // zsy

View File

@ -1,14 +1,19 @@
#ifndef RECOGNIZE_PROCESSOR_H #ifndef RECOGNIZE_PROCESSOR_H
#define RECOGNIZE_PROCESSOR_H #define RECOGNIZE_PROCESSOR_H
#include <memory>
#include <string> #include <string>
#include "barrier/barrier.h"
namespace zsy namespace zsy
{ {
class RecognizeProcessor class RecognizeProcessor
{ {
public: public:
static void process(bool front, const std::string& sn, const std::string& license, const std::string& imageFile); static void process(std::shared_ptr<RecognizeData> data);
static void addition_process(const std::string &orderNo,std::shared_ptr<RecognizeData> data);
}; };
} // zsy } // zsy

View File

@ -3,7 +3,7 @@
#include <httplib.h> #include <httplib.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "common/loging.h" #include "common/logging.h"
namespace zsy namespace zsy
{ {
@ -12,7 +12,7 @@ namespace zsy
{ {
} }
ReportPassResult ReportSvr::reportPass(const std::string &license, const std::string &sn, const std::string &carFrontUrl) ReportPassResult ReportSvr::reportPass(const std::string &license, const std::string &sn)
{ {
try try
{ {
@ -22,7 +22,6 @@ namespace zsy
ReportData reportData; ReportData reportData;
reportData.carNumber = license; reportData.carNumber = license;
reportData.carDiscernCode = sn; reportData.carDiscernCode = sn;
reportData.photoFront = carFrontUrl;
nlohmann::json data = reportData; nlohmann::json data = reportData;

View File

@ -111,7 +111,7 @@ namespace zsy
public: public:
ReportSvr(const nlohmann::json &config); ReportSvr(const nlohmann::json &config);
ReportPassResult reportPass(const std::string &license, const std::string &sn, const std::string &carFrontUrl); ReportPassResult reportPass(const std::string &license, const std::string &sn);
ReportResult report(const std::string &license, ReportResult report(const std::string &license,

View File

@ -1,6 +1,6 @@
#include "serial_port.h" #include "serial_port.h"
#include "common/loging.h" #include "common/logging.h"
#include "common/sys_util.h" #include "common/sys_util.h"
namespace zsy namespace zsy

View File

@ -8,7 +8,7 @@
namespace zsy namespace zsy
{ {
bool BarrierVidicon::saveImageToFile(const std::string &decodedImageData, const std::string &filePath) void BarrierVidicon::saveImageToFile(const std::string &decodedImageData, const std::string &filePath)
{ {
try try
{ {
@ -29,12 +29,12 @@ namespace zsy
{ {
throw std::system_error(errno, std::generic_category(), "写入文件失败"); throw std::system_error(errno, std::generic_category(), "写入文件失败");
} }
return true;
} catch (const std::exception &e) } catch (const std::exception &e)
{ {
LOGGER_ERROR("图片保存失败"); LOGGER_ERROR("图片保存失败");
return false; }catch (...)
{
LOGGER_ERROR("未知异常,图片保存失败");
} }
} }
@ -46,8 +46,7 @@ namespace zsy
: config(config) : config(config)
, hasNewContent(false) , hasNewContent(false)
{ {
SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp"); // SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp");
auto cli = Application::mqttCliHolder->localCli();
Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/up/snapshot", [this](const EventManager::Event &event) Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/up/snapshot", [this](const EventManager::Event &event)
{ {
if (!event.data.has_value()) if (!event.data.has_value())
@ -63,7 +62,7 @@ namespace zsy
imageContent = res.payload.image_content; imageContent = res.payload.image_content;
hasNewContent.store(true); hasNewContent.store(true);
}); });
Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/down/snapshot/reply", [this](const EventManager::Event &event) Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/down/snapshot/reply", [this](const EventManager::Event &event)
{ {
if (!event.data.has_value()) if (!event.data.has_value())
{ {
@ -76,12 +75,12 @@ namespace zsy
}); });
} }
std::string BarrierVidicon::photograph() std::shared_ptr<std::istream> BarrierVidicon::photograph()
{ {
try try
{ {
LOGGER_INFO("摄像机正在拍照,设备名称:{}", config.name); LOGGER_INFO("摄像机正在拍照,设备名称:{}", config.name);
const long timestamp = static_cast<long>(DateUtil::timestamp()/1000); const long timestamp = static_cast<long>(DateUtil::timestamp() / 1000);
nlohmann::json j{ nlohmann::json j{
{"id", "photograph" + std::to_string(timestamp)}, {"id", "photograph" + std::to_string(timestamp)},
{"sn", config.ip}, {"sn", config.ip},
@ -117,10 +116,9 @@ namespace zsy
} while (i <= 10 && !hasNewContent.load()); } while (i <= 10 && !hasNewContent.load());
const auto filename = "car_body_" + Snowflake::genIdStr() + ".jpg"; const auto filename = "car_body_" + Snowflake::genIdStr() + ".jpg";
std::string path = SysUtil::HOME_DIR + "\\temp\\" + filename;
auto content = SysUtil::base64_decode(imageContent); auto content = SysUtil::base64_decode(imageContent);
bool res = saveImageToFile(content, path);
return path; return std::make_shared<std::istringstream>(content, std::ios_base::in | std::ios_base::binary);
} else } else
{ {
LOGGER_ERROR("未找到 MQTT 本地客户端"); LOGGER_ERROR("未找到 MQTT 本地客户端");
@ -132,16 +130,16 @@ namespace zsy
{ {
LOGGER_ERROR("未知异常,拍照失败"); LOGGER_ERROR("未知异常,拍照失败");
} }
return ""; return nullptr;
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("摄像机拍照失败:{}", e.what()); LOGGER_ERROR("摄像机拍照失败:{}", e.what());
return {}; return nullptr;
} }
catch (...) catch (...)
{ {
LOGGER_ERROR("未知异常,摄像机拍照失败"); LOGGER_ERROR("未知异常,摄像机拍照失败");
return {}; return nullptr;
} }
} }
} }

View File

@ -34,14 +34,14 @@ namespace zsy
std::atomic<bool> hasNewContent; std::atomic<bool> hasNewContent;
std::string imageContent; std::string imageContent;
bool saveImageToFile(const std::string &decodedImageData, const std::string &filePath); void saveImageToFile(const std::string &decodedImageData, const std::string &filePath);
public: public:
~BarrierVidicon() override; ~BarrierVidicon() override;
explicit BarrierVidicon(const VidiconProperties &config); explicit BarrierVidicon(const VidiconProperties &config);
std::string photograph() override; std::shared_ptr<std::istream> photograph() override;
}; };
} }

View File

@ -1,4 +1,7 @@
#include "generic_vidicon.h" #include "generic_vidicon.h"
#include <fstream>
#include "HCNetSDK.h" #include "HCNetSDK.h"
#include "common/snowflake.h" #include "common/snowflake.h"
#include "common/sys_util.h" #include "common/sys_util.h"
@ -15,7 +18,76 @@ namespace zsy
SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp"); SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp");
} }
std::string GenericVidicon::photograph() std::shared_ptr<std::istream> GenericVidicon::read(const std::string &filePath)
{
if (!std::filesystem::exists(filePath))
{
LOGGER_ERROR("文件不存在:{}", filePath);
return nullptr;
}
std::uintmax_t fileSize = 0;
try
{
fileSize = std::filesystem::file_size(filePath);
} catch (const std::filesystem::filesystem_error &e)
{
LOGGER_ERROR("获取文件大小失败 - {}", e.what());
return nullptr;
}
// 打开文件
std::ifstream file(filePath, std::ios::binary);
if (!file.is_open())
{
LOGGER_ERROR("错误: 无法打开文件 {}", filePath);
return nullptr;
}
std::string fileContent;
fileContent.reserve(fileSize);
char buffer[4096];
while (file.read(buffer, sizeof(buffer)))
{
fileContent.append(buffer, sizeof(buffer));
}
// 处理最后一块可能不完整的数据
if (file.gcount() > 0)
{
fileContent.append(buffer, file.gcount());
}
// 检查读取是否成功
if (!file.eof())
{
LOGGER_ERROR("错误: 读取文件 '{}' 时发生错误", filePath);
return nullptr;
}
// 关闭文件
file.close();
return std::make_shared<std::istringstream>(fileContent, std::ios_base::in | std::ios_base::binary);
}
void GenericVidicon::remove(const std::string &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);
}
}
}
std::shared_ptr<std::istream> GenericVidicon::photograph()
{ {
try try
{ {
@ -73,7 +145,11 @@ namespace zsy
NET_DVR_Logout_V30(lLoginID); NET_DVR_Logout_V30(lLoginID);
NET_DVR_Cleanup(); NET_DVR_Cleanup();
return path; auto content = read(path);
remove(path);
return content;
} catch (std::exception &e) } catch (std::exception &e)
{ {
LOGGER_ERROR("摄像机拍照失败:{}", e.what()); LOGGER_ERROR("摄像机拍照失败:{}", e.what());

View File

@ -8,12 +8,17 @@ namespace zsy
class GenericVidicon : public Vidicon class GenericVidicon : public Vidicon
{ {
VidiconProperties config; VidiconProperties config;
public: public:
~GenericVidicon() override; ~GenericVidicon() override;
GenericVidicon(const VidiconProperties &config); GenericVidicon(const VidiconProperties &config);
std::string photograph() override; std::shared_ptr<std::istream> read(const std::string &photographPath);
void remove(const std::string &photographPath);
std::shared_ptr<std::istream> photograph() override;
}; };
} // zsy } // zsy

View File

@ -1,8 +1,9 @@
#include "test_vidicon.h" #include "test_vidicon.h"
namespace zsy { namespace zsy
std::string TestVidicon::photograph() {
std::shared_ptr<std::istream> TestVidicon::photograph()
{ {
return ""; return nullptr;
} }
} // zsy } // zsy

View File

@ -7,7 +7,7 @@ namespace zsy
class TestVidicon : public Vidicon class TestVidicon : public Vidicon
{ {
public: public:
std::string photograph() override; std::shared_ptr<std::istream> photograph() override;
}; };
} // zsy } // zsy

View File

@ -1,5 +1,6 @@
#ifndef VIDICON_H #ifndef VIDICON_H
#define VIDICON_H #define VIDICON_H
#include <memory>
#include <string> #include <string>
@ -10,7 +11,7 @@ namespace zsy
public: public:
virtual ~Vidicon() = default; virtual ~Vidicon() = default;
virtual std::string photograph() = 0; virtual std::shared_ptr<std::istream> photograph() = 0;
}; };
} }