GrabBag/App/BeltTearing/BeltTearingConfig/Src/VrBeltTearingConfig.cpp

381 lines
17 KiB
C++
Raw Normal View History

#include "VrBeltTearingConfig.h"
#include "IVrBeltTearingConfig.h"
#include <algorithm>
#include <sstream>
2025-08-31 21:08:28 +08:00
#include "VrLog.h"
#include <QFile>
#include <QTextStream>
#include <QString>
#include <QTextCodec>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
VrBeltTearingConfig::VrBeltTearingConfig()
: m_notify(nullptr)
{
}
VrBeltTearingConfig::~VrBeltTearingConfig()
{
}
// Also add the static CreateInstance method to the interface class
bool IVrBeltTearingConfig::CreateInstance(IVrBeltTearingConfig** ppVrConfig)
{
if (!ppVrConfig) {
return false;
}
*ppVrConfig = new VrBeltTearingConfig();
return true;
}
BeltTearingConfigResult VrBeltTearingConfig::LoadConfig(const std::string& filePath)
{
BeltTearingConfigResult result;
2025-08-31 21:08:28 +08:00
// 使用QString处理可能包含中文的路径
QString qFilePath = QString::fromStdString(filePath);
QFile file(qFilePath);
// 检查文件是否存在并可读
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LOG_DEBUG("Failed to open file: %s\n", filePath.c_str());
return result;
}
// 使用QXmlStreamReader解析XML内容
QXmlStreamReader xml(&file);
// 读取到根元素
if (xml.readNextStartElement()) {
if (xml.name() != "BeltTearingConfig") {
xml.raiseError(QObject::tr("Not a BeltTearingConfig file"));
}
} else {
xml.raiseError(QObject::tr("Failed to read root element"));
}
// 解析XML内容
while (!xml.atEnd() && !xml.hasError()) {
xml.readNext();
// 解析服务器配置
2025-09-10 00:31:27 +08:00
if (xml.isStartElement() && xml.name() == "ClientServers") {
while (xml.readNextStartElement()) {
if (xml.name() == "Server") {
ServerInfo server;
2025-09-10 00:31:27 +08:00
server.name = xml.attributes().value("name").toString().toStdString(); server.ip = xml.attributes().value("ip").toString().toStdString();
server.port = xml.attributes().value("port").toInt();
result.servers.push_back(server);
xml.skipCurrentElement();
}
}
}
// 解析算法参数
else if (xml.isStartElement() && xml.name() == "AlgorithmParams") {
while (xml.readNextStartElement()) {
// 皮带撕裂参数
if (xml.name() == "BeltTearingParam") {
// 读取简化的SDK兼容参数
result.algorithmParams.beltTearingParam.scanXScale =
xml.attributes().value("ScanXScale").toDouble();
result.algorithmParams.beltTearingParam.scanYScale =
xml.attributes().value("ScanYScale").toDouble();
result.algorithmParams.beltTearingParam.differnceBinTh =
xml.attributes().value("DiffernceBinTh").toDouble();
result.algorithmParams.beltTearingParam.tearingMinLen =
xml.attributes().value("TearingMinLen").toDouble();
result.algorithmParams.beltTearingParam.tearingMinGap =
xml.attributes().value("TearingMinGap").toDouble();
result.algorithmParams.beltTearingParam.sameGapTh =
xml.attributes().value("SameGapTh").toDouble();
result.algorithmParams.beltTearingParam.gapChkWin =
xml.attributes().value("GapChkWin").toInt();
// 设置默认值(如果参数不存在)
if (result.algorithmParams.beltTearingParam.scanXScale == 0.0) {
result.algorithmParams.beltTearingParam.scanXScale = 1.0;
}
if (result.algorithmParams.beltTearingParam.scanYScale == 0.0) {
result.algorithmParams.beltTearingParam.scanYScale = 1.0;
}
if (result.algorithmParams.beltTearingParam.differnceBinTh == 0.0) {
result.algorithmParams.beltTearingParam.differnceBinTh = 1.0;
}
if (result.algorithmParams.beltTearingParam.tearingMinLen == 0.0) {
result.algorithmParams.beltTearingParam.tearingMinLen = 5.0;
}
if (result.algorithmParams.beltTearingParam.tearingMinGap == 0.0) {
result.algorithmParams.beltTearingParam.tearingMinGap = 2.0;
}
if (result.algorithmParams.beltTearingParam.sameGapTh == 0.0) {
result.algorithmParams.beltTearingParam.sameGapTh = 2.0;
}
if (result.algorithmParams.beltTearingParam.gapChkWin == 0) {
result.algorithmParams.beltTearingParam.gapChkWin = 5;
}
xml.skipCurrentElement();
}
// 监控参数
else if (xml.name() == "MonitoringParam") {
result.algorithmParams.monitoringParam.checkInterval =
xml.attributes().value("CheckInterval").toInt();
result.algorithmParams.monitoringParam.alertThreshold =
xml.attributes().value("AlertThreshold").toDouble();
// 向后兼容:忽略不再使用的参数
// maxHistorySize 已移除,不再读取
xml.skipCurrentElement();
}
// 跳过不再使用的图像处理参数
else if (xml.name() == "ImageProcessingParam") {
// 向后兼容:跳过图像处理参数,不再使用
xml.skipCurrentElement();
}
else {
xml.skipCurrentElement();
}
}
}
// 解析调试参数
else if (xml.isStartElement() && xml.name() == "DebugParam") {
result.debugParam.enableDebug = xml.attributes().value("enableDebug").toInt();
result.debugParam.saveDebugImage = xml.attributes().value("saveDebugImage").toInt();
result.debugParam.printDetailLog = xml.attributes().value("printDetailLog").toInt();
result.debugParam.debugOutputPath = xml.attributes().value("debugOutputPath").toString().toStdString();
xml.skipCurrentElement();
}
// 解析队列处理参数
else if (xml.isStartElement() && xml.name() == "QueueProcessParam") {
int maxQueueSize = xml.attributes().value("maxQueueSize").toInt();
int generationInterval = xml.attributes().value("generationInterval").toInt();
// 设置默认值如果参数不存在或为0
result.queueProcessParam.maxQueueSize = (maxQueueSize > 0) ? maxQueueSize : 300;
result.queueProcessParam.generationInterval = (generationInterval > 0) ? generationInterval : 100;
xml.skipCurrentElement();
}
// 解析项目类型
else if (xml.isStartElement() && xml.name() == "ProjectType") {
QString typeStr = xml.attributes().value("type").toString();
if (typeStr == "BeltMonitoring") {
result.projectType = BeltTearingProjectType::BeltMonitoring;
} else {
result.projectType = BeltTearingProjectType::BeltTearing;
}
xml.skipCurrentElement();
}
2025-09-10 00:31:27 +08:00
// 解析服务端配置
else if (xml.isStartElement() && xml.name() == "LocalServerConfig") {
while (xml.readNextStartElement()) {
if (xml.name() == "ServerPort") {
result.serverPort = xml.attributes().value("port").toInt();
xml.skipCurrentElement();
} else if (xml.name() == "TcpPort") {
result.tcpPort = xml.attributes().value("port").toInt();
if (result.tcpPort == 0) {
result.tcpPort = 5901; // 默认值
}
xml.skipCurrentElement();
} else if (xml.name() == "ModbusTCPProtocol") {
// 解析ModbusTCP协议类型默认为简化协议
QString protocolStr = xml.attributes().value("type").toString().toLower();
if (protocolStr == "standard") {
result.modbusTCPProtocol = ModbusTCPProtocolType::Standard;
} else {
result.modbusTCPProtocol = ModbusTCPProtocolType::Simplified; // 默认简化协议
}
xml.skipCurrentElement();
} else {
xml.skipCurrentElement();
2025-09-10 00:31:27 +08:00
}
}
}
// 解析相机配置
else if (xml.isStartElement() && xml.name() == "Cameras") {
while (xml.readNextStartElement()) {
if (xml.name() == "Camera") {
CameraParam camera;
camera.name = xml.attributes().value("name").toString().toStdString();
camera.cameraIP = xml.attributes().value("ip").toString().toStdString();
result.cameras.push_back(camera);
xml.skipCurrentElement();
}
}
}
2025-11-26 22:44:38 +08:00
// 解析串口配置(用于 Modbus RTU
else if (xml.isStartElement() && xml.name() == "SerialPort") {
QString portName = xml.attributes().value("portName").toString();
int baudRate = xml.attributes().value("baudRate").toInt();
QString parity = xml.attributes().value("parity").toString();
int dataBits = xml.attributes().value("dataBits").toInt();
int stopBits = xml.attributes().value("stopBits").toInt();
// 如果配置文件中有串口配置,则使用配置值
if (!portName.isEmpty()) {
result.serialPortParam.portName = portName.toStdString();
}
if (baudRate > 0) {
result.serialPortParam.baudRate = baudRate;
}
if (!parity.isEmpty() && parity.length() > 0) {
result.serialPortParam.parity = parity.at(0).toLatin1();
}
if (dataBits > 0) {
result.serialPortParam.dataBits = dataBits;
}
if (stopBits > 0) {
result.serialPortParam.stopBits = stopBits;
}
xml.skipCurrentElement();
}
}
file.close();
// 检查解析错误
if (xml.hasError()) {
LOG_ERROR("XML parsing error: %s\n", xml.errorString().toStdString().c_str());
return BeltTearingConfigResult(); // 返回空结果
}
return result;
}
bool VrBeltTearingConfig::SaveConfig(const std::string& filePath, BeltTearingConfigResult& configResult)
{
// 使用QString处理可能包含中文的路径
QString qFilePath = QString::fromStdString(filePath);
QFile file(qFilePath);
// 打开文件进行写入
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
LOG_DEBUG("Failed to open file for writing: %s\n", filePath.c_str());
return false;
}
// 使用QXmlStreamWriter写入XML内容
QXmlStreamWriter xml(&file);
xml.setAutoFormatting(true);
xml.setCodec("UTF-8"); // Explicitly set UTF-8 encoding to handle Chinese characters correctly
xml.writeStartDocument();
// 设置编码为UTF-8以正确处理中文
xml.writeStartElement("BeltTearingConfig");
// 保存服务器配置
if (!configResult.servers.empty()) {
2025-09-10 00:31:27 +08:00
xml.writeStartElement("ClientServers");
for (const auto& server : configResult.servers) {
xml.writeStartElement("Server");
xml.writeAttribute("name", QString::fromStdString(server.name));
xml.writeAttribute("ip", QString::fromStdString(server.ip));
xml.writeAttribute("port", QString::number(server.port));
xml.writeEndElement(); // Server
}
2025-09-10 00:31:27 +08:00
xml.writeEndElement(); // ClientServers
}
// 保存算法参数
xml.writeStartElement("AlgorithmParams");
// 皮带撕裂参数 - 简化版本
xml.writeStartElement("BeltTearingParam");
xml.writeAttribute("ScanXScale", QString::number(configResult.algorithmParams.beltTearingParam.scanXScale));
xml.writeAttribute("ScanYScale", QString::number(configResult.algorithmParams.beltTearingParam.scanYScale));
xml.writeAttribute("DiffernceBinTh", QString::number(configResult.algorithmParams.beltTearingParam.differnceBinTh));
xml.writeAttribute("TearingMinLen", QString::number(configResult.algorithmParams.beltTearingParam.tearingMinLen));
xml.writeAttribute("TearingMinGap", QString::number(configResult.algorithmParams.beltTearingParam.tearingMinGap));
xml.writeAttribute("SameGapTh", QString::number(configResult.algorithmParams.beltTearingParam.sameGapTh));
xml.writeAttribute("GapChkWin", QString::number(configResult.algorithmParams.beltTearingParam.gapChkWin));
xml.writeEndElement(); // BeltTearingParam
// 监控参数
xml.writeStartElement("MonitoringParam");
xml.writeAttribute("CheckInterval", QString::number(configResult.algorithmParams.monitoringParam.checkInterval));
xml.writeAttribute("AlertThreshold", QString::number(configResult.algorithmParams.monitoringParam.alertThreshold));
xml.writeEndElement(); // MonitoringParam
xml.writeEndElement(); // AlgorithmParams
// 保存调试参数
xml.writeStartElement("DebugParam");
xml.writeAttribute("enableDebug", QString::number(configResult.debugParam.enableDebug));
xml.writeAttribute("saveDebugImage", QString::number(configResult.debugParam.saveDebugImage));
xml.writeAttribute("printDetailLog", QString::number(configResult.debugParam.printDetailLog));
xml.writeAttribute("debugOutputPath", QString::fromStdString(configResult.debugParam.debugOutputPath));
xml.writeEndElement(); // DebugParam
// 保存队列处理参数
xml.writeStartElement("QueueProcessParam");
xml.writeAttribute("maxQueueSize", QString::number(configResult.queueProcessParam.maxQueueSize));
xml.writeAttribute("generationInterval", QString::number(configResult.queueProcessParam.generationInterval));
xml.writeEndElement(); // QueueProcessParam
// 保存项目类型
xml.writeStartElement("ProjectType");
QString typeStr = (configResult.projectType == BeltTearingProjectType::BeltMonitoring) ? "BeltMonitoring" : "BeltTearing";
xml.writeAttribute("type", typeStr);
xml.writeEndElement(); // ProjectType
2025-09-10 00:31:27 +08:00
// 保存服务端配置
xml.writeStartElement("LocalServerConfig");
xml.writeStartElement("ServerPort");
xml.writeAttribute("port", QString::number(configResult.serverPort));
xml.writeEndElement(); // ServerPort
xml.writeStartElement("TcpPort");
xml.writeAttribute("port", QString::number(configResult.tcpPort));
xml.writeEndElement(); // TcpPort
// 保存ModbusTCP协议类型
xml.writeStartElement("ModbusTCPProtocol");
QString protocolTypeStr = (configResult.modbusTCPProtocol == ModbusTCPProtocolType::Standard) ? "standard" : "simplified";
xml.writeAttribute("type", protocolTypeStr);
xml.writeEndElement(); // ModbusTCPProtocol
2025-09-10 00:31:27 +08:00
xml.writeEndElement(); // LocalServerConfig
// 保存相机配置
xml.writeStartElement("Cameras");
for (const auto& camera : configResult.cameras) {
xml.writeStartElement("Camera");
xml.writeAttribute("name", QString::fromStdString(camera.name));
xml.writeAttribute("ip", QString::fromStdString(camera.cameraIP));
xml.writeEndElement(); // Camera
}
xml.writeEndElement(); // Cameras
2025-11-26 22:44:38 +08:00
// 保存串口配置(用于 Modbus RTU
xml.writeStartElement("SerialPort");
xml.writeAttribute("portName", QString::fromStdString(configResult.serialPortParam.portName));
xml.writeAttribute("baudRate", QString::number(configResult.serialPortParam.baudRate));
xml.writeAttribute("parity", QString(QChar(configResult.serialPortParam.parity)));
xml.writeAttribute("dataBits", QString::number(configResult.serialPortParam.dataBits));
xml.writeAttribute("stopBits", QString::number(configResult.serialPortParam.stopBits));
xml.writeEndElement(); // SerialPort
xml.writeEndElement(); // BeltTearingConfig
xml.writeEndDocument();
2025-08-31 21:08:28 +08:00
file.close();
// 通知配置改变
if (m_notify) {
m_notify->OnConfigChanged(configResult);
}
2025-08-31 21:08:28 +08:00
return true;
}
void VrBeltTearingConfig::SetConfigChangeNotify(IVrBeltTearingConfigChangeNotify* notify)
{
m_notify = notify;
}