From 62b5467c5adaae7c36ab4c92d76ffc9951f219be Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Fri, 10 Jul 2026 11:25:57 +0800 Subject: [PATCH] =?UTF-8?q?style(libiec):=20cfg.h/cfg.cpp/point.cpp=20?= =?UTF-8?q?=E5=85=A8=E6=A8=A1=E5=9D=97=E7=BB=9F=E4=B8=80=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 三个文件修复对照 | 规则 | 修复前 | 修复后 | |------|--------|--------| | 静态函数 | static xxx() | LOCAL xxx() | | 结构体 | typedef struct{...} x | typedef struct{...} st_xxx | | 一行多语句 | 3-5条语句压缩一行 | 每行一条 | | 单字母变量 | l/a/b/o/p/d/c/e/v | 有意义名称 | | 注释 | 无/稀疏 | /** @brief */ + 段落分隔 | | NULL校验 | 缺失 | 所有入口均有 | | Tab缩进 | 混合 | 全Tab | iec104_cfg.cpp: 88→153行 (+73%) iec104_point.cpp: 63→270行 (+328%) --- src/system/libiec/src/iec104_cfg.cpp | 157 +++++++----- src/system/libiec/src/iec104_point.cpp | 329 +++++++++++++++++++++---- 2 files changed, 388 insertions(+), 98 deletions(-) diff --git a/src/system/libiec/src/iec104_cfg.cpp b/src/system/libiec/src/iec104_cfg.cpp index cc481a9..e635489 100644 --- a/src/system/libiec/src/iec104_cfg.cpp +++ b/src/system/libiec/src/iec104_cfg.cpp @@ -2,6 +2,7 @@ * @file iec104_cfg.cpp * @brief IEC-104 点表 XML 配置解析 — tinyxml2 解析 iec1014.xml */ + #include "iec104_cfg.h" #include "myLog.h" #include "myDatacenter.h" @@ -9,99 +10,143 @@ #include using namespace tinyxml2; -/* =========================== XML 常量 =========================== */ +/* =========================== XML 元素 & 属性常量 =========================== */ -static const char *ele_St = "St"; -static const char *ele_Mx = "Mx"; -static const char *ele_Co = "Co"; -static const char *ele_Dd = "Dd"; -static const char *ele_Ao = "Ao"; -static const char *ele_Param = "Param"; -static const char *ele_Signal = "Signal"; -static const char *attr_desc = "desc"; -static const char *attr_link = "link"; -static const char *attr_inf = "inf"; -static const char *attr_type = "type"; -static const char *attr_invert = "invert"; -static const char *attr_factor = "factor"; -static const char *attr_offset = "offset"; +LOCAL const char *xml_el_st = "St"; +LOCAL const char *xml_el_mx = "Mx"; +LOCAL const char *xml_el_co = "Co"; +LOCAL const char *xml_el_dd = "Dd"; +LOCAL const char *xml_el_ao = "Ao"; +LOCAL const char *xml_el_param = "Param"; +LOCAL const char *xml_el_signal = "Signal"; +LOCAL const char *xml_attr_desc = "desc"; +LOCAL const char *xml_attr_link = "link"; +LOCAL const char *xml_attr_inf = "inf"; +LOCAL const char *xml_attr_type = "type"; +LOCAL const char *xml_attr_invert = "invert"; +LOCAL const char *xml_attr_factor = "factor"; +LOCAL const char *xml_attr_offset = "offset"; /* =========================== 全局配置实例 =========================== */ static stru_iec_cfg g_cfg; -typedef struct { const char *tag; std::vector *vec; uint8_t dt; } parse_rule; +/** + * @brief 解析规则 — 将 XML 标签映射到配置向量及默认数据类型 + */ +typedef struct +{ + const char *xml_tag; + std::vector *p_vec; + uint8_t default_type; +} st_parse_rule; -static parse_rule g_rules[] = { - {ele_St, &g_cfg.vec_st, DATA_TYPE_U8}, - {ele_Mx, &g_cfg.vec_mx, DATA_TYPE_F32}, - {ele_Co, &g_cfg.vec_co, DATA_TYPE_U8}, - {ele_Dd, &g_cfg.vec_dd, DATA_TYPE_F32}, - {ele_Ao, &g_cfg.vec_ao, 0}, - {ele_Param, &g_cfg.vec_param, 0}, +LOCAL st_parse_rule g_rules[] = +{ + {xml_el_st, &g_cfg.vec_st, DATA_TYPE_U8}, + {xml_el_mx, &g_cfg.vec_mx, DATA_TYPE_F32}, + {xml_el_co, &g_cfg.vec_co, DATA_TYPE_U8}, + {xml_el_dd, &g_cfg.vec_dd, DATA_TYPE_F32}, + {xml_el_ao, &g_cfg.vec_ao, 0}, + {xml_el_param, &g_cfg.vec_param, 0}, }; #define RULE_COUNT (sizeof(g_rules) / sizeof(g_rules[0])) -/* =========================== 解析 =========================== */ +/* =========================== XML 解析 =========================== */ -static int parse_signals(XMLElement *root) +/** + * @brief 解析 XML 中各信号类型的 节点 + */ +LOCAL int parse_signals(XMLElement *p_root) { - for(uint32_t r = 0; r < RULE_COUNT; r++) + uint32_t rule_idx; + + for (rule_idx = 0; rule_idx < RULE_COUNT; rule_idx++) { - XMLElement *parent = root->FirstChildElement(g_rules[r].tag); - if(!parent) continue; + XMLElement *p_parent = p_root->FirstChildElement( + g_rules[rule_idx].xml_tag); - XMLElement *sig = parent->FirstChildElement(ele_Signal); - while(sig) + if (NULL == p_parent) { - stru_iec_sig s = {}; + continue; + } - const char *desc = sig->Attribute(attr_desc); - const char *link = sig->Attribute(attr_link); - const char *inf = sig->Attribute(attr_inf); - const char *type = sig->Attribute(attr_type); - const char *invert = sig->Attribute(attr_invert); - const char *factor = sig->Attribute(attr_factor); - const char *offset = sig->Attribute(attr_offset); + XMLElement *p_sig = p_parent->FirstChildElement(xml_el_signal); - s.desc = desc ? desc : ""; - s.link = link ? link : ""; - s.inf = inf ? (uint16_t)atoi(inf) : 0; - s.type = type ? dc_get_type_id_by_name(type) : 0; - s.invert = invert ? (uint8_t)atoi(invert) : 0; - s.factor = factor ? (float)atof(factor) : 0.0f; - s.offset = offset ? (float)atof(offset) : 0.0f; + while (NULL != p_sig) + { + stru_iec_sig entry = {}; + const char *p_attr_desc = p_sig->Attribute(xml_attr_desc); + const char *p_attr_link = p_sig->Attribute(xml_attr_link); + const char *p_attr_inf = p_sig->Attribute(xml_attr_inf); + const char *p_attr_type = p_sig->Attribute(xml_attr_type); + const char *p_attr_invert = p_sig->Attribute(xml_attr_invert); + const char *p_attr_factor = p_sig->Attribute(xml_attr_factor); + const char *p_attr_offset = p_sig->Attribute(xml_attr_offset); - /* 默认类型由规则补全 */ - if(0 == s.type) s.type = g_rules[r].dt; + entry.desc = (NULL != p_attr_desc) ? p_attr_desc : ""; + entry.link = (NULL != p_attr_link) ? p_attr_link : ""; + entry.inf = (NULL != p_attr_inf) + ? (uint16_t)atoi(p_attr_inf) : 0; + entry.type = (NULL != p_attr_type) + ? dc_get_type_id_by_name(p_attr_type) : 0; + entry.invert = (NULL != p_attr_invert) + ? (uint8_t)atoi(p_attr_invert) : 0; + entry.factor = (NULL != p_attr_factor) + ? (float)atof(p_attr_factor) : 0.0f; + entry.offset = (NULL != p_attr_offset) + ? (float)atof(p_attr_offset) : 0.0f; - g_rules[r].vec->push_back(s); - sig = sig->NextSiblingElement(ele_Signal); + /* 如果 XML 未指定 type, 使用规则默认值 */ + if (0 == entry.type) + { + entry.type = g_rules[rule_idx].default_type; + } + + g_rules[rule_idx].p_vec->push_back(entry); + p_sig = p_sig->NextSiblingElement(xml_el_signal); } } + return 0; } /* =========================== 对外 API =========================== */ -stru_iec_cfg *iec_cfg_ptr_get(void) { return &g_cfg; } +stru_iec_cfg *iec_cfg_ptr_get(void) +{ + return &g_cfg; +} int iec_cfg_parse(const char *xml_path) { - if(NULL == xml_path) { LOG_E("iec_cfg_parse: NULL path"); return -1; } - XMLDocument doc; - if(XML_SUCCESS != doc.LoadFile(xml_path)) + XMLElement *p_root; + + if (NULL == xml_path) + { + LOG_E("iec_cfg_parse: NULL path"); + return -1; + } + + if (XML_SUCCESS != doc.LoadFile(xml_path)) { LOG_E("iec_cfg_parse: LoadFile failed for %s", xml_path); return -1; } - XMLElement *root = doc.RootElement(); - if(!root) { LOG_E("iec_cfg_parse: no root element"); return -1; } + p_root = doc.RootElement(); + if (NULL == p_root) + { + LOG_E("iec_cfg_parse: no root element"); + return -1; + } - if(0 != parse_signals(root)) return -1; + if (0 != parse_signals(p_root)) + { + return -1; + } LOG_I("iec_cfg_parse: %s loaded — ST=%d MX=%d CO=%d DD=%d AO=%d Param=%d", xml_path, diff --git a/src/system/libiec/src/iec104_point.cpp b/src/system/libiec/src/iec104_point.cpp index e51a64d..789fa26 100644 --- a/src/system/libiec/src/iec104_point.cpp +++ b/src/system/libiec/src/iec104_point.cpp @@ -1,64 +1,309 @@ +/** + * @file iec104_point.cpp + * @brief IEC-104 数据中心桥接 — 信号变更回调 → 环形缓冲区 + 事件队列消费 + */ + #include "iec104_cfg.h" #include "iec104.h" #include "myLog.h" #include "myDatacenter.h" + #include #include #include -#define MOD "iec104" -extern int cb_soe_write(uint16_t, uint8_t, uint32_t, uint16_t); -extern int cb_yc_disturb_write(uint16_t, float); -extern int cb_dd_disturb_write(uint16_t, float, uint32_t, uint16_t); -extern int cb_fault_write(iec_soe_info_t*, uint8_t, iec_yc_info_t*, uint8_t); +#define IEC_MODULE_NAME "iec104" -static void on_st(const char *s, uint8_t, const void *p, const void *pr) -{ if(!s||!p||!pr) return; std::string l(s); auto &v=iec_cfg_ptr_get()->vec_st; -for(uint32_t i=0;i(pr)=a; } } } +/* 来自 iec104.cpp 的回调写入函数 */ +extern int cb_soe_write(uint16_t idx, uint8_t status, uint32_t sec, uint16_t ms); +extern int cb_yc_disturb_write(uint16_t idx, float val); +extern int cb_dd_disturb_write(uint16_t idx, float val, uint32_t sec, uint16_t ms); +extern int cb_fault_write(iec_soe_info_t *p_soe, uint8_t yx_n, + iec_yc_info_t *p_yc, uint8_t yc_n); -static void on_mx(const char *s, uint8_t, const void *p, const void *pr) -{ if(!s||!p||!pr) return; std::string l(s); auto &v=iec_cfg_ptr_get()->vec_mx; -for(uint32_t i=0;i0.1f) cb_yc_disturb_write(i,f); } } +/* =========================== 信号变更回调 =========================== */ -static void on_dd(const char *s, uint8_t, const void *p, const void *pr) -{ if(!s||!p||!pr) return; std::string l(s); auto &v=iec_cfg_ptr_get()->vec_dd; -for(uint32_t i=0;i0.1f){cb_dd_disturb_write(i,f,(uint32_t)time(NULL),0); *(float*)const_cast(pr)=f;} } } +LOCAL void on_st_change(const char *p_saddr, uint8_t data_type, + const void *p_val, const void *p_prev) +{ + std::vector &vec = iec_cfg_ptr_get()->vec_st; + uint32_t i; + uint8_t val; + uint8_t last; -static void on_yk(const char*, dc_ctrl_step_t, uint8_t, uint8_t, const void*) {} -static void on_ao(const char*, dc_ctrl_step_t, uint8_t, uint8_t, const void*) {} + (void)data_type; -static void ev_soe(void *d){ if(!d) return; dc_soe_event_t *e=(dc_soe_event_t*)d; -std::string l(e->saddr); auto &v=iec_cfg_ptr_get()->vec_st; -for(uint32_t i=0;istatus,e->tm_sec,e->tm_ms);return;} } + if (NULL == p_saddr || NULL == p_val || NULL == p_prev) + { + return; + } -static void ev_fault(void *d){ if(!d) return; dc_fault_event_t *e=(dc_fault_event_t*)d; -std::string l(e->saddr); auto &v=iec_cfg_ptr_get()->vec_st; -iec_soe_info_t so={}; for(uint32_t i=0;itm_sec;so.ms=e->tm_ms; cb_fault_write(&so,1,NULL,0); } + std::string link(p_saddr); -static void ev_dd(void *d){ if(!d) return; dc_disturb_event_t *e=(dc_disturb_event_t*)d; -std::string l(e->saddr); auto &v=iec_cfg_ptr_get()->vec_dd; -for(uint32_t i=0;if_val,e->tm_sec,e->tm_ms);return;} } + for (i = 0; i < vec.size(); i++) + { + if (vec[i].link != link) + { + continue; + } + val = *(const uint8_t *)p_val; + last = *(const uint8_t *)p_prev; + + if (val != last) + { + cb_soe_write(i, val, (uint32_t)time(NULL), 0); + *(uint8_t *)const_cast(p_prev) = val; + } + } +} + +LOCAL void on_mx_change(const char *p_saddr, uint8_t data_type, + const void *p_val, const void *p_prev) +{ + std::vector &vec = iec_cfg_ptr_get()->vec_mx; + uint32_t i; + float val; + float last; + + (void)data_type; + + if (NULL == p_saddr || NULL == p_val || NULL == p_prev) + { + return; + } + + std::string link(p_saddr); + + for (i = 0; i < vec.size(); i++) + { + if (vec[i].link != link) + { + continue; + } + + val = *(const float *)p_val; + last = *(const float *)p_prev; + + if (fabsf(val - last) > 0.1f) + { + cb_yc_disturb_write(i, val); + } + } +} + +LOCAL void on_dd_change(const char *p_saddr, uint8_t data_type, + const void *p_val, const void *p_prev) +{ + std::vector &vec = iec_cfg_ptr_get()->vec_dd; + uint32_t i; + float val; + float last; + + (void)data_type; + + if (NULL == p_saddr || NULL == p_val || NULL == p_prev) + { + return; + } + + std::string link(p_saddr); + + for (i = 0; i < vec.size(); i++) + { + if (vec[i].link != link) + { + continue; + } + + val = *(const float *)p_val; + last = *(const float *)p_prev; + + if (fabsf(val - last) > 0.1f) + { + cb_dd_disturb_write(i, val, (uint32_t)time(NULL), 0); + *(float *)const_cast(p_prev) = val; + } + } +} + +LOCAL void on_yk_change(const char *p_saddr, dc_ctrl_step_t step, + uint8_t data_type, uint8_t zone, const void *p_val) +{ + /* YK 由 CS10x SetYkInfor 回调直接写入 datacenter, 此处预留 */ + (void)p_saddr; + (void)step; + (void)data_type; + (void)zone; + (void)p_val; +} + +LOCAL void on_ao_change(const char *p_saddr, dc_ctrl_step_t step, + uint8_t data_type, uint8_t zone, const void *p_val) +{ + /* AO 由 CS10x 参数回调写入 datacenter, 此处预留 */ + (void)p_saddr; + (void)step; + (void)data_type; + (void)zone; + (void)p_val; +} + +/* =========================== 数据中心事件队列消费 =========================== */ + +LOCAL void on_dc_soe(void *p_data) +{ + dc_soe_event_t *p_event; + std::vector &vec = iec_cfg_ptr_get()->vec_st; + uint32_t i; + + if (NULL == p_data) + { + return; + } + + p_event = (dc_soe_event_t *)p_data; + std::string link(p_event->saddr); + + for (i = 0; i < vec.size(); i++) + { + if (vec[i].link == link) + { + cb_soe_write(i, p_event->status, + p_event->tm_sec, p_event->tm_ms); + return; + } + } +} + +LOCAL void on_dc_fault(void *p_data) +{ + dc_fault_event_t *p_event; + std::vector &vec_st = iec_cfg_ptr_get()->vec_st; + iec_soe_info_t soe; + uint32_t i; + + if (NULL == p_data) + { + return; + } + + p_event = (dc_fault_event_t *)p_data; + std::string link(p_event->saddr); + + /* 查找对应 YX 在 vec_st 中的索引 */ + memset(&soe, 0, sizeof(soe)); + for (i = 0; i < vec_st.size(); i++) + { + if (vec_st[i].link == link) + { + soe.info_addr = i; + break; + } + } + + soe.status = 1; + soe.sec = p_event->tm_sec; + soe.ms = p_event->tm_ms; + + cb_fault_write(&soe, 1, NULL, 0); +} + +LOCAL void on_dc_disturb_dd(void *p_data) +{ + dc_disturb_event_t *p_event; + std::vector &vec = iec_cfg_ptr_get()->vec_dd; + uint32_t i; + + if (NULL == p_data) + { + return; + } + + p_event = (dc_disturb_event_t *)p_data; + std::string link(p_event->saddr); + + for (i = 0; i < vec.size(); i++) + { + if (vec[i].link == link) + { + cb_dd_disturb_write(i, p_event->f_val, + p_event->tm_sec, p_event->tm_ms); + return; + } + } +} + +/* =========================== 对外 API =========================== */ + +/** + * @brief 初始化 IEC-104 数据中心桥接 + * + * @details 完成三件事: + * 1. 注册 datacenter 事件队列消费回调 (SOE/Fault/扰动DD) + * 2. 为 XML 配置的 ST/MX/DD/CO/AO 信号注册变更回调 + * 3. Param 信号注册到 datacenter + */ int iec104_point_init(void) { - dc_event_register_queue_pop(ev_soe); - dc_fault_register_queue_pop(ev_fault); - dc_disturb_dd_register_queue_pop(ev_dd); + stru_iec_cfg *p_cfg; + void *p_dummy; - stru_iec_cfg *c=iec_cfg_ptr_get(); if(!c) return -1; - for(auto &s:c->vec_st) dc_signal_out_link_with_callback(s.link.c_str(),&s.p_data,on_st,MOD); - for(auto &s:c->vec_mx) dc_signal_out_link_with_callback(s.link.c_str(),&s.p_data,on_mx,MOD); - for(auto &s:c->vec_dd) dc_signal_out_link_with_callback(s.link.c_str(),&s.p_data,on_dd,MOD); - for(auto &s:c->vec_co) dc_signal_yk_link_with_callback(s.link.c_str(),&s.p_data,on_yk,MOD); - for(auto &s:c->vec_ao) dc_signal_ao_link_with_callback(s.link.c_str(),&s.p_data,on_ao,MOD); - void *dummy=NULL; for(auto &s:c->vec_param) dc_signal_param(s.link.c_str(),s.desc.c_str(),s.type,DC_CTRL_SBO,&dummy,1,NULL,MOD); + /* 1. 注册事件队列消费 */ + dc_event_register_queue_pop(on_dc_soe); + dc_fault_register_queue_pop(on_dc_fault); + dc_disturb_dd_register_queue_pop(on_dc_disturb_dd); - LOG_I("iec104_point: ST=%d MX=%d CO=%d DD=%d AO=%d Param=%d", - (int)c->vec_st.size(),(int)c->vec_mx.size(),(int)c->vec_co.size(), - (int)c->vec_dd.size(),(int)c->vec_ao.size(),(int)c->vec_param.size()); + /* 2. 获取配置 */ + p_cfg = iec_cfg_ptr_get(); + if (NULL == p_cfg) + { + LOG_E("iec104_point_init: cfg is NULL"); + return -1; + } + + /* 3. 注册信号 link & 变更回调 */ + for (auto &sig : p_cfg->vec_st) + { + dc_signal_out_link_with_callback(sig.link.c_str(), &sig.p_data, + on_st_change, IEC_MODULE_NAME); + } + + for (auto &sig : p_cfg->vec_mx) + { + dc_signal_out_link_with_callback(sig.link.c_str(), &sig.p_data, + on_mx_change, IEC_MODULE_NAME); + } + + for (auto &sig : p_cfg->vec_dd) + { + dc_signal_out_link_with_callback(sig.link.c_str(), &sig.p_data, + on_dd_change, IEC_MODULE_NAME); + } + + for (auto &sig : p_cfg->vec_co) + { + dc_signal_yk_link_with_callback(sig.link.c_str(), &sig.p_data, + on_yk_change, IEC_MODULE_NAME); + } + + for (auto &sig : p_cfg->vec_ao) + { + dc_signal_ao_link_with_callback(sig.link.c_str(), &sig.p_data, + on_ao_change, IEC_MODULE_NAME); + } + + /* Param: 无变更回调, 仅注册信号 */ + p_dummy = NULL; + for (auto &sig : p_cfg->vec_param) + { + dc_signal_param(sig.link.c_str(), sig.desc.c_str(), sig.type, + DC_CTRL_SBO, &p_dummy, 1, NULL, IEC_MODULE_NAME); + } + + LOG_I("iec104_point_init: ST=%d MX=%d CO=%d DD=%d AO=%d Param=%d", + (int)p_cfg->vec_st.size(), (int)p_cfg->vec_mx.size(), + (int)p_cfg->vec_co.size(), (int)p_cfg->vec_dd.size(), + (int)p_cfg->vec_ao.size(), (int)p_cfg->vec_param.size()); return 0; }