修复问题
parent
6e9047b0ae
commit
375ac4fca9
|
@ -111,9 +111,9 @@ namespace zsy
|
|||
LOGGER_INFO("等待...");
|
||||
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);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "application.h"
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
namespace zsy {
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef BARRIER_H
|
||||
#define BARRIER_H
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "recognize_data.h"
|
||||
|
||||
|
||||
namespace zsy
|
||||
{
|
||||
|
@ -14,7 +17,9 @@ namespace zsy
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "application.h"
|
||||
#include "recognize_processor.h"
|
||||
#include "common/date_util.h"
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/snowflake.h"
|
||||
#include "common/sys_util.h"
|
||||
|
||||
|
@ -48,39 +48,14 @@ namespace zsy
|
|||
LOGGER_INFO("收到车牌识别结果:{}", body);
|
||||
|
||||
auto [succ,recognizeResult] = GenericBarrier::parseRecognizeResult(body);
|
||||
if (!succ)
|
||||
if (succ)
|
||||
{
|
||||
LOGGER_ERROR("车牌识别结果解析失败");
|
||||
res.set_content(R"({})", "application/json");
|
||||
return;
|
||||
}
|
||||
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())
|
||||
Application::threadPool->submit([recognizeResult]
|
||||
{
|
||||
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);
|
||||
RecognizeProcessor::process(recognizeResult);
|
||||
LOGGER_INFO("车牌识别结果处理完成");
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
|
||||
|
@ -137,21 +112,56 @@ namespace zsy
|
|||
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
|
||||
{
|
||||
auto json = nlohmann::json::parse(jsonStr);
|
||||
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)
|
||||
{
|
||||
LOGGER_ERROR("未找到车牌识别结果:{}", e.what());
|
||||
return std::make_tuple(false, RecognizeResult());
|
||||
return std::make_tuple(false, nullptr);
|
||||
}catch (...)
|
||||
{
|
||||
LOGGER_ERROR("未知异常,未找到车牌识别结果");
|
||||
return std::make_tuple(false, RecognizeResult());
|
||||
return std::make_tuple(false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <tuple>
|
||||
|
||||
#include "recognize_data.h"
|
||||
|
||||
namespace zsy
|
||||
{
|
||||
struct DoorReq
|
||||
|
@ -150,9 +152,11 @@ namespace zsy
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,30 +1,40 @@
|
|||
#include "event_manager.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
namespace zsy
|
||||
{
|
||||
EventManager::Event::Event(std::string name, const std::string &data)
|
||||
: name(std::move(name))
|
||||
{
|
||||
if (data.empty()) {
|
||||
if (data.empty())
|
||||
{
|
||||
this->data = std::nullopt;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
this->data = nlohmann::json::parse(data);
|
||||
}
|
||||
}
|
||||
|
||||
EventManager::EventManager(std::shared_ptr<ThreadPool> threadPool)
|
||||
: threadPool(threadPool)
|
||||
EventManager::EventManager(): threadPool(std::make_shared<ThreadPool>("事件线程池", 4))
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
HandlerList *list = nullptr;
|
||||
|
||||
{
|
||||
std::lock_guard lock(handlersMutex);
|
||||
std::shared_lock lock(handlersMutex);
|
||||
auto it = handlers.find(name);
|
||||
if (it != handlers.end())
|
||||
{
|
||||
|
@ -36,9 +46,16 @@ namespace zsy
|
|||
}
|
||||
}
|
||||
|
||||
if (list == nullptr || list->size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
threadPool->submit([list, name, data]
|
||||
{
|
||||
for (auto fn_ptr: *list)
|
||||
{
|
||||
/*try
|
||||
try
|
||||
{
|
||||
(*fn_ptr.get())(Event(name, data));
|
||||
} catch (const std::exception &e)
|
||||
|
@ -47,20 +64,8 @@ namespace zsy
|
|||
}catch (...)
|
||||
{
|
||||
LOGGER_ERROR("事件处理异常:{}", name);
|
||||
}*/
|
||||
threadPool->submit([fn = fn_ptr.get(),name,data]
|
||||
{
|
||||
try
|
||||
{
|
||||
(*fn)(Event(name, data));
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("事件处理异常:{} {}", name, e.what());
|
||||
}catch (...)
|
||||
{
|
||||
LOGGER_ERROR("事件处理异常:{}", name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} // zsy
|
||||
|
|
|
@ -23,21 +23,15 @@ namespace zsy
|
|||
using EventHandler = std::function<void(const Event &)>;
|
||||
using HandlerList = std::vector<std::shared_ptr<EventHandler> >;
|
||||
|
||||
EventManager(std::shared_ptr<ThreadPool> threadPool);
|
||||
EventManager();
|
||||
|
||||
template<typename Fn>
|
||||
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 subscribe(const std::string &name, const EventHandler &handler);
|
||||
|
||||
void publish(const std::string &name, std::string data = {}) noexcept;
|
||||
void publish(const std::string &name, const std::string &data = {}) noexcept;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, HandlerList> handlers;
|
||||
std::mutex handlersMutex;
|
||||
std::shared_mutex handlersMutex;
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
};
|
||||
} // zsy
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef JSON_UTIL_H
|
||||
#define JSON_UTIL_H
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define PARSE_JSON(field, to) try \
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
#include "thread_pool.h"
|
||||
|
||||
#include "loging.h"
|
||||
#include "logging.h"
|
||||
|
||||
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)
|
||||
{
|
||||
if (threadCount < 1) threadCount = 1;
|
||||
workers.reserve(threadCount);
|
||||
{
|
||||
std::unique_lock lock(status_mtx);
|
||||
std::lock_guard lock(status_mtx);
|
||||
status = 1;
|
||||
createThread();
|
||||
}
|
||||
|
||||
void ThreadPool::createThread()
|
||||
{
|
||||
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())
|
||||
{
|
||||
|
@ -28,7 +30,7 @@ namespace zsy
|
|||
|
||||
if (st.stop_requested() && tasks.empty())
|
||||
{
|
||||
LOGGER_INFO("已停止线程");
|
||||
LOGGER_INFO("线程已停止:{}-{} 号", name, i);
|
||||
return;
|
||||
}
|
||||
task = std::move(tasks.front());
|
||||
|
@ -36,26 +38,47 @@ namespace zsy
|
|||
}
|
||||
try
|
||||
{
|
||||
LOGGER_INFO("开始执行任务:{}-{} 号", name, i);
|
||||
if (task) task();
|
||||
LOGGER_INFO("任务执行完成:{}-{} 号", name, i);
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("任务执行失败: {}", e.what());
|
||||
LOGGER_ERROR("任务执行失败:{}-{} 号, {}", name, i, e.what());
|
||||
}
|
||||
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()
|
||||
{
|
||||
std::unique_lock lock(status_mtx);
|
||||
std::lock_guard lock(status_mtx);
|
||||
status = 2;
|
||||
LOGGER_INFO("正在销毁线程池...");
|
||||
workers.clear();
|
||||
threads.clear();
|
||||
LOGGER_INFO("线程池已销毁");
|
||||
}
|
||||
} // zsy
|
||||
|
|
|
@ -8,36 +8,29 @@
|
|||
#include <condition_variable>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "loging.h"
|
||||
|
||||
namespace zsy
|
||||
{
|
||||
class ThreadPool
|
||||
{
|
||||
std::vector<std::jthread> workers; // 工作线程
|
||||
std::vector<std::jthread> threads; // 工作线程
|
||||
std::queue<std::function<void()> > tasks; // 任务队列
|
||||
mutable std::recursive_mutex queueMutex; // 保护任务队列的互斥锁
|
||||
std::condition_variable_any taskCondition; // 任务通知条件变量
|
||||
std::string name;
|
||||
// 0-->不可用,1-->已启动,2-->已关闭
|
||||
uint8_t status; // 线程池停止标志
|
||||
uint16_t threadCount; // 线程池停止标志
|
||||
std::shared_mutex status_mtx;
|
||||
|
||||
public:
|
||||
explicit ThreadPool(size_t threadCount = std::thread::hardware_concurrency() * 2);
|
||||
void addTask(const std::function<void()> &task);
|
||||
|
||||
template<typename Fn>
|
||||
void submit(Fn &&task) noexcept
|
||||
{
|
||||
std::shared_lock status_lock(status_mtx);
|
||||
if (status != 1)
|
||||
{
|
||||
LOGGER_ERROR("线程池未启动");
|
||||
return;
|
||||
}
|
||||
std::unique_lock lock(queueMutex);
|
||||
tasks.emplace(std::forward<Fn>(task));
|
||||
taskCondition.notify_one();
|
||||
}
|
||||
void createThread();
|
||||
|
||||
|
||||
public:
|
||||
explicit ThreadPool(std::string name,uint16_t threadCount = std::thread::hardware_concurrency() * 2);
|
||||
|
||||
void submit(const std::function<void()> &task);
|
||||
|
||||
~ThreadPool();
|
||||
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BARRIER_CONTROLLER_H
|
||||
#define BARRIER_CONTROLLER_H
|
||||
|
||||
namespace zsy {
|
||||
|
||||
class BarrierController {
|
||||
public:
|
||||
BarrierController();
|
||||
};
|
||||
|
||||
} // zsy
|
||||
|
||||
#endif //BARRIER_CONTROLLER_H
|
|
@ -116,7 +116,7 @@ namespace zsy
|
|||
{
|
||||
auto sn = req.get_param_value("sn");
|
||||
auto photograph = Application::deviceHolder->getVidicon(sn)->photograph();
|
||||
j["结果"] = photograph;
|
||||
j["结果"] = "";
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("错误", e.what());
|
||||
|
|
|
@ -51,11 +51,15 @@ namespace zsy
|
|||
}
|
||||
|
||||
HttpSvr::~HttpSvr()
|
||||
{
|
||||
{
|
||||
std::unique_lock lock(status_mtx);
|
||||
status = 1;
|
||||
}
|
||||
if (svr)
|
||||
{
|
||||
LOGGER_INFO("正在停止 HTTP 服务器");
|
||||
|
||||
svr->stop();
|
||||
}
|
||||
if (svrThread && svrThread->joinable())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "oss.h"
|
||||
#include <httplib.h>
|
||||
#include <map>
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/sys_util.h"
|
||||
|
||||
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);
|
||||
if (!file)
|
||||
{
|
||||
LOGGER_ERROR("文件为空");
|
||||
return std::make_tuple(false, "");
|
||||
}
|
||||
try
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
@ -45,7 +50,7 @@ namespace zsy
|
|||
};
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
buffer << file->rdbuf();
|
||||
const std::string &content = buffer.str();
|
||||
|
||||
// 发送请求
|
||||
|
@ -81,8 +86,8 @@ namespace zsy
|
|||
LOGGER_INFO("文件上传失败,文件路径为空");
|
||||
return std::make_tuple(false, "");
|
||||
}
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
if (!file.is_open())
|
||||
std::shared_ptr<std::ifstream> file = std::make_shared<std::ifstream>(filePath, std::ios::binary);
|
||||
if (!file->is_open())
|
||||
{
|
||||
auto [_,code,msg] = SysUtil::getError();
|
||||
LOGGER_INFO("文件上传失败,无法打开文件:{},错误码:{},错误信息:{}", filePath, code, msg);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <fstream>
|
||||
|
||||
#include "oss_properties.h"
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
|
||||
namespace zsy
|
||||
|
@ -30,7 +30,7 @@ namespace zsy
|
|||
public:
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -1,61 +1,31 @@
|
|||
#include "recognize_processor.h"
|
||||
#include "application.h"
|
||||
#include "common/date_util.h"
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/sys_util.h"
|
||||
#include "common/snowflake.h"
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
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)))
|
||||
{
|
||||
LOGGER_INFO("不进行后续处理");
|
||||
return;
|
||||
}
|
||||
auto [carFrontUrlSucc,carFrontUrl] = Application::oss->upload(date + "/" + "front_" + photoId + ".jpg", *imageFileStream);
|
||||
|
||||
// 上报结果 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);
|
||||
addition_process(reportPassResult.data.orderNo, data);
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("车牌识别结果处理失败: {}", e.what());
|
||||
|
@ -65,4 +35,26 @@ namespace zsy
|
|||
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
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
#ifndef RECOGNIZE_PROCESSOR_H
|
||||
#define RECOGNIZE_PROCESSOR_H
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "barrier/barrier.h"
|
||||
|
||||
|
||||
namespace zsy
|
||||
{
|
||||
class RecognizeProcessor
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <httplib.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -22,7 +22,6 @@ namespace zsy
|
|||
ReportData reportData;
|
||||
reportData.carNumber = license;
|
||||
reportData.carDiscernCode = sn;
|
||||
reportData.photoFront = carFrontUrl;
|
||||
|
||||
nlohmann::json data = reportData;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace zsy
|
|||
public:
|
||||
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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "serial_port.h"
|
||||
|
||||
#include "common/loging.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/sys_util.h"
|
||||
|
||||
namespace zsy
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -29,12 +29,12 @@ namespace zsy
|
|||
{
|
||||
throw std::system_error(errno, std::generic_category(), "写入文件失败");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("图片保存失败");
|
||||
return false;
|
||||
}catch (...)
|
||||
{
|
||||
LOGGER_ERROR("未知异常,图片保存失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,7 @@ namespace zsy
|
|||
: config(config)
|
||||
, hasNewContent(false)
|
||||
{
|
||||
SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp");
|
||||
auto cli = Application::mqttCliHolder->localCli();
|
||||
// SysUtil::createDirs(SysUtil::HOME_DIR + "\\temp");
|
||||
Application::eventManager->subscribe(MqttCli::TYPE_LOCAL + "/device/" + config.ip + "/message/up/snapshot", [this](const EventManager::Event &event)
|
||||
{
|
||||
if (!event.data.has_value())
|
||||
|
@ -76,7 +75,7 @@ namespace zsy
|
|||
});
|
||||
}
|
||||
|
||||
std::string BarrierVidicon::photograph()
|
||||
std::shared_ptr<std::istream> BarrierVidicon::photograph()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -117,10 +116,9 @@ namespace zsy
|
|||
} while (i <= 10 && !hasNewContent.load());
|
||||
|
||||
const auto filename = "car_body_" + Snowflake::genIdStr() + ".jpg";
|
||||
std::string path = SysUtil::HOME_DIR + "\\temp\\" + filename;
|
||||
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
|
||||
{
|
||||
LOGGER_ERROR("未找到 MQTT 本地客户端");
|
||||
|
@ -132,16 +130,16 @@ namespace zsy
|
|||
{
|
||||
LOGGER_ERROR("未知异常,拍照失败");
|
||||
}
|
||||
return "";
|
||||
return nullptr;
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("摄像机拍照失败:{}", e.what());
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOGGER_ERROR("未知异常,摄像机拍照失败");
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,14 +34,14 @@ namespace zsy
|
|||
std::atomic<bool> hasNewContent;
|
||||
std::string imageContent;
|
||||
|
||||
bool saveImageToFile(const std::string &decodedImageData, const std::string &filePath);
|
||||
void saveImageToFile(const std::string &decodedImageData, const std::string &filePath);
|
||||
|
||||
public:
|
||||
~BarrierVidicon() override;
|
||||
|
||||
explicit BarrierVidicon(const VidiconProperties &config);
|
||||
|
||||
std::string photograph() override;
|
||||
std::shared_ptr<std::istream> photograph() override;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "generic_vidicon.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "HCNetSDK.h"
|
||||
#include "common/snowflake.h"
|
||||
#include "common/sys_util.h"
|
||||
|
@ -15,7 +18,76 @@ namespace zsy
|
|||
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
|
||||
{
|
||||
|
@ -73,7 +145,11 @@ namespace zsy
|
|||
NET_DVR_Logout_V30(lLoginID);
|
||||
NET_DVR_Cleanup();
|
||||
|
||||
return path;
|
||||
auto content = read(path);
|
||||
|
||||
remove(path);
|
||||
|
||||
return content;
|
||||
} catch (std::exception &e)
|
||||
{
|
||||
LOGGER_ERROR("摄像机拍照失败:{}", e.what());
|
||||
|
|
|
@ -8,12 +8,17 @@ namespace zsy
|
|||
class GenericVidicon : public Vidicon
|
||||
{
|
||||
VidiconProperties config;
|
||||
|
||||
public:
|
||||
~GenericVidicon() override;
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include "test_vidicon.h"
|
||||
|
||||
namespace zsy {
|
||||
std::string TestVidicon::photograph()
|
||||
namespace zsy
|
||||
{
|
||||
return "";
|
||||
std::shared_ptr<std::istream> TestVidicon::photograph()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
} // zsy
|
|
@ -7,7 +7,7 @@ namespace zsy
|
|||
class TestVidicon : public Vidicon
|
||||
{
|
||||
public:
|
||||
std::string photograph() override;
|
||||
std::shared_ptr<std::istream> photograph() override;
|
||||
};
|
||||
} // zsy
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef VIDICON_H
|
||||
#define VIDICON_H
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
@ -10,7 +11,7 @@ namespace zsy
|
|||
public:
|
||||
virtual ~Vidicon() = default;
|
||||
|
||||
virtual std::string photograph() = 0;
|
||||
virtual std::shared_ptr<std::istream> photograph() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue