Browse Source

添加pdf组件

storage-in-realtime
zhaohe 12 months ago
parent
commit
ada31ffca0
  1. 94
      CMakeLists.txt
  2. 1
      README.md
  3. 17
      appsrc/appbase/appevent/app_disinfection_finished_event.hpp
  4. 2
      appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp
  5. 224
      appsrc/appbase/utils/zsimplepdf.cpp
  6. 79
      appsrc/appbase/utils/zsimplepdf.hpp
  7. 14
      appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.cpp
  8. 2
      appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp
  9. 145
      appsrc/service/disinfection_logs_service.cpp
  10. 3
      appsrc/service/disinfection_logs_service.hpp
  11. 10
      buildpc.sh
  12. 235
      test/testpdf.cpp

94
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)

1
README.md

@ -84,6 +84,7 @@ TODO:
整理错误码,为所有错误吗添加中文示意
消毒过程中检测水禁传感器,
添加日志自动删除逻辑
...
5. 单片机支持自动过滤掉重发的指令。

17
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> disinfectionStatistics;
public:
AppDisinfectionFinishedEvent(string sessionId) : sessionId(sessionId) {}
AppDisinfectionFinishedEvent(string sessionId, shared_ptr<DisinfectionStatistics> disinfectionStatistics) : sessionId(sessionId), disinfectionStatistics(disinfectionStatistics) {}
virtual ~AppDisinfectionFinishedEvent() {}
string getSessionId() { return sessionId; }
string getSessionId() { return sessionId; }
shared_ptr<DisinfectionStatistics> getDisinfectionStatistics() { return disinfectionStatistics; }
};
} // namespace iflytop

2
appsrc/appbase/appevent/app_disinfection_snapshot_event.hpp

@ -13,6 +13,8 @@ class DisinfectionStateSnapshot {
shared_ptr<H2O2SensorDataSnapshot> h2o2Snapshot;
bool forcelog = false;
float dval = 0;
float nlog = 0;
float tlog = 0;

224
appsrc/appbase/utils/zsimplepdf.cpp

@ -0,0 +1,224 @@
#include "zsimplepdf.hpp"
using namespace iflytop;
void ZSimplePDF::ZSimplePDF::spitText(const string& content, list<string>& 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<Page> pPage = make_shared<Page>();
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<Content> pContent = make_shared<Content>();
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<string> 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<char**>(&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> 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);
}

79
appsrc/appbase/utils/zsimplepdf.hpp

@ -0,0 +1,79 @@
#pragma once
#include <assert.h>
#include <iconv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include "hpdf.h"
#include "iflytop/core/core.hpp"
namespace iflytop {
class ZSimplePDF {
THISCLASS(ZSimplePDF);
class Content {
public:
int fontSize = 20;
list<string> textlist;
int maxWidth;
};
class Page {
public:
list<shared_ptr<Content>> 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<Content> curContent;
list<shared_ptr<Page>> m_pages;
shared_ptr<Page> curPage;
shared_ptr<Content> 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<string>& 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> 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

14
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<DisinfectionStateSnapshot> snapshot = make_shared<DisinfectionStateSnapshot>();
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<AppDisinfectionSnapshotEvent>(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<AppDisinfectionFinishedEvent>(s_sessionId));
shared_ptr<DisinfectionStatistics> statistice = make_shared<DisinfectionStatistics>();
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<AppDisinfectionFinishedEvent>(s_sessionId, statistice));
return;
}
}

2
appsrc/service/app/disinfection_ctrl/disinfection_ctrl_service.hpp

@ -110,7 +110,7 @@ class DisinfectionCtrlService : public enable_shared_from_this<DisinfectionCtrlS
private:
void tryLogState(bool forceLog);
void logState();
void logState(bool forcelog);
void traceState();
};

145
appsrc/service/disinfection_logs_service.cpp

@ -58,6 +58,16 @@ static string formatSensorVal(int val) {
return fmt::format("{}", val);
}
}
static string format_zsystem_tp(zsystem_tp tp) {
time_t time = system_clock().to_time_t(tp);
struct tm tm = {0};
localtime_r(&time, &tm);
return fmt::format("{:0>4}-{: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<string>& sv) {
sv.clear();
@ -99,6 +109,7 @@ static void split(const string& s, vector<string>& 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<IAppEvent> event) {
if (auto e = dynamic_pointer_cast<AppDisinfectionStartEvent>(event); e) {
logger->info("DisinfectionLogsService: start new disinfection session");
startNewDisinfectionSession(e->getSessionId());
return;
}
if (auto e = dynamic_pointer_cast<AppDisinfectionFinishedEvent>(event); e) {
logger->info("DisinfectionLogsService: finish disinfection session");
finishDisinfectionSession();
m_statistics = e->getDisinfectionStatistics();
return;
}
if (auto e = dynamic_pointer_cast<AppDisinfectionSnapshotEvent>(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, list<shar
// 保存到记录到csv文件中
//
ZCSV csv;
DisinfectionState state = DisinfectionState::idle;
bool first = true;
zsystem_tp lastlogtime;
int32_t logdtime = GET_SETTING(int, SettingId::record_period_min) * 60;
logger->info("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<shar
csv.dumpCSV(fmt::format("{}{}.csv", LOG_STORGE_PATH, sessionId));
}
void DisinfectionLogsService::dumpDisinfectionToPrinterLog(string sessionId, list<shared_ptr<DisinfectionStateSnapshot>> 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<shared_ptr<DisinfectionStateSnapshot>> snapshots) {}
void DisinfectionLogsService::clearRecordFiles() {
// TODO: 删除掉多余的csv文件
// TODO: 检查时间,如果已经存储文件的时间大于当前时间,也删掉

3
appsrc/service/disinfection_logs_service.hpp

@ -26,6 +26,7 @@ class DisinfectionLogsService : public enable_shared_from_this<DisinfectionLogsS
string m_sessionId;
list<shared_ptr<DisinfectionStateSnapshot>> m_snapshots;
shared_ptr<DisinfectionStatistics> m_statistics;
ZDictionary m_csvHeaderDict;
ZDictionary m_dmStateDict;
@ -41,6 +42,8 @@ class DisinfectionLogsService : public enable_shared_from_this<DisinfectionLogsS
private:
void dumpDisinfectionRecord(string sessionId, list<shared_ptr<DisinfectionStateSnapshot>> snapshots);
void dumpDisinfectionToPrinterLog(string sessionId, list<shared_ptr<DisinfectionStateSnapshot>> snapshots);
void dumpDisinfectionToPrinterPdf(string sessionId, list<shared_ptr<DisinfectionStateSnapshot>> snapshots);
private:
/*******************************************************************************

10
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
cmake .. \
-DARCH=amd64
make -j8
make install

235
test/testpdf.cpp

@ -11,204 +11,61 @@
* It is provided "as is" without express or implied warranty.
*
*/
#include <assert.h>
#include <iconv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
// #include <exception>
#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, "<Standerd Type1 fonts samples>");
// 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 <vector>
// /* 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<char**>(&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;
}
Loading…
Cancel
Save