修复问题

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("等待...");
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);

View File

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

View File

@ -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

View File

@ -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;
Application::threadPool->submit([recognizeResult]
{
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)
{
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);
}
}

View File

@ -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

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 "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,23 +46,18 @@ namespace zsy
}
}
for (auto fn_ptr: *list)
if (list == nullptr || list->size() == 0)
{
/*try
{
(*fn_ptr.get())(Event(name, data));
} catch (const std::exception &e)
{
LOGGER_ERROR("事件处理异常:{} {}", name, e.what());
}catch (...)
{
LOGGER_ERROR("事件处理异常:{}", name);
}*/
threadPool->submit([fn = fn_ptr.get(),name,data]
return;
}
threadPool->submit([list, name, data]
{
for (auto fn_ptr: *list)
{
try
{
(*fn)(Event(name, data));
(*fn_ptr.get())(Event(name, data));
} catch (const std::exception &e)
{
LOGGER_ERROR("事件处理异常:{} {}", name, e.what());
@ -60,7 +65,7 @@ namespace zsy
{
LOGGER_ERROR("事件处理异常:{}", name);
}
});
}
}
});
}
} // zsy

View File

@ -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

View File

@ -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 \

View File

@ -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)
{
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)
{
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

View File

@ -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();

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 photograph = Application::deviceHolder->getVidicon(sn)->photograph();
j["结果"] = photograph;
j["结果"] = "";
} catch (std::exception &e)
{
LOGGER_ERROR("错误", e.what());

View File

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

View File

@ -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);

View File

@ -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);
};

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

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

View File

@ -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())
@ -63,7 +62,7 @@ namespace zsy
imageContent = res.payload.image_content;
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())
{
@ -76,12 +75,12 @@ namespace zsy
});
}
std::string BarrierVidicon::photograph()
std::shared_ptr<std::istream> BarrierVidicon::photograph()
{
try
{
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{
{"id", "photograph" + std::to_string(timestamp)},
{"sn", config.ip},
@ -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;
}
}
}

View File

@ -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;
};
}

View File

@ -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());

View File

@ -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

View File

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

View File

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

View File

@ -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;
};
}