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

381 lines
17 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "VrBeltTearingConfig.h"
#include "IVrBeltTearingConfig.h"
#include <algorithm>
#include <sstream>
#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;
// 使用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();
// 解析服务器配置
if (xml.isStartElement() && xml.name() == "ClientServers") {
while (xml.readNextStartElement()) {
if (xml.name() == "Server") {
ServerInfo server;
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();
}
// 解析服务端配置
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();
}
}
}
// 解析相机配置
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();
}
}
}
// 解析串口配置(用于 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()) {
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
}
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
// 保存服务端配置
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
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
// 保存串口配置(用于 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();
file.close();
// 通知配置改变
if (m_notify) {
m_notify->OnConfigChanged(configResult);
}
return true;
}
void VrBeltTearingConfig::SetConfigChangeNotify(IVrBeltTearingConfigChangeNotify* notify)
{
m_notify = notify;
}