From ada31ffca061e5d2286160b03727914e15adb1e3 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Mon, 19 Aug 2024 13:38:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0pdf=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 94 ++++----- README.md | 1 + .../appevent/app_disinfection_finished_event.hpp | 17 +- .../appevent/app_disinfection_snapshot_event.hpp | 2 + appsrc/appbase/utils/zsimplepdf.cpp | 224 ++++++++++++++++++++ appsrc/appbase/utils/zsimplepdf.hpp | 79 +++++++ .../disinfection_ctrl_service.cpp | 14 +- .../disinfection_ctrl_service.hpp | 2 +- appsrc/service/disinfection_logs_service.cpp | 145 ++++++++++++- appsrc/service/disinfection_logs_service.hpp | 3 + buildpc.sh | 10 +- test/testpdf.cpp | 235 ++++----------------- 12 files changed, 568 insertions(+), 258 deletions(-) create mode 100644 appsrc/appbase/utils/zsimplepdf.cpp create mode 100644 appsrc/appbase/utils/zsimplepdf.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fc037c1..6008b70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,81 +52,65 @@ file( appsrc/*.c # appsrc/*.hpp # appsrc/*.h # - appdep/*.cpp # - appdep/*.c # - appdep/*.hpp # - appdep/*.h # app_protocols/*.cpp # app_protocols/*.c # app_protocols/*.hpp # app_protocols/*.h # ) -zadd_executable( - TARGET - app.out - # - # INSTALL PATH - # - INSTALL - ./app/ - # - # SRC - # - SRC - ${APP_SRC} - # - # INCLUDE_DIRECTORIES - # - INCLUDE_DIRECTORIES - appdep/iflytop/core/spdlog/include - appsrc/ - appdep/ - app_protocols/ - ./ - appdep/libs/libixwebsocket/include - # - # LINK_LIBRARIES - # - LINK_LIBRARIES +file( + GLOB_RECURSE + APP_DEP_SRC # + appdep/*.cpp # + appdep/*.c # + appdep/*.hpp # + appdep/*.h # +) + +include_directories( + appdep/iflytop/core/spdlog/include # + appsrc/ # + appdep/ # + app_protocols/ # + ./ # + appdep/libs/libixwebsocket/include # + appdep/libs/libhpdf/include) + +link_directories(appdep/libs/libixwebsocket/${ARCH}/ + appdep/libs/libhpdf/${ARCH}/) + +link_libraries( pthread + hpdf ixwebsocket z crypto ssl dl - sqlite3 - # - # LINK_DIRECTORIES - # - LINK_DIRECTORIES - # - appdep/libs/libixwebsocket/${ARCH}/ - appdep/libs/libhpdf/${ARCH}/) + sqlite3) + +# ******************************************************************************* +# * APP * +# ******************************************************************************* zadd_executable( TARGET - zcsv_test.out - # SRC + app.out + INSTALL + ./app/ SRC - ./test/zcsv_test.cpp - appdep/iflytop/core/components/zcsv/zcsv.cpp - # INCLUDE_DIRECTORIES - INCLUDE_DIRECTORIES - appdep/) + ${APP_DEP_SRC} + ${APP_SRC}) # # testpdf # zadd_executable( TARGET - testpdf.out + testpdf.out # + INSTALL + ./app/ # SRC - ./test/testpdf.cpp - INCLUDE_DIRECTORIES - appdep/libs/libhpdf/include - LINK_LIBRARIES - hpdf - z - LINK_DIRECTORIES - appdep/libs/libhpdf/${ARCH}/) + ${APP_DEP_SRC} + appsrc/appbase/utils/zsimplepdf.cpp + ./test/testpdf.cpp) diff --git a/README.md b/README.md index fc0e059..0b577f0 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ TODO: 整理错误码,为所有错误吗添加中文示意 消毒过程中检测水禁传感器, +添加日志自动删除逻辑 ... 5. 单片机支持自动过滤掉重发的指令。 diff --git a/appsrc/appbase/appevent/app_disinfection_finished_event.hpp b/appsrc/appbase/appevent/app_disinfection_finished_event.hpp index 77ac4f6..112b10c 100644 --- a/appsrc/appbase/appevent/app_disinfection_finished_event.hpp +++ b/appsrc/appbase/appevent/app_disinfection_finished_event.hpp @@ -2,14 +2,25 @@ #include "iapp_event.hpp" namespace iflytop { +class DisinfectionStatistics { + public: + zsystem_tp start_tp = {}; + zsystem_tp complete_tp = {}; + int disinfectantVolume_g = {}; // 消毒剂量 + int tLog = 0; // target log + int finalLog = 0; // final log +}; + class AppDisinfectionFinishedEvent : public IAppEvent { private: - string sessionId; + string sessionId; + shared_ptr disinfectionStatistics; public: - AppDisinfectionFinishedEvent(string sessionId) : sessionId(sessionId) {} + AppDisinfectionFinishedEvent(string sessionId, shared_ptr disinfectionStatistics) : sessionId(sessionId), disinfectionStatistics(disinfectionStatistics) {} virtual ~AppDisinfectionFinishedEvent() {} - string getSessionId() { return sessionId; } + string getSessionId() { return sessionId; } + shared_ptr getDisinfectionStatistics() { return disinfectionStatistics; } }; } // namespace iflytop \ No newline at end of file diff --git a/appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp b/appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp index 2b62744..bb67d4c 100644 --- a/appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp +++ b/appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp @@ -13,6 +13,8 @@ class DisinfectionStateSnapshot { shared_ptr h2o2Snapshot; + bool forcelog = false; + float dval = 0; float nlog = 0; float tlog = 0; diff --git a/appsrc/appbase/utils/zsimplepdf.cpp b/appsrc/appbase/utils/zsimplepdf.cpp new file mode 100644 index 0000000..59bdfbe --- /dev/null +++ b/appsrc/appbase/utils/zsimplepdf.cpp @@ -0,0 +1,224 @@ +#include "zsimplepdf.hpp" +using namespace iflytop; + +void ZSimplePDF::ZSimplePDF::spitText(const string& content, list& textlist) { + textlist.clear(); + // 按行分割字符串 + std::istringstream stream(content); + std::string line; + + while (std::getline(stream, line)) { + textlist.push_back(line); + } +} + +void ZSimplePDF::forceMkdir(string filename) { + string::size_type sepPos = filename.find_last_of("/"); + if (sepPos != string::npos) { + string dirPath = filename.substr(0, sepPos); + system(("mkdir -p " + dirPath).c_str()); + } +} + +void ZSimplePDF::buildPDFAndFont(HPDF_Doc& pdf, HPDF_Font& font) { + pdf = HPDF_New(error_handler, this); + ZASSERT(pdf); + // install chinese fonts + HPDF_UseCNSFonts(pdf); + HPDF_UseCNTFonts(pdf); + HPDF_UseCNTEncodings(pdf); + HPDF_UseCNSEncodings(pdf); + + // getFont + font = HPDF_GetFont(pdf, "SimSun", "GBK-EUC-H"); + ZASSERT(font); +} + +ZSimplePDF::ZSimplePDF(string filename, int defaultFrontSize) : m_fileName(filename), m_defaultFrontSize(defaultFrontSize) {} + +void ZSimplePDF::newPage() { + if (curPage != nullptr) { + pushPage(); + } + shared_ptr pPage = make_shared(); + curPage = pPage; +} +void ZSimplePDF::pushPage() { + ZASSERT(curPage); + if (curContent) { + curPage->contents.push_back(curContent); + curContent = nullptr; + } + m_pages.push_back(curPage); + curPage = nullptr; +} + +void ZSimplePDF::newConent(int frontSize) { + if (curPage == nullptr) { + newPage(); + } + if (curContent != nullptr) { + pushContent(); + } + + shared_ptr pContent = make_shared(); + pContent->fontSize = frontSize; + curContent = pContent; +} + +void ZSimplePDF::pushContent() { + ZASSERT(curPage); + ZASSERT(curContent); + curPage->contents.push_back(curContent); + curContent = nullptr; +} + +void ZSimplePDF::addText(const string& text) { + if (curPage == nullptr) { + newPage(); + } + if (curContent == nullptr) { + newConent(m_defaultFrontSize); + } + list textlist; + spitText(text, textlist); + curContent->textlist.insert(curContent->textlist.end(), textlist.begin(), textlist.end()); +} + +void ZSimplePDF::utf8ToGb2312(const string& incontent, string& output) { + // 打开转换描述符 + iconv_t cd = iconv_open("GB2312", "UTF-8"); + if (cd == (iconv_t)-1) { + perror("iconv_open failed"); + exit(EXIT_FAILURE); + } + + // 输入字符串 + const char* in_str = incontent.c_str(); + size_t in_size = incontent.size(); + + // 输出缓冲区 + size_t out_size = in_size * 2; // 假设输出的字节数不会超过输入的两倍 + char* out_buf = new char[out_size]; + char* out_str = out_buf; + + // 进行转换 + if (iconv(cd, const_cast(&in_str), &in_size, &out_str, &out_size) == (size_t)-1) { + perror("iconv failed"); + iconv_close(cd); + delete[] out_buf; + exit(EXIT_FAILURE); + } + + // 关闭转换描述符 + iconv_close(cd); + + // 获取转换后的字符串 + std::string gb2312_str(out_buf, out_str - out_buf); + // 释放内存 + delete[] out_buf; + output = gb2312_str; +} + +void ZSimplePDF::utf8ToGb2312() { + for (auto& page : m_pages) { + for (auto& content : page->contents) { + for (auto& line : content->textlist) { + string gb2312; + utf8ToGb2312(line, gb2312); + line = gb2312; + } + } + } +} + +float ZSimplePDF::findTextMaxWidth(shared_ptr content) { + HPDF_Doc pdf; + HPDF_Font font; + buildPDFAndFont(pdf, font); + HPDF_Page szPage = HPDF_AddPage(pdf); + HPDF_Page_SetFontAndSize(szPage, font, content->fontSize); + + float maxWidth = 0; + for (auto& line : content->textlist) { + float size = HPDF_Page_TextWidth(szPage, line.c_str()); + if (size > maxWidth) { + maxWidth = size; + } + } + HPDF_Free(pdf); + return maxWidth; +} + +float ZSimplePDF::findTextMaxWidth() { + float maxWidth = 0; + for (auto& page : m_pages) { + for (auto& content : page->contents) { + float size = findTextMaxWidth(content); + if (size > maxWidth) { + maxWidth = size; + } + } + } + return maxWidth; +} + +int ZSimplePDF::findTextMaxHight() { + int maxHight = 0; + for (auto& page : m_pages) { + int hight = 0; + for (auto& content : page->contents) { + hight += (content->fontSize + linePadding) * content->textlist.size(); + } + if (hight > maxHight) { + maxHight = hight; + } + } + return maxHight; +} + +void ZSimplePDF::dump() { + if (curContent) pushContent(); + if (curPage) pushPage(); + + forceMkdir(m_fileName); + utf8ToGb2312(); + + float maxWidth = findTextMaxWidth(); + HPDF_Doc pdf; + HPDF_Font font; + buildPDFAndFont(pdf, font); + int pageHight = findTextMaxHight(); + + for (auto& page : m_pages) { + HPDF_Page szPage = HPDF_AddPage(pdf); + + HPDF_Page_SetSize(szPage, HPDF_PAGE_SIZE_COMM10, HPDF_PAGE_PORTRAIT); + // 设置页面高度 + HPDF_Page_SetHeight(szPage, pageHight + pagePadding * 2); + // 设置页面宽度 + HPDF_Page_SetWidth(szPage, maxWidth + pagePadding * 2); + + float writehpos = HPDF_Page_GetHeight(szPage); + writehpos -= pagePadding; + for (auto& content : page->contents) { + HPDF_Page_SetFontAndSize(szPage, font, content->fontSize); + for (auto& line : content->textlist) { + HPDF_Page_BeginText(szPage); + writehpos -= content->fontSize; + // printf("writehpos=%f\n", writehpos); + HPDF_Page_MoveTextPos(szPage, pagePadding, writehpos); + HPDF_Page_ShowText(szPage, line.c_str()); + HPDF_Page_EndText(szPage); + writehpos -= linePadding; + } + } + } + + HPDF_SaveToFile(pdf, m_fileName.c_str()); +}; + +void ZSimplePDF::error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) { // + ZSimplePDF* thisclass = (ZSimplePDF*)user_data; + thisclass->logger->error("ERROR: error_no={:x}, detail_no={:x}", (HPDF_UINT)error_no, (HPDF_UINT)detail_no); +} \ No newline at end of file diff --git a/appsrc/appbase/utils/zsimplepdf.hpp b/appsrc/appbase/utils/zsimplepdf.hpp new file mode 100644 index 0000000..b53056b --- /dev/null +++ b/appsrc/appbase/utils/zsimplepdf.hpp @@ -0,0 +1,79 @@ +#pragma once +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hpdf.h" +#include "iflytop/core/core.hpp" + +namespace iflytop { + +class ZSimplePDF { + THISCLASS(ZSimplePDF); + class Content { + public: + int fontSize = 20; + list textlist; + int maxWidth; + }; + + class Page { + public: + list> contents; + }; + + public: + string m_fileName; + int m_defaultFrontSize = 20; + int pagePadding = 5; + int linePadding = 10; + + HPDF_Doc m_pdf; + HPDF_Font m_font; + + // shared_ptr curContent; + list> m_pages; + + shared_ptr curPage; + shared_ptr curContent; + + public: + ZSimplePDF(string filename, int defaultFrontSize = 20); + + void newPage(); + void newConent(int frontSize = 20); + void addText(const string& text); + + void dump(); + + private: + void spitText(const string& content, list& textlist); + void forceMkdir(string filename); + + void buildPDFAndFont(HPDF_Doc& pdf, HPDF_Font& font); + + void utf8ToGb2312(const string& incontent, string& output); + void utf8ToGb2312(); + float findTextMaxWidth(shared_ptr content); + float findTextMaxWidth(); + int findTextMaxHight(); + + void pushContent(); + void pushPage(); + + static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data); +}; +} // namespace iflytop diff --git a/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.cpp b/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.cpp index 2629034..e2de9db 100644 --- a/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.cpp +++ b/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.cpp @@ -249,12 +249,12 @@ void DisinfectionCtrlService::tryLogState(bool forceLog) { // 每隔离10秒记录一次 if (forceLog || zsteady_clock().elapsedTimeS(s_lastTakeSnapt) > 10) { s_lastTakeSnapt = zsteady_clock().now(); - logState(); + logState(forceLog); traceState(); } } -void DisinfectionCtrlService::logState() { +void DisinfectionCtrlService::logState(bool forcelog) { shared_ptr snapshot = make_shared(); snapshot->state = sm.getState(); snapshot->time = zsystem_clock().now(); @@ -265,6 +265,7 @@ void DisinfectionCtrlService::logState() { snapshot->remainDisinfectant = dwus->getWeight(); snapshot->h2o2Snapshot = s_h2o2Snapshot; snapshot->ecode = s_error; + snapshot->forcelog = forcelog; AppEventBus::ins()->push(make_shared(snapshot)); } void DisinfectionCtrlService::traceState() { @@ -656,7 +657,14 @@ void DisinfectionCtrlService::processStateFinished(DisinfectionEvent* event) { // tryLogSatate(true); tryLogState(true); logger->info("finished disinfection {}", s_sessionId); - AppEventBus::ins()->push(make_shared(s_sessionId)); + shared_ptr statistice = make_shared(); + statistice->start_tp = s_start_tp; + statistice->complete_tp = s_complete_tp; + statistice->disinfectantVolume_g = s_afterDisinfectantVolume_g - s_beforeDisinfectantVolume_g; + statistice->tLog = m_tlog; + statistice->finalLog = s_nlog; + + AppEventBus::ins()->push(make_shared(s_sessionId, statistice)); return; } } diff --git a/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp b/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp index bef0d67..a7c09fa 100644 --- a/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp +++ b/appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp @@ -110,7 +110,7 @@ class DisinfectionCtrlService : public enable_shared_from_this4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", tm.tm_year + 1900, // + tm.tm_mon + 1, // + tm.tm_mday, // + tm.tm_hour, // + tm.tm_min, tm.tm_sec); +} static void listDirCSVFile(string path, vector& sv) { sv.clear(); @@ -99,6 +109,7 @@ static void split(const string& s, vector& sv, const char delim = ' ') { } return; } + /******************************************************************************* * CLASS * *******************************************************************************/ @@ -137,15 +148,38 @@ void DisinfectionLogsService::initialize() { m_csvHeaderDict.insert(CSVHeader::reamintime, "预计剩余时间"); m_dmStateDict.insert(DisinfectionState::idle, "空闲"); + m_dmStateDict.insert(DisinfectionState::init, "初始化"); m_dmStateDict.insert(DisinfectionState::preheat, "预热"); m_dmStateDict.insert(DisinfectionState::disinfection, "消毒"); - m_dmStateDict.insert(DisinfectionState::degradation, "讲解"); - m_dmStateDict.insert(DisinfectionState::finished, "消毒结束"); + m_dmStateDict.insert(DisinfectionState::degradation, "降解"); m_dmStateDict.insert(DisinfectionState::dehumidificationBeforeDisinfection, "消毒前除湿"); - m_dmStateDict.insert(DisinfectionState::emptyLiquidFromTheLine, "清空管路"); m_dmStateDict.insert(DisinfectionState::dehumidificationAfterDisinfection, "消毒后除湿"); + m_dmStateDict.insert(DisinfectionState::emptyLiquidFromTheLine, "清空管路"); + m_dmStateDict.insert(DisinfectionState::finished, "消毒结束"); + m_dmStateDict.insert(DisinfectionState::error, "错误"); // TODO: 检查指令iconv是否可用 + + AppEventBus::ins()->onEvent.connect([this](shared_ptr event) { + if (auto e = dynamic_pointer_cast(event); e) { + logger->info("DisinfectionLogsService: start new disinfection session"); + startNewDisinfectionSession(e->getSessionId()); + return; + } + + if (auto e = dynamic_pointer_cast(event); e) { + logger->info("DisinfectionLogsService: finish disinfection session"); + finishDisinfectionSession(); + m_statistics = e->getDisinfectionStatistics(); + return; + } + + if (auto e = dynamic_pointer_cast(event); e) { + logger->info("DisinfectionLogsService: push state snapshot"); + pushStateSnapshot(e->getStateSnapshot()); + return; + } + }); } void DisinfectionLogsService::startNewDisinfectionSession(string sessionId) { // @@ -161,7 +195,6 @@ void DisinfectionLogsService::finishDisinfectionSession() { * 2.创建PDF文件缓存 */ - clearRecordFiles(); } @@ -176,7 +209,28 @@ void DisinfectionLogsService::dumpDisinfectionRecord(string sessionId, listinfo("DisinfectionLogsService: dumpDisinfectionRecord, sessionId: {}, min period: {}s", sessionId, logdtime); + for (auto& s : snapshots) { + bool logthis = false; + + if (first) logthis = true; + if (s->forcelog) logthis = true; + if (s->state != state) logthis = true; + if (tu_sys().dToS(s->time - lastlogtime) > logdtime) logthis = true; + + if (!logthis) continue; + + first = false; + state = s->state; + lastlogtime = s->time; + csv.addValue(m_csvHeaderDict.getChName(CSVHeader::time), /******************/ tu_sys::fmt(s->time, "%Y-%m-%d %H:%M:%S")); csv.addValue(m_csvHeaderDict.getChName(CSVHeader::state), /*****************/ m_dmStateDict.getChName(s->state)); @@ -218,6 +272,89 @@ void DisinfectionLogsService::dumpDisinfectionRecord(string sessionId, list> snapshots) { + string content; + ZASSERT(snapshots.size() >= 2); + ZASSERT(m_statistics); + + int32_t totaltime_s = zsystem_clock().tpToS(m_statistics->complete_tp) - zsystem_clock().tpToS(m_statistics->start_tp); + int32_t total_hours = totaltime_s / 3600; + int32_t total_mins = (totaltime_s % 3600) / 60; + int32_t total_secs = totaltime_s % 60; + + int32_t logdtime = GET_SETTING(int, SettingId::record_printer_period_min) * 60; + + content += fmt::format("= = = = = = = = = = = = = = = \n"); + content += fmt::format(" 全思美特 \n"); + content += fmt::format("操作人 {}\n", GET_SERVICE(DeviceStateService)->getLoginUid()); + content += fmt::format("开始时间 {}\n", format_zsystem_tp(m_statistics->start_tp)); + content += fmt::format("结束时间 {}\n", format_zsystem_tp(m_statistics->complete_tp)); + content += fmt::format("总耗时(hh:mm::ss) {}:{}:{}\n", total_hours, total_mins, total_secs); + content += fmt::format("消毒液使用 {}g\n", m_statistics->disinfectantVolume_g); + content += fmt::format("目标LOG {}\n", m_statistics->tLog); + content += fmt::format("实际LOG {}\n", m_statistics->finalLog); + content += fmt::format("日志打印间隔: {}min\n", logdtime / 60); + content += fmt::format("= = = = = = = = = = = = = = = \n"); + + DisinfectionState state = DisinfectionState::idle; + bool first = true; + zsystem_tp lastlogtime; + + for (auto& snapshot : snapshots) { + bool logthis = false; + bool stateChanged = false; + + if (first) logthis = true; + if (snapshot->forcelog) logthis = true; + if (snapshot->state != state) { + logthis = true; + stateChanged = true; + } + if (tu_sys().dToS(snapshot->time - lastlogtime) > logdtime) logthis = true; + + if (!logthis) continue; + + content += fmt::format("{}\n", format_zsystem_tp(snapshot->time)); + if (stateChanged) { + content += fmt::format("{}\n", m_dmStateDict.getChName(snapshot->state)); + } + if (state == DisinfectionState::disinfection) { + content += fmt::format("LOG: {}\n", snapshot->nlog); + } + + if (state == DisinfectionState::disinfection) { + auto h2o2data = snapshot->h2o2Snapshot; + for (int i = 0; i < h2o2data->getSensorDataNum(); i++) { + if (i == 0) { + content += fmt::format(" [S0] {}ppm {}%RS {}%RH \n", h2o2data->isExpired[0] ? "N/A" : formatSensorVal(h2o2data->h2o2[0]), // + h2o2data->isExpired[0] ? "N/A" : formatSensorVal(h2o2data->saturation[0]), // + h2o2data->isExpired[0] ? "N/A" : formatSensorVal(h2o2data->humid[0])); + } + if (i == 1 && !h2o2data->isExpired[1]) { + content += fmt::format(" [S1] {}ppm {}%RS {}%RH \n", formatSensorVal(h2o2data->h2o2[1]), // + formatSensorVal(h2o2data->saturation[1]), // + formatSensorVal(h2o2data->humid[1])); + } + if (i == 2 && !h2o2data->isExpired[2]) { + content += fmt::format(" [S2] {}ppm {}%RS {}%RH \n", formatSensorVal(h2o2data->h2o2[2]), // + formatSensorVal(h2o2data->saturation[2]), // + formatSensorVal(h2o2data->humid[2])); + } + } + } + } + content += ("\n"); + content += ("\n"); + content += ("\n"); + content += ("\n"); + content += ("\n"); + content += ("\n"); + + FileUtils().writeToFile(fmt::format("{}{}.log", LOG_STORGE_PATH, sessionId), content.c_str(), content.size()); + logger->info("dump log to printer log file: {},\n", fmt::format("{}{}.log", LOG_STORGE_PATH, sessionId), content); +} +void DisinfectionLogsService::dumpDisinfectionToPrinterPdf(string sessionId, list> snapshots) {} + void DisinfectionLogsService::clearRecordFiles() { // TODO: 删除掉多余的csv文件 // TODO: 检查时间,如果已经存储文件的时间大于当前时间,也删掉 diff --git a/appsrc/service/disinfection_logs_service.hpp b/appsrc/service/disinfection_logs_service.hpp index 41bd6e2..dcdb82f 100644 --- a/appsrc/service/disinfection_logs_service.hpp +++ b/appsrc/service/disinfection_logs_service.hpp @@ -26,6 +26,7 @@ class DisinfectionLogsService : public enable_shared_from_this> m_snapshots; + shared_ptr m_statistics; ZDictionary m_csvHeaderDict; ZDictionary m_dmStateDict; @@ -41,6 +42,8 @@ class DisinfectionLogsService : public enable_shared_from_this> snapshots); + void dumpDisinfectionToPrinterLog(string sessionId, list> snapshots); + void dumpDisinfectionToPrinterPdf(string sessionId, list> snapshots); private: /******************************************************************************* diff --git a/buildpc.sh b/buildpc.sh index f68ef71..d94c582 100755 --- a/buildpc.sh +++ b/buildpc.sh @@ -1,7 +1,7 @@ #!/bin/bash # -# ./build.sh +# ./build.sh # # PROJECT_TYPE_LARGE_SPACE_DISINFECTION # PROJECT_TYPE_SMALL_SPACE_DISINFECTION @@ -14,7 +14,11 @@ inittestdata.sh cd build cmake .. \ - -DARCH=amd64 \ + -DARCH=amd64 make -j8 -make install \ No newline at end of file + +cmake .. \ + -DARCH=amd64 +make -j8 +make install diff --git a/test/testpdf.cpp b/test/testpdf.cpp index 351ab5e..323a9dd 100644 --- a/test/testpdf.cpp +++ b/test/testpdf.cpp @@ -11,204 +11,61 @@ * It is provided "as is" without express or implied warranty. * */ - +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include -// #include -#include "hpdf.h" - -#ifdef HPDF_DLL -void __stdcall -#else -void -#endif - error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data) { - printf("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no); -} - -// const char *font_list[] = {"SimHei", NULL}; - -// int main(int argc, char **argv) { -// const char *page_title = "Font Demo"; -// HPDF_Doc pdf; -// char fname[256]; -// HPDF_Page page; -// HPDF_Font def_font; -// HPDF_REAL tw; -// HPDF_REAL height; -// HPDF_REAL width; -// HPDF_UINT i; - -// strcpy(fname, argv[0]); -// strcat(fname, ".pdf"); - -// pdf = HPDF_New(error_handler, NULL); -// if (!pdf) { -// printf("error: cannot create PdfDoc object\n"); -// return 1; -// } - -// HPDF_STATUS statu = HPDF_UseCNSFonts(pdf); -// printf("HPDF_UseCNSFonts: %x\n", statu); -// statu = HPDF_UseCNTFonts(pdf); -// printf("HPDF_UseCNTFonts: %x\n", statu); -// statu = HPDF_UseCNTEncodings(pdf); -// printf("HPDF_UseCNTEncodings: %x\n", statu); -// statu = HPDF_UseCNSEncodings(pdf); -// printf("HPDF_UseCNSEncodings: %x\n", statu); - -// try { -// /* Add a new page object. */ -// page = HPDF_AddPage(pdf); - -// height = HPDF_Page_GetHeight(page); -// width = HPDF_Page_GetWidth(page); - -// /* Print the lines of the page. */ -// HPDF_Page_SetLineWidth(page, 1); -// HPDF_Page_Rectangle(page, 50, 50, width - 100, height - 110); -// HPDF_Page_Stroke(page); - -// /* Print the title of the page (with positioning center). */ -// def_font = HPDF_GetFont(pdf, "Helvetica", NULL); -// HPDF_Page_SetFontAndSize(page, def_font, 24); - -// tw = HPDF_Page_TextWidth(page, page_title); -// HPDF_Page_BeginText(page); -// HPDF_Page_MoveTextPos(page, (width - tw) / 2, height - 50); -// HPDF_Page_ShowText(page, page_title); -// HPDF_Page_EndText(page); - -// /* output subtitle. */ -// HPDF_Page_BeginText(page); -// HPDF_Page_MoveTextPos(page, 60, height - 80); -// HPDF_Page_SetFontAndSize(page, def_font, 16); -// HPDF_Page_ShowText(page, ""); -// HPDF_Page_EndText(page); - -// HPDF_Page_BeginText(page); -// HPDF_Page_MoveTextPos(page, 60, height - 105); - -// i = 0; -// while (font_list[i]) { -// const char *samp_text = "abcd"; -// HPDF_Font font = HPDF_GetFont(pdf, font_list[i], NULL); -// if (!font) { -// printf("error: cannot get %s font\n", font_list[i]); -// return 1; -// } - -// /* print a label of text */ -// HPDF_Page_SetFontAndSize(page, def_font, 9); -// HPDF_Page_ShowText(page, font_list[i]); -// HPDF_Page_MoveTextPos(page, 0, -18); - -// /* print a sample text. */ -// HPDF_Page_SetFontAndSize(page, font, 20); -// HPDF_Page_ShowText(page, samp_text); -// HPDF_Page_MoveTextPos(page, 0, -20); - -// i++; -// } - -// HPDF_Page_EndText(page); - -// HPDF_SaveToFile(pdf, fname); - -// } catch (...) { -// HPDF_Free(pdf); -// return 1; -// } +#include -// /* clean up */ -// HPDF_Free(pdf); - -// return 0; -// } +#include "appbase/utils/zsimplepdf.hpp" using namespace std; - -string utf8_to_gb2312(const std::string& utf8_str) { - // 打开转换描述符 - iconv_t cd = iconv_open("GB2312", "UTF-8"); - if (cd == (iconv_t)-1) { - perror("iconv_open failed"); - exit(EXIT_FAILURE); - } - - // 输入字符串 - const char* in_str = utf8_str.c_str(); - size_t in_size = utf8_str.size(); - - // 输出缓冲区 - size_t out_size = in_size * 2; // 假设输出的字节数不会超过输入的两倍 - char* out_buf = new char[out_size]; - char* out_str = out_buf; - - // 进行转换 - if (iconv(cd, const_cast(&in_str), &in_size, &out_str, &out_size) == (size_t)-1) { - perror("iconv failed"); - iconv_close(cd); - delete[] out_buf; - exit(EXIT_FAILURE); - } - - // 关闭转换描述符 - iconv_close(cd); - - // 获取转换后的字符串 - std::string gb2312_str(out_buf, out_str - out_buf); - // 释放内存 - delete[] out_buf; - return gb2312_str; -} +using namespace iflytop; int main() { - HPDF_Doc pdf; - HPDF_Font font; - HPDF_Page szPage[10115]; - HPDF_REAL tw; - - string strPdfContent = utf8_to_gb2312("这是一个测试,支持中文"); - - string strPdfName = "XXX.pdf"; - - pdf = HPDF_New(error_handler, NULL); - - HPDF_UseCNSFonts(pdf); - HPDF_UseCNTFonts(pdf); - HPDF_UseCNTEncodings(pdf); - HPDF_UseCNSEncodings(pdf); - - // support Chinese Song (SimSun)and Chinese black (SimHei) - font = HPDF_GetFont(pdf, "SimSun", "GBK-EUC-H"); - if (!font) { - printf("error: cannot get font\n"); - return 1; - } - - for (int i = 0; i < 10115; ++i) { - szPage[i] = HPDF_AddPage(pdf); - - HPDF_Page_SetSize(szPage[i], HPDF_PAGE_SIZE_LETTER, HPDF_PAGE_PORTRAIT); - - HPDF_Page_BeginText(szPage[i]); - - HPDF_Page_SetFontAndSize(szPage[i], font, 20); - - tw = HPDF_Page_TextWidth(szPage[i], strPdfContent.c_str()); - - HPDF_Page_MoveTextPos(szPage[i], (HPDF_Page_GetWidth(szPage[i]) - tw) / 2, (HPDF_Page_GetHeight(szPage[i]) - 20) / 2); - - HPDF_Page_ShowText(szPage[i], strPdfContent.c_str()); - - HPDF_Page_EndText(szPage[i]); - } - - HPDF_SaveToFile(pdf, strPdfName.c_str()); - HPDF_Free(pdf); + ZSimplePDF pdf("test.pdf"); + pdf.newConent(30); + pdf.addText("Page0 Size30 文件头.....\n"); + pdf.newConent(20); + pdf.addText("文件内容 文件内容\n"); + pdf.addText("文件内容 文件内容\n"); + pdf.addText("文件内容 文件内容\n"); + pdf.newConent(15); + pdf.addText("文件内容 文件内容\n"); + + pdf.newPage(); + + pdf.newConent(30); + pdf.addText("Page1 Size30 文件头.....\n"); + pdf.newConent(20); + pdf.addText("文件内容 文件内容\n"); + pdf.addText("文件内容 文件内容\n"); + pdf.addText("文件内容 文件内容\n"); + pdf.newConent(15); + pdf.addText("文件内容 文件内容\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + pdf.addText("\n"); + + pdf.dump(); + // pdf.dump("test.pdf", "940年3月,英国物理学家奥托弗里施鲁道夫佩尔斯撰写了弗"); + return 0; } \ No newline at end of file