<修改> 1、调整参数逻辑,参数定值文件分为可配置文件与自动生成文件。可配置文件下载后,自动文件同步相关信息

This commit is contained in:
ypc 2026-06-08 10:00:30 +08:00
parent 7549032700
commit 7c18f5ee9d
6 changed files with 229 additions and 83 deletions

View File

@ -477,7 +477,7 @@ LOCAL void mms_s_da_values_init(stru_icd &icd, std::string da_name, stru_all_DA
return; 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); g_iec61850s_value_init_cb_map[p_all_da->bType](p_all_da->DA, p_all_da->val);
} }

View File

@ -53,6 +53,7 @@ int main(void)
MY_LOG_E("app_cfg_parse failed !"); MY_LOG_E("app_cfg_parse failed !");
return -1; return -1;
} }
if(0 != app_sys_init()) if(0 != app_sys_init())
{ {

View File

@ -20,7 +20,8 @@ bool dc_param_metadata_lookup(const std::string &saddr, stru_signal_param &out_p
return false; 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; using namespace tinyxml2;
@ -38,7 +39,136 @@ int dc_param_cfg_parse(const std::string &path)
return -1; 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<std::string, std::string> dc_self_param_load(const std::string &path)
{
using namespace tinyxml2;
std::unordered_map<std::string, std::string> 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 &param_path,
const std::unordered_map<std::string, std::string> &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"); XMLElement *ao_elem = root->FirstChildElement("Ao");
if (ao_elem) if (ao_elem)
{ {
@ -61,22 +191,25 @@ int dc_param_cfg_parse(const std::string &path)
continue; continue;
} }
float min = sig->FloatAttribute("min", 0.0f); // 默认值始终从 param.xml 读取
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");
const char *default_val = sig->Attribute("default"); 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); void *p_data = dc_create_data_ptr_by_type(data_type);
if (p_data) if (p_data)
{ {
if (val && strlen(val) > 0) if (!run_val.empty())
dc_set_signal_val_from_str(p_data, data_type, std::string(val)); dc_set_signal_val_from_str(p_data, data_type, run_val);
else if (default_val && strlen(default_val) > 0)
dc_set_signal_val_from_str(p_data, data_type, std::string(default_val));
} }
void *p_default_data = dc_create_data_ptr_by_type(data_type); 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) 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, dc_signal_ao(saddr, desc, data_type,
SIGNAL_CTRL_TYPE::SBO_NORMAL, SIGNAL_CTRL_TYPE::SBO_NORMAL,
p_data, p_default_data, nullptr); 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"); XMLElement *param_elem = root->FirstChildElement("Param");
if (param_elem) if (param_elem)
{ {
@ -126,58 +251,49 @@ int dc_param_cfg_parse(const std::string &path)
continue; continue;
} }
float min = sig->FloatAttribute("min", 0.0f); int num = sig->IntAttribute("num", -1);
float max = sig->FloatAttribute("max", 0.0f); if (num < 1) continue;
float step = sig->FloatAttribute("step", 0.0f);
const char *unit = sig->Attribute("unit");
std::vector<void *> vec_p_data; std::vector<void *> vec_p_data;
std::vector<void *> vec_p_default_data; std::vector<void *> vec_p_default_data;
int num = sig->IntAttribute("num", -1); for (XMLElement *item = sig->FirstChildElement("Item"); item != nullptr;
if (num >= 1) item = item->NextSiblingElement("Item"))
{ {
for (XMLElement *item = sig->FirstChildElement("Item"); item != nullptr; int index = item->IntAttribute("index", -1);
item = item->NextSiblingElement("Item")) 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"); if (!run_val.empty())
const char *default_val = item->Attribute("default"); dc_set_signal_val_from_str(p_data, data_type, run_val);
vec_p_data.push_back(p_data);
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);
}
} }
} void *p_default_data = dc_create_data_ptr_by_type(data_type);
else if (p_default_data)
{ {
continue; 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, dc_signal_param(saddr, desc, data_type,
SIGNAL_CTRL_TYPE::SBO_NORMAL, SIGNAL_CTRL_TYPE::SBO_NORMAL,
vec_p_data.data(), vec_p_default_data.data(), num, nullptr); 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<std::string, std::string> 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; return 0;
} }

View File

@ -2177,14 +2177,20 @@ void dc_param_cfg_check(const std::string &path)
root->InsertEndChild(ao_elem); root->InsertEndChild(ao_elem);
root->InsertEndChild(param_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); 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 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());
} }
} }

View File

@ -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_file_path_set(base_path.c_str());
mms_s_value_update_register(&g_mms_s_value_update_cb); mms_s_value_update_register(&g_mms_s_value_update_cb);
if(NULL == g_mms_s_value_update_cb) if(NULL == g_mms_s_value_update_cb)

View File

@ -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); stru_self_ptl_cfg_param_data *p_ao = &p_app_cfg_data->ao_vec.at(i);
if(p_ao && p_ao->p_param) 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); 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); stru_self_ptl_cfg_param_data *p_param = &p_app_cfg_data->param_vec.at(i);
if(p_param && p_param->p_param) if(p_param && p_param->p_param)
{ {
stru_signal_param param; ret |= dc_signal_param(p_param->p_param->base.saddr, p_param->p_param->base.desc, p_param->p_param->type,
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,
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); 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);
} }
} }