#include "dc_param.h" #include "tinyxml2.h" // 中央元数据表(以 saddr 为键,初始化时写入,运行时只读) static std::unordered_map g_param_metadata; void dc_param_metadata_store(const std::string &saddr, const stru_signal_param ¶m) { g_param_metadata[saddr] = param; } bool dc_param_metadata_lookup(const std::string &saddr, stru_signal_param &out_param) { auto it = g_param_metadata.find(saddr); if (it != g_param_metadata.end()) { out_param = it->second; return true; } return false; } // 解析 param.xml,只提取元数据存入 g_param_metadata,不注册信号 static int dc_param_parse_metadata(const std::string &path) { using namespace tinyxml2; XMLDocument doc; if (XML_SUCCESS != doc.LoadFile(path.c_str())) { MY_LOG_E("failed to load param file: %s", path.c_str()); return -1; } XMLElement *root = doc.RootElement(); if (nullptr == root) { MY_LOG_E("param file has no root element"); return -1; } // 解析 Ao 段 XMLElement *ao_elem = root->FirstChildElement("Ao"); if (ao_elem) { for (XMLElement *sig = ao_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); if (nullptr == saddr) { MY_LOG_E("Ao Signal missing saddr, skipping"); continue; } stru_signal_param param; param.min = sig->FloatAttribute("min", 0.0f); param.max = sig->FloatAttribute("max", 0.0f); param.step = sig->FloatAttribute("step", 0.0f); const char *unit = sig->Attribute("unit"); param.unit = unit ? std::string(unit) : std::string(); g_param_metadata[saddr] = param; } } // 解析 Param 段 XMLElement *param_elem = root->FirstChildElement("Param"); if (param_elem) { for (XMLElement *sig = param_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); if (nullptr == saddr) { MY_LOG_E("Param Signal missing saddr, skipping"); continue; } stru_signal_param param; param.min = sig->FloatAttribute("min", 0.0f); param.max = sig->FloatAttribute("max", 0.0f); param.step = sig->FloatAttribute("step", 0.0f); const char *unit = sig->Attribute("unit"); param.unit = unit ? std::string(unit) : std::string(); g_param_metadata[saddr] = param; } } return 0; } // 从 self_param.xml 加载运行时值,返回 saddr → value字符串 的映射 // Ao段: key=saddr, value="value_attr" // Param段: key=saddr + "_" + index, value="value_attr" static std::unordered_map dc_self_param_load(const std::string &path) { using namespace tinyxml2; std::unordered_map values; XMLDocument doc; if (XML_SUCCESS != doc.LoadFile(path.c_str())) return values; // 文件不存在或解析失败,返回空映射 XMLElement *root = doc.RootElement(); if (nullptr == root) return values; // 加载 Ao 段值 XMLElement *ao_elem = root->FirstChildElement("Ao"); if (ao_elem) { for (XMLElement *sig = ao_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); const char *val = sig->Attribute("value"); if (saddr && val) values[saddr] = std::string(val); } } // 加载 Param 段值 XMLElement *param_elem = root->FirstChildElement("Param"); if (param_elem) { for (XMLElement *sig = param_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); if (nullptr == saddr) continue; for (XMLElement *item = sig->FirstChildElement("Item"); item != nullptr; item = item->NextSiblingElement("Item")) { int index = item->IntAttribute("index", -1); const char *val = item->Attribute("value"); if (index >= 1 && val) { std::string key = std::string(saddr) + "_" + std::to_string(index); values[key] = std::string(val); } } } } return values; } // 根据 param.xml 和 self_param.xml 的值生成信号并注册 static int dc_param_register_signals(const std::string ¶m_path, const std::unordered_map &self_values) { using namespace tinyxml2; XMLDocument doc; if (XML_SUCCESS != doc.LoadFile(param_path.c_str())) { MY_LOG_E("failed to reload param file: %s", param_path.c_str()); return -1; } XMLElement *root = doc.RootElement(); if (nullptr == root) { MY_LOG_E("param file has no root element"); return -1; } // 注册 Ao 段信号 XMLElement *ao_elem = root->FirstChildElement("Ao"); if (ao_elem) { for (XMLElement *sig = ao_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); const char *desc = sig->Attribute("desc"); const char *type_str = sig->Attribute("type"); if (nullptr == saddr || nullptr == desc || nullptr == type_str) { MY_LOG_E("Ao Signal missing required attributes, skipping"); continue; } uint8_t data_type = dc_get_data_type_id_by_str(type_str); if (0 == data_type) { MY_LOG_E("unknown data type %s for saddr %s", type_str, saddr); continue; } // 默认值始终从 param.xml 读取 const char *default_val = sig->Attribute("default"); // 运行时值:优先使用 self_param.xml 中的值,否则使用 param.xml 的 value 属性 const char *val_attr = sig->Attribute("value"); std::string run_val; auto it = self_values.find(std::string(saddr)); if (it != self_values.end()) run_val = it->second; else if (val_attr && strlen(val_attr) > 0) run_val = std::string(val_attr); else if (default_val && strlen(default_val) > 0) run_val = std::string(default_val); void *p_data = dc_create_data_ptr_by_type(data_type); if (p_data) { if (!run_val.empty()) dc_set_signal_val_from_str(p_data, data_type, run_val); } void *p_default_data = dc_create_data_ptr_by_type(data_type); if (p_default_data) { if (default_val && strlen(default_val) > 0) dc_set_signal_val_from_str(p_default_data, data_type, std::string(default_val)); } if (p_data && p_default_data) { dc_signal_ao(saddr, desc, data_type, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_data, p_default_data, nullptr); } } } // 注册 Param 段信号 XMLElement *param_elem = root->FirstChildElement("Param"); if (param_elem) { for (XMLElement *sig = param_elem->FirstChildElement("Signal"); sig != nullptr; sig = sig->NextSiblingElement("Signal")) { const char *saddr = sig->Attribute("saddr"); const char *desc = sig->Attribute("desc"); const char *type_str = sig->Attribute("type"); if (nullptr == saddr || nullptr == desc || nullptr == type_str) { MY_LOG_E("Param Signal missing required attributes, skipping"); continue; } uint8_t data_type = dc_get_data_type_id_by_str(type_str); if (0 == data_type) { MY_LOG_E("unknown data type %s for saddr %s", type_str, saddr); continue; } int num = sig->IntAttribute("num", -1); if (num < 1) continue; std::vector vec_p_data; std::vector vec_p_default_data; for (XMLElement *item = sig->FirstChildElement("Item"); item != nullptr; item = item->NextSiblingElement("Item")) { int index = item->IntAttribute("index", -1); const char *default_val = item->Attribute("default"); const char *val_attr = item->Attribute("value"); // 运行时值:优先使用 self_param.xml 中的值 std::string key = std::string(saddr) + "_" + std::to_string(index); std::string run_val; auto it = self_values.find(key); if (it != self_values.end()) run_val = it->second; else if (val_attr && strlen(val_attr) > 0) run_val = std::string(val_attr); else if (default_val && strlen(default_val) > 0) run_val = std::string(default_val); void *p_data = dc_create_data_ptr_by_type(data_type); if (p_data) { if (!run_val.empty()) dc_set_signal_val_from_str(p_data, data_type, run_val); vec_p_data.push_back(p_data); } void *p_default_data = dc_create_data_ptr_by_type(data_type); if (p_default_data) { if (default_val && strlen(default_val) > 0) dc_set_signal_val_from_str(p_default_data, data_type, std::string(default_val)); vec_p_default_data.push_back(p_default_data); } } if (!vec_p_data.empty() && vec_p_data.size() == vec_p_default_data.size()) { dc_signal_param(saddr, desc, data_type, SIGNAL_CTRL_TYPE::SBO_NORMAL, vec_p_data.data(), vec_p_default_data.data(), num, nullptr); } } } // 首次注册后标记变更,触发 self_param.xml 生成 dc_set_param_cfg_change(true); return 0; } int dc_param_cfg_parse(const std::string &path) { // 1. 从 param.xml 提取元数据到 g_param_metadata if (0 != dc_param_parse_metadata(path)) { MY_LOG_E("dc_param_parse_metadata failed, path:%s", path.c_str()); return -1; } // 2. 构造 self_param.xml 路径 std::string self_path = path; size_t pos = self_path.rfind("param.xml"); if (pos != std::string::npos) self_path.replace(pos, 9, "self_param.xml"); else self_path = path.substr(0, path.rfind('/') + 1) + "self_param.xml"; // 3. 尝试加载 self_param.xml 中的运行时值 std::unordered_map self_values = dc_self_param_load(self_path); if (!self_values.empty()) MY_LOG_I("loaded %zu saved values from self_param.xml", self_values.size()); else MY_LOG_I("no self_param.xml found, using default values from param.xml"); // 4. 用合并后的值注册所有信号 if (0 != dc_param_register_signals(path, self_values)) { MY_LOG_E("dc_param_register_signals failed"); return -1; } return 0; }