修复问题

master
lzq 2025-07-09 19:16:33 +08:00
parent 13ca181d34
commit 935b227d20
13 changed files with 546 additions and 18 deletions

View File

@ -27,7 +27,7 @@
{ {
"sn": "remote", "sn": "remote",
"name": "远程", "name": "远程",
"server": "47.117.76.168", "server": "127.0.0.1",
"port": 1883, "port": 1883,
"clientId": "yztq", "clientId": "yztq",
"username": "dcs", "username": "dcs",

View File

@ -0,0 +1,137 @@
{
"name": "牛能专用",
"delay": 60,
"daemon": true,
"httpSvr": {
"port": 11000
},
"oss": {
"endpoint": "oss-cn-shanghai.aliyuncs.com",
"bucketName": "tq-cdn",
"ak": "LTAI5t9ppUx8fkEnPwnNwmnx",
"sk": "uxrwL01P1Nw6M3YRFWoMIluY4swKwC"
},
"mqtts": [
{
"sn": "local",
"name": "本地",
"server": "127.0.0.1",
"port": 1883,
"clientId": "local",
"username": "dcs",
"password": "123456",
"subscribes": [
{
"topic": "stop",
"qos": 0
}
]
},
{
"sn": "remote",
"name": "远程",
"server": "47.117.76.168",
"port": 1883,
"clientId": "yztq",
"username": "dcs",
"password": "123456",
"subscribes": [
{
"topic": "yztq/1/barrier",
"qos": 0
},
{
"topic": "yztq/1/voice",
"qos": 0
}
]
}
],
"reportSvr": {
"server": "https://biz-api.jstqhj.cn:443",
"passUrl": "/api/site/report-car-pass?debug=1",
"reportUrl": "/api/site/report-v2?debug=1"
},
"barriers": [
{
"name": "进前置",
"sn": "b11ceeb5-af42d80f",
"ip": "192.168.120.240",
"io": 0,
"platformScale": "1",
"soundColumn": "1",
"vidicon": "1"
},
{
"name": "进",
"sn": "25ec7559-74125e77",
"ip": "192.168.120.235",
"io": 0,
"platformScale": "1",
"soundColumn": "2",
"vidicon": "1"
},
{
"name": "出前置",
"sn": "351b2406-6fae5ab5",
"ip": "192.168.120.243",
"io": 0,
"platformScale": "1",
"soundColumn": "2",
"vidicon": "2"
},
{
"name": "出",
"sn": "34fc9ce5-8b091060",
"ip": "192.168.120.238",
"io": 0,
"platformScale": "1",
"soundColumn": "1",
"vidicon": "2"
}
],
"platformScales": [
{
"sn": "1",
"name": "地磅",
"sample": 20,
"port": "COM2",
"baudRate": 1200,
"byteSize": 8,
"parity": 0,
"stopBits": 0
}
],
"soundColumns": [
{
"sn": "1",
"name": "音柱1",
"server": "http://192.168.120.246:80",
"path": "/v1/speech"
},
{
"sn": "2",
"name": "音柱2",
"server": "http://192.168.120.237:80",
"path": "/v1/speech"
}
],
"vidicons": [
{
"sn": "1",
"name": "摄像头1",
"ip": "192.168.120.245",
"port": 8000,
"username": "admin",
"passwd": "gk147258"
},
{
"sn": "2",
"name": "摄像头2",
"ip": "192.168.120.244",
"port": 8000,
"username": "admin",
"passwd": "gk147258"
}
]
}

View File

@ -0,0 +1,137 @@
{
"name": "天勤专用",
"delay": 60,
"daemon": true,
"httpSvr": {
"port": 11000
},
"oss": {
"endpoint": "oss-cn-shanghai.aliyuncs.com",
"bucketName": "tq-cdn",
"ak": "LTAI5t9ppUx8fkEnPwnNwmnx",
"sk": "uxrwL01P1Nw6M3YRFWoMIluY4swKwC"
},
"mqtts": [
{
"sn": "local",
"name": "本地",
"server": "127.0.0.1",
"port": 1883,
"clientId": "local",
"username": "dcs",
"password": "123456",
"subscribes": [
{
"topic": "stop",
"qos": 0
}
]
},
{
"sn": "remote",
"name": "远程",
"server": "47.117.76.168",
"port": 1883,
"clientId": "yztq",
"username": "dcs",
"password": "123456",
"subscribes": [
{
"topic": "yztq/1/barrier",
"qos": 0
},
{
"topic": "yztq/1/voice",
"qos": 0
}
]
}
],
"reportSvr": {
"server": "https://biz-api.jstqhj.cn:443",
"passUrl": "/api/site/report-car-pass?debug=1",
"reportUrl": "/api/site/report-v2?debug=1"
},
"barriers": [
{
"name": "进前置",
"sn": "b11ceeb5-af42d80f",
"ip": "192.168.120.240",
"io": 0,
"platformScale": "1",
"soundColumn": "1",
"vidicon": "1"
},
{
"name": "进",
"sn": "25ec7559-74125e77",
"ip": "192.168.120.235",
"io": 0,
"platformScale": "1",
"soundColumn": "2",
"vidicon": "1"
},
{
"name": "出前置",
"sn": "351b2406-6fae5ab5",
"ip": "192.168.120.243",
"io": 0,
"platformScale": "1",
"soundColumn": "2",
"vidicon": "2"
},
{
"name": "出",
"sn": "34fc9ce5-8b091060",
"ip": "192.168.120.238",
"io": 0,
"platformScale": "1",
"soundColumn": "1",
"vidicon": "2"
}
],
"platformScales": [
{
"sn": "1",
"name": "地磅",
"sample": 20,
"port": "COM2",
"baudRate": 1200,
"byteSize": 8,
"parity": 0,
"stopBits": 0
}
],
"soundColumns": [
{
"sn": "1",
"name": "音柱1",
"server": "http://192.168.120.246:80",
"path": "/v1/speech"
},
{
"sn": "2",
"name": "音柱2",
"server": "http://192.168.120.237:80",
"path": "/v1/speech"
}
],
"vidicons": [
{
"sn": "1",
"name": "摄像头1",
"ip": "192.168.120.245",
"port": 8000,
"username": "admin",
"passwd": "gk147258"
},
{
"sn": "2",
"name": "摄像头2",
"ip": "192.168.120.244",
"port": 8000,
"username": "admin",
"passwd": "gk147258"
}
]
}

View File

@ -1,14 +1,14 @@
#include "application.h" #include "application.h"
#include <windows.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc > 1) if (argc == 2)
{ {
FreeConsole(); zsy::Application::run(argv[1]);
} else
{
zsy::Application::run();
} }
std::this_thread::sleep_for(std::chrono::milliseconds(30000));
zsy::Application::run();
return 0; return 0;
} }

View File

@ -94,11 +94,21 @@ namespace zsy
} }
} }
Application::Application() Application::Application(const std::string &configFile)
: configFile(SysUtil::WORK_DIR + "\\config\\config.json"), : configFile(SysUtil::WORK_DIR + "\\config\\" + configFile),
pidFilePath(SysUtil::WORK_DIR + "\\logs") pidFilePath(SysUtil::WORK_DIR + "\\logs")
{ {
loadConfig(); loadConfig();
auto appProperties = config.get<AppProperties>();
if (appProperties.daemon)
{
FreeConsole();
}
if (appProperties.delay > 0)
{
LOGGER_INFO("等待...");
std::this_thread::sleep_for(std::chrono::milliseconds(appProperties.delay * 1000));
}
threadPool = std::make_shared<ThreadPool>(3); threadPool = std::make_shared<ThreadPool>(3);
eventManager = std::make_shared<EventManager>(threadPool); eventManager = std::make_shared<EventManager>(threadPool);
@ -115,10 +125,15 @@ namespace zsy
} }
void Application::run() void Application::run()
{
run("config.json");
}
void Application::run(const std::string &configFile)
{ {
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
LOGGER_INFO("启动中..."); LOGGER_INFO("启动中...");
Application app; Application app(configFile);
app.writePid(); app.writePid();
LOGGER_INFO("启动完成PID{}", app.pid); LOGGER_INFO("启动完成PID{}", app.pid);

View File

@ -8,6 +8,17 @@
namespace zsy namespace zsy
{ {
struct AppProperties
{
bool daemon{false};
uint32_t delay{0};
};
inline void from_json(const nlohmann::json &j, AppProperties &o)
{
PARSE_JSON(daemon, o.daemon);
PARSE_JSON(delay, o.delay);
}
class Application class Application
{ {
@ -39,10 +50,12 @@ namespace zsy
static std::shared_ptr<DeviceHolder> deviceHolder; static std::shared_ptr<DeviceHolder> deviceHolder;
Application(); Application(const std::string &configFile);
static void run(); static void run();
static void run(const std::string &configFile);
static void stop(); static void stop();
~Application(); ~Application();

View File

@ -51,8 +51,8 @@ namespace zsy
nlohmann::json j; nlohmann::json j;
try try
{ {
// double weight = Application::deviceHolder->getPlatformScale("b11ceeb5-af42d80f")->reading(); double weight = Application::deviceHolder->getPlatformScale("b11ceeb5-af42d80f")->reading();
// j["地磅读数"] = weight; j["地磅读数"] = weight;
// Application::deviceHolder->getSoundColumn( "b11ceeb5-af42d80f")->play("欢迎光临"); // Application::deviceHolder->getSoundColumn( "b11ceeb5-af42d80f")->play("欢迎光临");
// auto reportPassResult = Application::reportSvr->reportPass("苏K85076", "b11ceeb5-af42d80f", ""); // auto reportPassResult = Application::reportSvr->reportPass("苏K85076", "b11ceeb5-af42d80f", "");
} catch (std::exception &e) } catch (std::exception &e)

View File

@ -0,0 +1,145 @@
#include "daily_and_size_sink.h"
namespace zsy
{
DailyAndSizeSink::DailyAndSizeSink(const std::string &filename, uintmax_t maxSize, int32_t maxDays)
: maxSize(maxSize)
, maxDays(maxDays)
{
std::filesystem::path base_path(filename);
auto paths = base_path.parent_path();
basePath = paths.string();
baseFilename = base_path.stem().string();
baseExt = base_path.extension().string();
std::filesystem::create_directories(paths);
currentDate = today();
currentIndex = lastIndex();
currentSize = lastSize();
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
}
void DailyAndSizeSink::rotateFile()
{
auto current_date = today();
if (current_date != currentDate)
{
fileHelper.flush();
fileHelper.close();
std::filesystem::rename(basePath + "\\" + baseFilename + baseExt, basePath + "\\" + baseFilename + "." + currentDate + "." + std::to_string(currentIndex) + baseExt);
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
currentDate = current_date;
currentIndex = 1;
} else
{
if (currentSize >= maxSize)
{
fileHelper.flush();
fileHelper.close();
std::filesystem::rename(basePath + "\\" + baseFilename + baseExt, basePath + "\\" + baseFilename + "." + currentDate + "." + std::to_string(currentIndex) + baseExt);
fileHelper.open(basePath + "\\" + baseFilename + baseExt, false);
currentIndex++;
}
}
}
void DailyAndSizeSink::cleanOldFiles()
{
try
{
if (maxDays <= 0) return;
auto now = std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now());
auto cutoff_time = now - std::chrono::days(maxDays);
// 正则表达式模式baseName.YYYY-MM-DD(.index)?.ext
std::regex file_pattern(baseFilename + R"(\.(\d{4}-\d{2}-\d{2})(\.\d+)?)" + baseExt);
std::filesystem::path paths(basePath);
for (const auto &entry: std::filesystem::directory_iterator(paths))
{
if (entry.is_regular_file())
{
std::string filename = entry.path().filename().string();
std::smatch match;
if (std::regex_match(filename, match, file_pattern))
{
std::string date_str = match[1].str();
std::chrono::sys_days date;
std::istringstream tstr(date_str);
tstr >> std::chrono::parse("%F", date);
if (date < cutoff_time)
{
std::filesystem::remove(entry.path());
}
}
}
}
} catch (const std::exception &e)
{
// 清理失败
}
}
void DailyAndSizeSink::sink_it_(const spdlog::details::log_msg &msg)
{
spdlog::memory_buf_t formatted;
formatter_->format(msg, formatted);
std::string formatted_str(formatted.data(), formatted.size());
rotateFile();
fileHelper.write(formatted);
currentSize = fileHelper.size();
cleanOldFiles();
}
void DailyAndSizeSink::flush_()
{
fileHelper.flush();
}
std::string DailyAndSizeSink::today()
{
auto now = std::chrono::system_clock::now();
auto local_time = std::chrono::zoned_time{std::chrono::current_zone(), now};
return std::format("{:%F}", local_time);
}
uint32_t DailyAndSizeSink::lastIndex()
{
uint32_t index = 0;
std::regex file_pattern(baseFilename + R"(\.\d{4}-\d{2}-\d{2}\.(\d+))" + baseExt);
std::filesystem::path paths(basePath);
for (const auto &entry: std::filesystem::directory_iterator(paths))
{
if (entry.is_regular_file())
{
std::string filename = entry.path().filename().string();
std::smatch match;
if (std::regex_match(filename, match, file_pattern))
{
std::string index_str = match[1].str();
auto index_chp = index_str.data();
int index_{};
std::from_chars(index_chp, index_chp + index_str.size(), index_);
if (index_ > index) index = index_;
}
}
}
return index + 1;
}
uintmax_t DailyAndSizeSink::lastSize()
{
uintmax_t size = 0;
std::filesystem::path filePath(basePath + "\\" + baseFilename + baseExt);
if (std::filesystem::exists(filePath))
{
size = std::filesystem::file_size(filePath);
}
return size;
}
}

View File

@ -0,0 +1,51 @@
#ifndef DAILY_AND_SIZE_SINK_H
#define DAILY_AND_SIZE_SINK_H
#include <spdlog/sinks/base_sink.h>
#include <spdlog/details/file_helper.h>
#include <mutex>
#include <string>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <filesystem>
#include <regex>
namespace zsy
{
class DailyAndSizeSink final : public spdlog::sinks::base_sink<std::mutex>
{
bool init;
std::string basePath;
std::string baseFilename;
std::string baseExt;
uintmax_t maxSize;
int32_t maxDays;
std::string currentDate;
uint32_t currentIndex = 0;
uintmax_t currentSize = 0;
std::string currentFilename;
spdlog::details::file_helper fileHelper;
void rotateFile();
void cleanOldFiles();
std::string today();
uint32_t lastIndex();
uintmax_t lastSize();
public:
// 构造函数:基础文件名、最大文件大小(字节)、最大保留天数
DailyAndSizeSink( const std::string &filename, size_t maxSize, int32_t maxDays);
protected:
void sink_it_(const spdlog::details::log_msg &msg) override;
void flush_() override;
};
}
#endif //DAILY_AND_SIZE_SINK_H

View File

@ -1,7 +1,8 @@
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/daily_file_sink.h> // #include <spdlog/sinks/daily_file_sink.h>
#include "sys_util.h" #include "sys_util.h"
#include "daily_and_size_sink.h"
namespace zsy namespace zsy
{ {
@ -9,7 +10,12 @@ namespace zsy
{ {
static std::shared_ptr<spdlog::logger> logger = [] static std::shared_ptr<spdlog::logger> logger = []
{ {
const auto file_sink = std::make_shared<spdlog::sinks::daily_file_format_sink_mt>(SysUtil::WORK_DIR + "\\logs\\deviceAccessLayer.log", 0, 0); // const auto file_sink = std::make_shared<spdlog::sinks::daily_file_format_sink_mt>(SysUtil::WORK_DIR + "\\logs\\deviceAccessLayer.log", 0, 0);
auto file_sink = std::make_shared<DailyAndSizeSink>(
SysUtil::WORK_DIR + "\\logs\\deviceAccessLayer.log",
100 * 1024 * 1024,
15
);
file_sink->set_level(spdlog::level::info); file_sink->set_level(spdlog::level::info);
file_sink->set_pattern("%Y-%m-%d %H:%M:%S.%e %=7l %=10t %-40s [%-64! %10#]: %v"); file_sink->set_pattern("%Y-%m-%d %H:%M:%S.%e %=7l %=10t %-40s [%-64! %10#]: %v");

View File

@ -89,6 +89,7 @@ namespace zsy
double GenericPlatformScale::reading() double GenericPlatformScale::reading()
{ {
// 02 2B 30 30 32 30 30 30 32 31 42 03
std::shared_lock lock(status_mtx); std::shared_lock lock(status_mtx);
try try
{ {
@ -98,6 +99,24 @@ namespace zsy
LOGGER_INFO("无法称重,地磅状态:{}", status); LOGGER_INFO("无法称重,地磅状态:{}", status);
return 0.0; return 0.0;
} }
int retry_count = 0;
while ((serialPort->status.load() == 3 || serialPort->readStatus.load() == 3) && retry_count < 10)
{
retry_count++;
LOGGER_INFO("无法称重,串口异常,正在重启串口...");
delete serialPort;
serialPort = new SerialPort(config.port, config.baudRate, config.byteSize, config.parity, config.stopBits, new GenericPlatformScaleProcessor());
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
}
if (serialPort->status.load() == 3 || serialPort->readStatus.load() == 3)
{
LOGGER_ERROR("无法称重,串口异常,重试失败");
status = 1;
return 0.0;
}
status = 2; status = 2;
LOGGER_INFO("正在称重..."); LOGGER_INFO("正在称重...");
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));

View File

@ -20,6 +20,10 @@ namespace zsy
}; };
Processor *processor; Processor *processor;
// 0-->不可用1-->已打开2-->已关闭3-->错误
std::atomic<uint8_t> status;
// 0-->不可用1-->正在读取2-->已停止3-->错误
std::atomic<uint8_t> readStatus;
SerialPort( SerialPort(
const std::string &port, const std::string &port,
@ -32,10 +36,7 @@ namespace zsy
private: private:
std::vector<uint8_t> *buffer; std::vector<uint8_t> *buffer;
// 0-->不可用1-->已打开2-->已关闭3-->错误
std::atomic<uint8_t> status;
// 0-->不可用1-->正在读取2-->已停止3-->错误
std::atomic<uint8_t> readStatus;
std::string port; std::string port;
uint32_t baudRate; uint32_t baudRate;
uint8_t byteSize; uint8_t byteSize;

4
start.bat 100644
View File

@ -0,0 +1,4 @@
chcp 65001
d:
cd D:\zsy\deviceAccessLayer
start deviceAccessLayer.exe