#include "VrBeltTearingConfig.h" #include "VrLog.h" #include "tinyxml2.h" using namespace tinyxml2; namespace { const char* attr(const XMLElement* node, const char* name, const char* fallback = "") { const char* value = node ? node->Attribute(name) : nullptr; return value ? value : fallback; } } VrBeltTearingConfig::VrBeltTearingConfig() : m_notify(nullptr) {} VrBeltTearingConfig::~VrBeltTearingConfig() = default; bool IVrBeltTearingConfig::CreateInstance(IVrBeltTearingConfig** output) { if (!output) return false; *output = new VrBeltTearingConfig(); return true; } BeltTearingConfigResult VrBeltTearingConfig::LoadConfig(const std::string& filePath) { BeltTearingConfigResult result; XMLDocument document; if (document.LoadFile(filePath.c_str()) != XML_SUCCESS) return result; const XMLElement* root = document.FirstChildElement("BeltTearingConfig"); if (!root) return BeltTearingConfigResult(); const XMLElement* servers = root->FirstChildElement("ClientServers"); for (const XMLElement* node = servers ? servers->FirstChildElement("Server") : nullptr; node; node = node->NextSiblingElement("Server")) { ServerInfo server; server.name = attr(node, "name"); server.ip = attr(node, "ip"); server.port = node->IntAttribute("port", 5900); if (server.port <= 0 || server.port > 65535) server.port = 5900; result.servers.push_back(server); } const XMLElement* algorithm = root->FirstChildElement("AlgorithmParams"); const XMLElement* tearing = algorithm ? algorithm->FirstChildElement("BeltTearingParam") : nullptr; if (tearing) { BeltTearingParam& params = result.algorithmParams.beltTearingParam; params.scanXScale = tearing->DoubleAttribute("ScanXScale", params.scanXScale); params.scanYScale = tearing->DoubleAttribute("ScanYScale", params.scanYScale); params.differnceBinTh = tearing->DoubleAttribute("DiffernceBinTh", params.differnceBinTh); params.tearingMinLen = tearing->DoubleAttribute("TearingMinLen", params.tearingMinLen); params.tearingMinWidthY = tearing->DoubleAttribute("TearingMinWidthY", params.tearingMinWidthY); params.tearingMinDepthZ = tearing->DoubleAttribute("TearingMinDepthZ", params.tearingMinDepthZ); params.tearingMinGap = tearing->DoubleAttribute("TearingMinGap", params.tearingMinGap); params.sameGapTh = tearing->DoubleAttribute("SameGapTh", params.sameGapTh); params.gapChkWin = tearing->IntAttribute("GapChkWin", params.gapChkWin); } const XMLElement* monitoring = algorithm ? algorithm->FirstChildElement("MonitoringParam") : nullptr; if (monitoring) { result.algorithmParams.monitoringParam.checkInterval = monitoring->IntAttribute("CheckInterval", result.algorithmParams.monitoringParam.checkInterval); result.algorithmParams.monitoringParam.alertThreshold = monitoring->DoubleAttribute("AlertThreshold", result.algorithmParams.monitoringParam.alertThreshold); } const XMLElement* debug = root->FirstChildElement("DebugParam"); if (debug) { result.debugParam.enableDebug = debug->BoolAttribute("enableDebug", result.debugParam.enableDebug); result.debugParam.saveDebugImage = debug->BoolAttribute("saveDebugImage", result.debugParam.saveDebugImage); result.debugParam.printDetailLog = debug->BoolAttribute("printDetailLog", result.debugParam.printDetailLog); result.debugParam.debugOutputPath = attr(debug, "debugOutputPath"); } const XMLElement* queue = root->FirstChildElement("QueueProcessParam"); if (queue) { result.queueProcessParam.maxQueueSize = queue->IntAttribute("maxQueueSize", result.queueProcessParam.maxQueueSize); result.queueProcessParam.generationInterval = queue->IntAttribute("generationInterval", result.queueProcessParam.generationInterval); result.queueProcessParam.imageLineCount = queue->IntAttribute("imageLineCount", result.queueProcessParam.imageLineCount); } const XMLElement* pointCloud = root->FirstChildElement("PointCloudSendParam"); if (pointCloud) { result.pointCloudSendParam.enabled = pointCloud->BoolAttribute("enabled", result.pointCloudSendParam.enabled); result.pointCloudSendParam.lineStep = pointCloud->IntAttribute("lineStep", result.pointCloudSendParam.lineStep); result.pointCloudSendParam.pointStep = pointCloud->IntAttribute("pointStep", result.pointCloudSendParam.pointStep); } const XMLElement* project = root->FirstChildElement("ProjectType"); if (project && std::string(attr(project, "type")) == "BeltMonitoring") result.projectType = BeltTearingProjectType::BeltMonitoring; const XMLElement* local = root->FirstChildElement("LocalServerConfig"); if (local) { const XMLElement* serverPort = local->FirstChildElement("ServerPort"); const XMLElement* tcpPort = local->FirstChildElement("TcpPort"); const XMLElement* protocol = local->FirstChildElement("ModbusTCPProtocol"); if (serverPort) result.serverPort = serverPort->IntAttribute("port", result.serverPort); if (tcpPort) result.tcpPort = tcpPort->IntAttribute("port", result.tcpPort); if (protocol && std::string(attr(protocol, "type")) == "standard") result.modbusTCPProtocol = ModbusTCPProtocolType::Standard; } const XMLElement* cameras = root->FirstChildElement("Cameras"); for (const XMLElement* node = cameras ? cameras->FirstChildElement("Camera") : nullptr; node; node = node->NextSiblingElement("Camera")) { CameraParam camera; camera.name = attr(node, "name"); camera.cameraIP = attr(node, "ip"); result.cameras.push_back(camera); } const XMLElement* serial = root->FirstChildElement("SerialPort"); if (serial) { result.serialPortParam.portName = attr(serial, "portName", result.serialPortParam.portName.c_str()); result.serialPortParam.baudRate = serial->IntAttribute("baudRate", result.serialPortParam.baudRate); const char* parity = serial->Attribute("parity"); if (parity && parity[0]) result.serialPortParam.parity = parity[0]; result.serialPortParam.dataBits = serial->IntAttribute("dataBits", result.serialPortParam.dataBits); result.serialPortParam.stopBits = serial->IntAttribute("stopBits", result.serialPortParam.stopBits); } return result; } bool VrBeltTearingConfig::SaveConfig(const std::string& filePath, BeltTearingConfigResult& config) { XMLDocument document; document.InsertEndChild(document.NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"")); XMLElement* root = document.NewElement("BeltTearingConfig"); document.InsertEndChild(root); if (!config.servers.empty()) { XMLElement* servers = document.NewElement("ClientServers"); root->InsertEndChild(servers); for (const ServerInfo& server : config.servers) { XMLElement* node = document.NewElement("Server"); node->SetAttribute("name", server.name.c_str()); node->SetAttribute("ip", server.ip.c_str()); node->SetAttribute("port", server.port); servers->InsertEndChild(node); } } XMLElement* algorithm = document.NewElement("AlgorithmParams"); root->InsertEndChild(algorithm); XMLElement* tearing = document.NewElement("BeltTearingParam"); algorithm->InsertEndChild(tearing); const BeltTearingParam& params = config.algorithmParams.beltTearingParam; tearing->SetAttribute("ScanXScale", params.scanXScale); tearing->SetAttribute("ScanYScale", params.scanYScale); tearing->SetAttribute("DiffernceBinTh", params.differnceBinTh); tearing->SetAttribute("TearingMinLen", params.tearingMinLen); tearing->SetAttribute("TearingMinWidthY", params.tearingMinWidthY); tearing->SetAttribute("TearingMinDepthZ", params.tearingMinDepthZ); tearing->SetAttribute("TearingMinGap", params.tearingMinGap); tearing->SetAttribute("SameGapTh", params.sameGapTh); tearing->SetAttribute("GapChkWin", params.gapChkWin); XMLElement* monitoring = document.NewElement("MonitoringParam"); algorithm->InsertEndChild(monitoring); monitoring->SetAttribute("CheckInterval", config.algorithmParams.monitoringParam.checkInterval); monitoring->SetAttribute("AlertThreshold", config.algorithmParams.monitoringParam.alertThreshold); XMLElement* debug = document.NewElement("DebugParam"); root->InsertEndChild(debug); debug->SetAttribute("enableDebug", config.debugParam.enableDebug); debug->SetAttribute("saveDebugImage", config.debugParam.saveDebugImage); debug->SetAttribute("printDetailLog", config.debugParam.printDetailLog); debug->SetAttribute("debugOutputPath", config.debugParam.debugOutputPath.c_str()); XMLElement* queue = document.NewElement("QueueProcessParam"); root->InsertEndChild(queue); queue->SetAttribute("maxQueueSize", config.queueProcessParam.maxQueueSize); queue->SetAttribute("generationInterval", config.queueProcessParam.generationInterval); queue->SetAttribute("imageLineCount", config.queueProcessParam.imageLineCount); XMLElement* pointCloud = document.NewElement("PointCloudSendParam"); root->InsertEndChild(pointCloud); pointCloud->SetAttribute("enabled", config.pointCloudSendParam.enabled ? "true" : "false"); pointCloud->SetAttribute("lineStep", config.pointCloudSendParam.lineStep); pointCloud->SetAttribute("pointStep", config.pointCloudSendParam.pointStep); XMLElement* project = document.NewElement("ProjectType"); root->InsertEndChild(project); project->SetAttribute("type", config.projectType == BeltTearingProjectType::BeltMonitoring ? "BeltMonitoring" : "BeltTearing"); XMLElement* local = document.NewElement("LocalServerConfig"); root->InsertEndChild(local); XMLElement* serverPort = document.NewElement("ServerPort"); serverPort->SetAttribute("port", config.serverPort); local->InsertEndChild(serverPort); XMLElement* tcpPort = document.NewElement("TcpPort"); tcpPort->SetAttribute("port", config.tcpPort); local->InsertEndChild(tcpPort); XMLElement* protocol = document.NewElement("ModbusTCPProtocol"); protocol->SetAttribute("type", config.modbusTCPProtocol == ModbusTCPProtocolType::Standard ? "standard" : "simplified"); local->InsertEndChild(protocol); XMLElement* cameras = document.NewElement("Cameras"); root->InsertEndChild(cameras); for (const CameraParam& camera : config.cameras) { XMLElement* node = document.NewElement("Camera"); node->SetAttribute("name", camera.name.c_str()); node->SetAttribute("ip", camera.cameraIP.c_str()); cameras->InsertEndChild(node); } XMLElement* serial = document.NewElement("SerialPort"); root->InsertEndChild(serial); serial->SetAttribute("portName", config.serialPortParam.portName.c_str()); serial->SetAttribute("baudRate", config.serialPortParam.baudRate); serial->SetAttribute("parity", std::string(1, config.serialPortParam.parity).c_str()); serial->SetAttribute("dataBits", config.serialPortParam.dataBits); serial->SetAttribute("stopBits", config.serialPortParam.stopBits); if (document.SaveFile(filePath.c_str()) != XML_SUCCESS) return false; if (m_notify) m_notify->OnConfigChanged(config); return true; } void VrBeltTearingConfig::SetConfigChangeNotify(IVrBeltTearingConfigChangeNotify* notify) { m_notify = notify; }