#include "VrConfig.h" #include #include #include #include "VrLog.h" using namespace tinyxml2; CVrConfig::CVrConfig() : m_pNotify(nullptr) { // 构造函数 } CVrConfig::~CVrConfig() { // 析构函数 } int CVrConfig::LoadConfig(const std::string& filePath, ConfigResult& configResult) { // 使用tinyxml2库加载XML文件 XMLDocument doc; XMLError err = doc.LoadFile(filePath.c_str()); if (err != XML_SUCCESS) { LOG_ERR("Failed to open config file: %s\n", filePath.c_str()); return LOAD_CONFIG_FILE_NOT_FOUND; } // 获取根元素 XMLElement* root = doc.RootElement(); if (!root || std::string(root->Name()) != "BagThreadPositionConfig") { LOG_ERR("Config file format error: root element is not BagThreadPositionConfig\n"); return LOAD_CONFIG_INVALID_FORMAT; } // 1. 解析相机设备列表 XMLElement* camerasElement = root->FirstChildElement("Cameras"); if (camerasElement) { configResult.cameraList.clear(); XMLElement* cameraElement = camerasElement->FirstChildElement("Camera"); while (cameraElement) { DeviceInfo camera; if (cameraElement->Attribute("name")) camera.name = cameraElement->Attribute("name"); if (cameraElement->Attribute("ip")) camera.ip = cameraElement->Attribute("ip"); cameraElement->QueryIntAttribute("index", &camera.index); configResult.cameraList.push_back(camera); LOG_INFO("Camera: name=%s, ip=%s, index=%d\n", camera.name.c_str(), camera.ip.c_str(), camera.index); cameraElement = cameraElement->NextSiblingElement("Camera"); } } // 2. 解析调试参数 XMLElement* debugElement = root->FirstChildElement("Debug"); if (debugElement) { debugElement->QueryBoolAttribute("enableDebug", &configResult.debugParam.enableDebug); debugElement->QueryBoolAttribute("saveDebugImage", &configResult.debugParam.saveDebugImage); debugElement->QueryBoolAttribute("savePointCloud", &configResult.debugParam.savePointCloud); debugElement->QueryBoolAttribute("printDetailLog", &configResult.debugParam.printDetailLog); if (debugElement->Attribute("debugOutputPath")) configResult.debugParam.debugOutputPath = debugElement->Attribute("debugOutputPath"); LOG_INFO("Debug config: enableDebug=%d, saveDebugImage=%d, savePointCloud=%d, debugOutputPath=%s\n", configResult.debugParam.enableDebug, configResult.debugParam.saveDebugImage, configResult.debugParam.savePointCloud, configResult.debugParam.debugOutputPath.c_str()); } // 3. 解析串口配置 XMLElement* serialElement = root->FirstChildElement("Serial"); if (serialElement) { if (serialElement->Attribute("portName")) configResult.serialConfig.portName = serialElement->Attribute("portName"); serialElement->QueryIntAttribute("baudRate", &configResult.serialConfig.baudRate); serialElement->QueryIntAttribute("dataBits", &configResult.serialConfig.dataBits); serialElement->QueryIntAttribute("stopBits", &configResult.serialConfig.stopBits); serialElement->QueryIntAttribute("parity", &configResult.serialConfig.parity); serialElement->QueryIntAttribute("flowControl", &configResult.serialConfig.flowControl); serialElement->QueryBoolAttribute("enabled", &configResult.serialConfig.enabled); LOG_INFO("Serial config: port=%s, baudRate=%d, enabled=%d\n", configResult.serialConfig.portName.c_str(), configResult.serialConfig.baudRate, configResult.serialConfig.enabled); } // 4. 解析TCP端口 XMLElement* tcpElement = root->FirstChildElement("TCP"); if (tcpElement) { int port = 5020; tcpElement->QueryIntAttribute("port", &port); configResult.tcpPort = static_cast(port); LOG_INFO("TCP port: %d\n", configResult.tcpPort); } LOG_INFO("Config loaded successfully from: %s\n", filePath.c_str()); return LOAD_CONFIG_SUCCESS; } bool CVrConfig::SaveConfig(const std::string& filePath, ConfigResult& configResult) { XMLDocument doc; // 创建 XML 声明 XMLDeclaration* declaration = doc.NewDeclaration(); doc.InsertFirstChild(declaration); // 创建根元素 XMLElement* root = doc.NewElement("BagThreadPositionConfig"); doc.InsertEndChild(root); // 1. 保存相机设备列表 if (!configResult.cameraList.empty()) { XMLElement* camerasElement = doc.NewElement("Cameras"); for (const auto& camera : configResult.cameraList) { XMLElement* cameraElement = doc.NewElement("Camera"); cameraElement->SetAttribute("name", camera.name.c_str()); cameraElement->SetAttribute("ip", camera.ip.c_str()); cameraElement->SetAttribute("index", camera.index); camerasElement->InsertEndChild(cameraElement); } root->InsertEndChild(camerasElement); } // 2. 保存调试参数 XMLElement* debugElement = doc.NewElement("Debug"); debugElement->SetAttribute("enableDebug", configResult.debugParam.enableDebug); debugElement->SetAttribute("saveDebugImage", configResult.debugParam.saveDebugImage); debugElement->SetAttribute("savePointCloud", configResult.debugParam.savePointCloud); debugElement->SetAttribute("printDetailLog", configResult.debugParam.printDetailLog); debugElement->SetAttribute("debugOutputPath", configResult.debugParam.debugOutputPath.c_str()); root->InsertEndChild(debugElement); // 3. 保存串口配置 XMLElement* serialElement = doc.NewElement("Serial"); serialElement->SetAttribute("portName", configResult.serialConfig.portName.c_str()); serialElement->SetAttribute("baudRate", configResult.serialConfig.baudRate); serialElement->SetAttribute("dataBits", configResult.serialConfig.dataBits); serialElement->SetAttribute("stopBits", configResult.serialConfig.stopBits); serialElement->SetAttribute("parity", configResult.serialConfig.parity); serialElement->SetAttribute("flowControl", configResult.serialConfig.flowControl); serialElement->SetAttribute("enabled", configResult.serialConfig.enabled); root->InsertEndChild(serialElement); // 4. 保存TCP端口 XMLElement* tcpElement = doc.NewElement("TCP"); tcpElement->SetAttribute("port", configResult.tcpPort); root->InsertEndChild(tcpElement); // 保存到文件 XMLError err = doc.SaveFile(filePath.c_str()); if (err != XML_SUCCESS) { LOG_ERR("Failed to save config file: %s\n", filePath.c_str()); return false; } LOG_INFO("Config saved successfully to: %s\n", filePath.c_str()); return true; } // 设置配置改变通知回调 void CVrConfig::SetConfigChangeNotify(IVrConfigChangeNotify* notify) { m_pNotify = notify; } /** * @brief 创建实例 * @return 实例 */ bool IVrConfig::CreateInstance(IVrConfig** ppVrConfig) { *ppVrConfig = new CVrConfig() ; return *ppVrConfig != nullptr; }