diff --git a/src/protocol/libmms_s/src/mms_s_value.cpp b/src/protocol/libmms_s/src/mms_s_value.cpp index b1318ef..bfaa2dd 100644 --- a/src/protocol/libmms_s/src/mms_s_value.cpp +++ b/src/protocol/libmms_s/src/mms_s_value.cpp @@ -477,7 +477,7 @@ LOCAL void mms_s_da_values_init(stru_icd &icd, std::string da_name, stru_all_DA return; } - if(NULL != g_iec61850s_value_init_cb_map[p_all_da->bType]) + if(NULL != g_iec61850s_value_init_cb_map[p_all_da->bType] && !p_all_da->val.empty()) { g_iec61850s_value_init_cb_map[p_all_da->bType](p_all_da->DA, p_all_da->val); } diff --git a/src/system/RTU/src/main.cpp b/src/system/RTU/src/main.cpp index 621859f..200d4ea 100644 --- a/src/system/RTU/src/main.cpp +++ b/src/system/RTU/src/main.cpp @@ -53,6 +53,7 @@ int main(void) MY_LOG_E("app_cfg_parse failed !"); return -1; } + if(0 != app_sys_init()) { diff --git a/src/system/libdatacenter/src/dc_param.cpp b/src/system/libdatacenter/src/dc_param.cpp index 98c1a74..c733bb2 100644 --- a/src/system/libdatacenter/src/dc_param.cpp +++ b/src/system/libdatacenter/src/dc_param.cpp @@ -20,7 +20,8 @@ bool dc_param_metadata_lookup(const std::string &saddr, stru_signal_param &out_p return false; } -int dc_param_cfg_parse(const std::string &path) +// 解析 param.xml,只提取元数据存入 g_param_metadata,不注册信号 +static int dc_param_parse_metadata(const std::string &path) { using namespace tinyxml2; @@ -38,7 +39,136 @@ int dc_param_cfg_parse(const std::string &path) return -1; } - // 解析 Ao 段:单值参数(一份值 + 一份缺省值) + // 解析 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) { @@ -61,22 +191,25 @@ int dc_param_cfg_parse(const std::string &path) continue; } - float min = sig->FloatAttribute("min", 0.0f); - float max = sig->FloatAttribute("max", 0.0f); - float step = sig->FloatAttribute("step", 0.0f); - const char *unit = sig->Attribute("unit"); - - // Ao 段:从 Signal 属性读取单值 - const char *val = sig->Attribute("value"); + // 默认值始终从 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 (val && strlen(val) > 0) - dc_set_signal_val_from_str(p_data, data_type, std::string(val)); - else if (default_val && strlen(default_val) > 0) - dc_set_signal_val_from_str(p_data, data_type, std::string(default_val)); + 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); @@ -88,14 +221,6 @@ int dc_param_cfg_parse(const std::string &path) if (p_data && p_default_data) { - stru_signal_param param; - param.min = min; - param.max = max; - param.step = step; - param.unit = unit ? std::string(unit) : std::string(); - - // 先存入中央元数据表,再注册信号 - dc_param_metadata_store(saddr, param); dc_signal_ao(saddr, desc, data_type, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_data, p_default_data, nullptr); @@ -103,7 +228,7 @@ int dc_param_cfg_parse(const std::string &path) } } - // 解析 Param 段:多值参数(多份值 + 多份缺省值) + // 注册 Param 段信号 XMLElement *param_elem = root->FirstChildElement("Param"); if (param_elem) { @@ -126,58 +251,49 @@ int dc_param_cfg_parse(const std::string &path) continue; } - float min = sig->FloatAttribute("min", 0.0f); - float max = sig->FloatAttribute("max", 0.0f); - float step = sig->FloatAttribute("step", 0.0f); - const char *unit = sig->Attribute("unit"); + int num = sig->IntAttribute("num", -1); + if (num < 1) continue; std::vector vec_p_data; std::vector vec_p_default_data; - int num = sig->IntAttribute("num", -1); - if (num >= 1) + for (XMLElement *item = sig->FirstChildElement("Item"); item != nullptr; + item = item->NextSiblingElement("Item")) { - 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) { - const char *val = item->Attribute("value"); - const char *default_val = item->Attribute("default"); - - void *p_data = dc_create_data_ptr_by_type(data_type); - if (p_data) - { - if (val && strlen(val) > 0) - dc_set_signal_val_from_str(p_data, data_type, std::string(val)); - else if (default_val && strlen(default_val) > 0) - dc_set_signal_val_from_str(p_data, data_type, std::string(default_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 (!run_val.empty()) + dc_set_signal_val_from_str(p_data, data_type, run_val); + vec_p_data.push_back(p_data); } - } - else - { - continue; + 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()) + if (!vec_p_data.empty() && vec_p_data.size() == vec_p_default_data.size()) { - stru_signal_param param; - param.min = min; - param.max = max; - param.step = step; - param.unit = unit ? std::string(unit) : std::string(); - - // 先存入中央元数据表,再注册信号 - dc_param_metadata_store(saddr, param); dc_signal_param(saddr, desc, data_type, SIGNAL_CTRL_TYPE::SBO_NORMAL, vec_p_data.data(), vec_p_default_data.data(), num, nullptr); @@ -185,5 +301,42 @@ int dc_param_cfg_parse(const std::string &path) } } + // 首次注册后标记变更,触发 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; } diff --git a/src/system/libdatacenter/src/dc_signal.cpp b/src/system/libdatacenter/src/dc_signal.cpp index 0ca7f20..f4b2e65 100644 --- a/src/system/libdatacenter/src/dc_signal.cpp +++ b/src/system/libdatacenter/src/dc_signal.cpp @@ -2177,14 +2177,20 @@ void dc_param_cfg_check(const std::string &path) root->InsertEndChild(ao_elem); root->InsertEndChild(param_elem); - if (XML_SUCCESS == doc.SaveFile(path.c_str())) + // 保存到 self_param.xml,不覆盖参数模板 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"); + + if (XML_SUCCESS == doc.SaveFile(self_path.c_str())) { dc_set_param_cfg_change(false); - MY_LOG_I("param config file saved to %s", path.c_str()); + MY_LOG_I("param runtime saved to %s", self_path.c_str()); } else { - MY_LOG_E("failed to save param config file to %s", path.c_str()); + MY_LOG_E("failed to save param runtime to %s", self_path.c_str()); } } diff --git a/src/system/libiec61850s/src/iec61850s.cpp b/src/system/libiec61850s/src/iec61850s.cpp index a22fccd..405301a 100644 --- a/src/system/libiec61850s/src/iec61850s.cpp +++ b/src/system/libiec61850s/src/iec61850s.cpp @@ -406,7 +406,7 @@ int app_iec61850s_init1(void *arg) } - mms_s_dbg_switch(true); + mms_s_dbg_switch(false); mms_s_file_path_set(base_path.c_str()); mms_s_value_update_register(&g_mms_s_value_update_cb); if(NULL == g_mms_s_value_update_cb) diff --git a/src/system/libself_ptl/src/self_ptl.cpp b/src/system/libself_ptl/src/self_ptl.cpp index ab15927..8ee1417 100644 --- a/src/system/libself_ptl/src/self_ptl.cpp +++ b/src/system/libself_ptl/src/self_ptl.cpp @@ -892,13 +892,6 @@ int self_ptl_do_signal_out(stru_app *p_app) stru_self_ptl_cfg_param_data *p_ao = &p_app_cfg_data->ao_vec.at(i); if(p_ao && p_ao->p_param) { - stru_signal_param param; - param.min = safeStringToFloat(p_ao->p_param->min); - param.max = safeStringToFloat(p_ao->p_param->max); - param.step = safeStringToFloat(p_ao->p_param->step); - param.unit = p_ao->p_param->unit; - // dc_param_metadata_store(p_ao->p_param->base.saddr, param); - ret |= dc_signal_ao(p_ao->p_param->base.saddr, p_ao->p_param->base.desc, p_ao->p_param->type, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_ao->vec_p_data[0], p_ao->vec_p_default_data[0], self_ptl_signal_change_callback); } } @@ -913,14 +906,7 @@ int self_ptl_do_signal_out(stru_app *p_app) stru_self_ptl_cfg_param_data *p_param = &p_app_cfg_data->param_vec.at(i); if(p_param && p_param->p_param) { - stru_signal_param param; - param.min = safeStringToFloat(p_param->p_param->min); - param.max = safeStringToFloat(p_param->p_param->max); - param.step = safeStringToFloat(p_param->p_param->step); - param.unit = p_param->p_param->unit; - // dc_param_metadata_store(p_param->p_param->base.saddr, param); - - ret |= dc_signal_param(p_param->p_param->base.saddr, p_param->p_param->base.desc, p_param->p_param->type, + ret |= dc_signal_param(p_param->p_param->base.saddr, p_param->p_param->base.desc, p_param->p_param->type, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_param->vec_p_data.data(), p_param->vec_p_default_data.data(), p_param->p_param->num, self_ptl_signal_change_callback); } }