2025-12-10 00:01:32 +08:00

204 lines
8.4 KiB
C++

#include "VrConfig.h"
#include <iostream>
#include <vector>
#include <string>
#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()) != "WorkpieceProjectConfig")
{
LOG_ERR("Config file format error: root element is not WorkpieceProjectConfig\n");
return LOAD_CONFIG_INVALID_FORMAT;
}
// 1. 解析 BinocularMark 客户端配置
XMLElement* binocularMarkElement = root->FirstChildElement("BinocularMark");
if (binocularMarkElement)
{
if (binocularMarkElement->Attribute("serverIP"))
configResult.binocularMarkConfig.serverIP = binocularMarkElement->Attribute("serverIP");
binocularMarkElement->QueryIntAttribute("serverPort", &configResult.binocularMarkConfig.serverPort);
binocularMarkElement->QueryIntAttribute("reconnectInterval", &configResult.binocularMarkConfig.reconnectInterval);
binocularMarkElement->QueryIntAttribute("heartbeatInterval", &configResult.binocularMarkConfig.heartbeatInterval);
LOG_INFO("BinocularMark config: IP=%s, Port=%d\n",
configResult.binocularMarkConfig.serverIP.c_str(),
configResult.binocularMarkConfig.serverPort);
}
// 2. 解析 EpicEyeDevice 列表(仅 WorkpiecePositionApp 需要)
XMLElement* epicEyeDevicesElement = root->FirstChildElement("EpicEyeDevices");
if (epicEyeDevicesElement)
{
configResult.epicEyeDeviceList.clear();
XMLElement* deviceElement = epicEyeDevicesElement->FirstChildElement("Device");
while (deviceElement)
{
DeviceInfo device;
if (deviceElement->Attribute("name"))
device.name = deviceElement->Attribute("name");
if (deviceElement->Attribute("ip"))
device.ip = deviceElement->Attribute("ip");
deviceElement->QueryIntAttribute("index", &device.index);
configResult.epicEyeDeviceList.push_back(device);
LOG_INFO("EpicEye Device: name=%s, ip=%s, index=%d\n",
device.name.c_str(), device.ip.c_str(), device.index);
deviceElement = deviceElement->NextSiblingElement("Device");
}
}
// 3. 解析调试参数
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());
}
// 4. 解析串口配置(可选,用于机械臂通信)
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\n",
configResult.serialConfig.portName.c_str(),
configResult.serialConfig.baudRate);
}
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("WorkpieceProjectConfig");
doc.InsertEndChild(root);
// 1. 保存 BinocularMark 客户端配置
XMLElement* binocularMarkElement = doc.NewElement("BinocularMark");
binocularMarkElement->SetAttribute("serverIP", configResult.binocularMarkConfig.serverIP.c_str());
binocularMarkElement->SetAttribute("serverPort", configResult.binocularMarkConfig.serverPort);
binocularMarkElement->SetAttribute("reconnectInterval", configResult.binocularMarkConfig.reconnectInterval);
binocularMarkElement->SetAttribute("heartbeatInterval", configResult.binocularMarkConfig.heartbeatInterval);
root->InsertEndChild(binocularMarkElement);
// 2. 保存 EpicEyeDevice 列表
if (!configResult.epicEyeDeviceList.empty())
{
XMLElement* epicEyeDevicesElement = doc.NewElement("EpicEyeDevices");
for (const auto& device : configResult.epicEyeDeviceList)
{
XMLElement* deviceElement = doc.NewElement("Device");
deviceElement->SetAttribute("name", device.name.c_str());
deviceElement->SetAttribute("ip", device.ip.c_str());
deviceElement->SetAttribute("index", device.index);
epicEyeDevicesElement->InsertEndChild(deviceElement);
}
root->InsertEndChild(epicEyeDevicesElement);
}
// 3. 保存调试参数
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);
// 4. 保存串口配置
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);
// 保存到文件
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;
}
bool IVrConfig::CreateInstance(IVrConfig** ppVrConfig)
{
if (ppVrConfig == nullptr)
{
return false;
}
*ppVrConfig = new CVrConfig();
return true;
}