<修改> 1、增加git筛选;2、调整解析ftu文件的工具程序;3、编写解析私有规约配置文件的代码

This commit is contained in:
ypc 2026-05-11 15:43:52 +08:00
parent b3201d4dd3
commit 488858317e
12 changed files with 3346 additions and 3029 deletions

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# 只忽略编译出来的二进制、目标文件
*.o
*.a
*.obj
*.lib
*.exe
*.out
*.elf
*.hex
*.map
*.d
*.su
*.pdb
*.idb
*.gch
# 编译临时目录
obj/
build/
lib/
tmp/
# vscode 缓存
.vscode/

View File

View File

@ -1,6 +1,6 @@
SUBDIRS :=
SUBDIRS += ./public
# SUBDIRS += ./public
SUBDIRS += ./protocol
SUBDIRS += ./system

View File

@ -5,7 +5,7 @@ SUBDIRS += ./libicp67
SUBDIRS += ./libmms_m
SUBDIRS += ./libmoongoose
# SUBDIRS += ./libmoongoose

View File

@ -13,9 +13,9 @@ SUBDIRS += ./libweb_server
SUBDIRS += ./RTU
SUBDIRS += ./uart_trans
# SUBDIRS += ./uart_trans
SUBDIRS += ./FTU_cfg_parse
# SUBDIRS += ./FTU_cfg_parse
define make_subdir
@for subdir in $(SUBDIRS); do \

View File

@ -12,6 +12,11 @@ typedef struct
std::string desc;
std::string type_str;
std::string default_value;
std::string min;
std::string max;
std::string step;
std::string unit;
uint8_t type;
uint16_t inf;
}stru_param_cfg_data;

View File

@ -17,12 +17,16 @@ typedef struct
int capacity;
}stru_csv_data;
typedef struct
typedef struct
{
std::string saddr;
std::string desc;
std::string type_str;
std::string default_value;
std::string min;
std::string max;
std::string step;
std::string unit;
}stru_param_csv_data;
@ -41,12 +45,6 @@ typedef struct
std::vector<stru_st_mx_co_dd_info> *p_info;
}stru_cfg_file_info;
// LOCAL std::map<std::string, std::vector<stru_st_mx_co_dd_info> *> g_gen_file_list = {
// {"st.csv", &g_ftu_cfg.st_info_vec},
// {"mx.csv", &g_ftu_cfg.mx_info_vec},
// {"co.csv", &g_ftu_cfg.co_info_vec},
// {"dd.csv", &g_ftu_cfg.dd_info_vec}
// };
LOCAL std::vector<stru_cfg_file_info> g_gen_file_list = {
{"st", "st.csv", &g_ftu_cfg.st_info_vec},
@ -311,6 +309,133 @@ LOCAL void show_st_mx_co_dd_info_vec(const std::vector<stru_st_mx_co_dd_info> &i
}
}
LOCAL void parse_remark(const std::string &remark, std::string &min, std::string &max, std::string &step, std::string &unit)
{
if (remark.empty())
{
return;
}
// 找到"范围"部分
std::string range_part;
size_t range_pos = remark.find("\xe8\x8c\x83\xe5\x9b\xb4"); // "范围" UTF-8
if (range_pos == std::string::npos)
{
return;
}
std::string after_range = remark.substr(range_pos + 6); // skip "范围"
// 跳过冒号(中文:或英文:
if (!after_range.empty() && (after_range[0] == '\xef' && after_range[1] == '\xbc' && after_range[2] == '\x9a'))
{
after_range = after_range.substr(3); // skip ""
}
else if (!after_range.empty() && after_range[0] == ':')
{
after_range = after_range.substr(1); // skip ":"
}
// 按""分割,第一部分是范围,后面可能有单位和描述
size_t semicolon = after_range.find("\xef\xbc\x9b"); // "" UTF-8
range_part = (semicolon != std::string::npos) ? after_range.substr(0, semicolon) : after_range;
std::string rest = (semicolon != std::string::npos) ? after_range.substr(semicolon + 3) : "";
// 解析范围部分
range_part = trim(range_part);
if (!range_part.empty())
{
if (range_part[0] == '<')
{
// 范围:< MAX
std::string val = range_part.substr(1);
max = trim(val);
}
else if (range_part[0] == '>')
{
// 范围:> MIN
std::string val = range_part.substr(1);
min = trim(val);
}
else
{
// 范围MIN-MAX
size_t dash = range_part.find('-');
if (dash == std::string::npos)
{
// 尝试找 "/" 分隔的枚举值取第一个值作为min最后一个作为max
// 如 "电磁式100/220"
size_t slash = range_part.find('/');
if (slash != std::string::npos)
{
// 复杂枚举,不做解析
}
return;
}
min = trim(range_part.substr(0, dash));
max = trim(range_part.substr(dash + 1));
}
}
// 从剩余部分提取单位
if (!rest.empty())
{
size_t unit_pos = rest.find("\xe5\x8d\x95\xe4\xbd\x8d"); // "单位" UTF-8
if (unit_pos != std::string::npos)
{
std::string unit_str = rest.substr(unit_pos + 6); // skip "单位"
// 跳过冒号(中文:或英文:
if (!unit_str.empty() && (unit_str[0] == '\xef' && unit_str[1] == '\xbc' && unit_str[2] == '\x9a'))
{
unit_str = unit_str.substr(3); // skip ""
}
else if (!unit_str.empty() && unit_str[0] == ':')
{
unit_str = unit_str.substr(1);
}
// 只取到下一个""或结尾
size_t next_semi = unit_str.find("\xef\xbc\x9b");
if (next_semi != std::string::npos)
{
unit_str = unit_str.substr(0, next_semi);
}
// 去掉括号中的补充说明,如 "ms(等于0时...)" -> "ms"
size_t paren = unit_str.find('(');
if (paren != std::string::npos)
{
unit_str = unit_str.substr(0, paren);
}
// 去掉"/"后的补充说明,如 "s/21600s=6h" -> "s"
size_t slash = unit_str.find('/');
if (slash != std::string::npos)
{
unit_str = unit_str.substr(0, slash);
}
unit = trim(unit_str);
}
}
// 如果备注中没有分号而是空格分隔,尝试匹配 "单位XXX" 直接在范围后面
// 如 "范围: 0-60000 单位5ms"
if (unit.empty() && semicolon == std::string::npos)
{
size_t unit_pos = after_range.find("\xe5\x8d\x95\xe4\xbd\x8d"); // "单位"
if (unit_pos != std::string::npos)
{
std::string unit_str = after_range.substr(unit_pos + 6);
if (!unit_str.empty() && (unit_str[0] == '\xef' && unit_str[1] == '\xbc' && unit_str[2] == '\x9a'))
{
unit_str = unit_str.substr(3);
}
else if (!unit_str.empty() && unit_str[0] == ':')
{
unit_str = unit_str.substr(1);
}
unit = trim(unit_str);
}
}
}
LOCAL int parse_param_csv(const std::string &path)
{
stru_csv_data *p_csv = nullptr;
@ -331,9 +456,13 @@ LOCAL int parse_param_csv(const std::string &path)
std::string saddr = row.field_vec[1];
std::string type_str = row.field_vec[2];
std::string desc = row.field_vec[3];
std::string remark = row.field_vec[4];
std::string default_value = row.field_vec[5];
g_param_csv_data_vec.push_back({saddr, desc, type_str, default_value});
std::string min, max, step, unit;
parse_remark(remark, min, max, step, unit);
g_param_csv_data_vec.push_back({saddr, desc, type_str, default_value, min, max, step, unit});
}
return 0;
@ -375,7 +504,10 @@ LOCAL void parse_param_cfg_info(std::string temp, stru_param_cfg &param_cfg)
desc = param_csv_data.desc;
default_value = param_csv_data.default_value;
std::string saddr_str = "self_ptl.param." + saddr;
vec_param.push_back({saddr_str, desc, type, default_value, type_info.type_id, 0});
vec_param.push_back({saddr_str, desc, type, default_value,
param_csv_data.min, param_csv_data.max,
param_csv_data.step, param_csv_data.unit,
type_info.type_id, 0});
break;
}
}

View File

@ -37,9 +37,9 @@ LOCAL tinyxml2::XMLElement *add_info_element(tinyxml2::XMLDocument &doc, tinyxml
// 设置desc属性
item->SetAttribute("desc", info.desc.c_str());
// 设置inf属性
std::ostringstream oss;
oss << "0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << info.inf;
item->SetAttribute("inf_hex", oss.str().c_str());
// std::ostringstream oss;
// oss << "0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << info.inf;
// item->SetAttribute("inf_hex", oss.str().c_str());
item->SetAttribute("inf", (int)info.inf);
@ -49,36 +49,6 @@ LOCAL tinyxml2::XMLElement *add_info_element(tinyxml2::XMLDocument &doc, tinyxml
LOCAL void add_param_element(tinyxml2::XMLDocument &doc, tinyxml2::XMLElement *parent, const stru_param_cfg_data &param)
{
// tinyxml2::XMLElement *item = doc.NewElement("Param");
// tinyxml2::XMLElement *saddr = doc.NewElement("saddr");
// saddr->SetText(param.saddr.c_str());
// item->InsertEndChild(saddr);
// tinyxml2::XMLElement *desc = doc.NewElement("desc");
// desc->SetText(param.desc.c_str());
// item->InsertEndChild(desc);
// tinyxml2::XMLElement *type_str = doc.NewElement("type_str");
// type_str->SetText(param.type_str.c_str());
// item->InsertEndChild(type_str);
// tinyxml2::XMLElement *default_value = doc.NewElement("default_value");
// default_value->SetText(param.default_value.c_str());
// item->InsertEndChild(default_value);
// tinyxml2::XMLElement *type_id = doc.NewElement("type_id");
// type_id->SetText(type_id_to_str(param.type));
// item->InsertEndChild(type_id);
// std::ostringstream oss;
// oss << "0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << param.inf;
// tinyxml2::XMLElement *inf = doc.NewElement("inf");
// inf->SetText(oss.str().c_str());
// item->InsertEndChild(inf);
// parent->InsertEndChild(item);
tinyxml2::XMLElement *item = doc.NewElement("Item");
// 设置 saddr 属性
@ -87,21 +57,31 @@ LOCAL void add_param_element(tinyxml2::XMLDocument &doc, tinyxml2::XMLElement *p
// 设置desc属性
item->SetAttribute("desc", param.desc.c_str());
// 设置inf属性
std::ostringstream oss;
oss << "0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << param.inf;
item->SetAttribute("inf_hex", oss.str().c_str());
// std::ostringstream oss;
// oss << "0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << param.inf;
// item->SetAttribute("inf_hex", oss.str().c_str());
item->SetAttribute("inf", (int)param.inf);
// 设置type_str属性
item->SetAttribute("type_str", param.type_str.c_str());
item->SetAttribute("type", param.type_str.c_str());
// type_id属性
item->SetAttribute("type_id", (int)param.type);
// item->SetAttribute("type_id", (int)param.type);
// 设置default_value属性
item->SetAttribute("default_value", param.default_value.c_str());
item->SetAttribute("default", param.default_value.c_str());
// 设置min、max、step、unit属性
// item->SetAttribute("min", param.min.c_str());
// item->SetAttribute("max", param.max.c_str());
// item->SetAttribute("step", param.step.c_str());
// item->SetAttribute("unit", param.unit.c_str());
item->SetAttribute("min", "");
item->SetAttribute("max", "");
item->SetAttribute("step", "");
item->SetAttribute("unit", "");
parent->InsertEndChild(item);

View File

@ -0,0 +1,39 @@
#pragma once
#include "myBase.h"
#include "mySystem.h"
typedef struct
{
std::string saddr;
std::string desc;
uint16_t inf;
}stru_self_ptl_cfg_base;
typedef struct
{
stru_self_ptl_cfg_base base;
uint8_t type;
std::string default_value;
std::string unit;
std::string min;
std::string max;
std::string step;
}stru_self_ptl_cfg_param;
typedef struct
{
std::vector<stru_self_ptl_cfg_base> st_vec;
std::vector<stru_self_ptl_cfg_base> mx_vec;
std::vector<stru_self_ptl_cfg_base> co_vec;
std::vector<stru_self_ptl_cfg_base> dd_vec;
std::vector<stru_self_ptl_cfg_param> param_vec;
}stru_self_ptl_cfg;
int self_ptl_cfg_parse(const std::string &path);
stru_self_ptl_cfg* self_ptl_cfg_get();

View File

@ -1,3 +0,0 @@
#include "myBase.h"
#include "mySystem.h"

View File

@ -0,0 +1,140 @@
#include "self_ptl_cfg.h"
#include "tinyxml2.h"
LOCAL const char *ele_Root = "Root";
LOCAL const char *ele_St = "St";
LOCAL const char *ele_Mx = "Mx";
LOCAL const char *ele_Co = "Co";
LOCAL const char *ele_Dd = "Dd";
LOCAL const char *ele_Param = "Param";
LOCAL const char *ele_Item = "Item";
LOCAL const char *attr_count = "count";
LOCAL const char *attr_saddr = "saddr";
LOCAL const char *attr_desc = "desc";
LOCAL const char *attr_inf = "inf";
LOCAL const char *attr_type = "type";
LOCAL const char *attr_default = "default";
LOCAL const char *attr_unit = "unit";
LOCAL const char *attr_min = "min";
LOCAL const char *attr_max = "max";
LOCAL const char *attr_step = "step";
LOCAL stru_self_ptl_cfg g_self_ptl_cfg;
typedef struct
{
std::string type;
std::vector<stru_self_ptl_cfg_base> *p_vec;
}stru_local_parse_base;
std::vector<stru_local_parse_base> g_local_parse_vec =
{
{ele_St, &g_self_ptl_cfg.st_vec},
{ele_Mx, &g_self_ptl_cfg.mx_vec},
{ele_Co, &g_self_ptl_cfg.co_vec},
{ele_Dd, &g_self_ptl_cfg.dd_vec},
};
stru_self_ptl_cfg* self_ptl_cfg_get()
{
return &g_self_ptl_cfg;
}
LOCAL int parse_base(tinyxml2::XMLElement *root)
{
if (root == nullptr)
{
MY_LOG_E("parse failed, root element is null");
return -1;
}
for (const auto &local_parse : g_local_parse_vec)
{
tinyxml2::XMLElement *parent_ele = root->FirstChildElement(local_parse.type.c_str());
if (parent_ele == nullptr)
{
MY_LOG_E("not found element %s", local_parse.type.c_str());
continue;
}
const char *count_str = parent_ele->Attribute(attr_count);
int count = 0;
if (count_str != nullptr)
{
count = atoi(count_str);
}
else
{
MY_LOG_E("not found attribute %s in element %s", attr_count, local_parse.type.c_str());
continue;
}
tinyxml2::XMLElement *item_ele = parent_ele->FirstChildElement(ele_Item);
while (item_ele != nullptr)
{
stru_self_ptl_cfg_base cfg_base;
const char *saddr = item_ele->Attribute(attr_saddr);
const char *desc = item_ele->Attribute(attr_desc);
int inf = 0;
item_ele->QueryIntAttribute(attr_inf, &inf);
if (saddr != nullptr)
{
cfg_base.saddr = saddr;
}
if (desc != nullptr)
{
cfg_base.desc = desc;
}
cfg_base.inf = inf;
local_parse.p_vec->push_back(cfg_base);
item_ele = item_ele->NextSiblingElement(ele_Item);
}
if(local_parse.p_vec->size() != count)
{
MY_LOG_E("count mismatch for element %s, expected %d, actual %d",
local_parse.type.c_str(), count, (int)local_parse.p_vec->size());
return -1;
}
}
return 0;
}
int self_ptl_cfg_parse(const std::string &path)
{
// 解析XML文件
tinyxml2::XMLDocument doc;
if (doc.LoadFile(path.c_str()) != tinyxml2::XML_SUCCESS)
{
MY_LOG_E("Failed to load XML file: %s", path.c_str());
return -1;
}
tinyxml2::XMLElement *root = doc.RootElement();
if (root == nullptr)
{
MY_LOG_E("Failed to get root element");
return -1;
}
if(parse_base(root) != 0)
{
MY_LOG_E("Failed to parse base elements");
return -1;
}
return 0;
}

File diff suppressed because it is too large Load Diff