#include "VrBeltTearingConfig.h" #include "IVrBeltTearingConfig.h" #include #include #include "VrLog.h" #include #include #include #include #include #include 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() == "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.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(); } } } } 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("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.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 xml.writeEndElement(); // BeltTearingConfig xml.writeEndDocument(); file.close(); return true; } void VrBeltTearingConfig::SetConfigChangeNotify(IVrBeltTearingConfigChangeNotify* notify) { m_notify = notify; }