style(libiec): cfg.h/cfg.cpp/point.cpp 全模块统一格式规范

## 三个文件修复对照

| 规则 | 修复前 | 修复后 |
|------|--------|--------|
| 静态函数 | 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%)
This commit is contained in:
ypc 2026-07-10 11:25:57 +08:00
parent be2d8352fb
commit 62b5467c5a
2 changed files with 388 additions and 98 deletions

View File

@ -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 <tinyxml2.h>
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<stru_iec_sig> *vec; uint8_t dt; } parse_rule;
/**
* @brief XML
*/
typedef struct
{
const char *xml_tag;
std::vector<stru_iec_sig> *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 <Signal>
*/
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;
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,

View File

@ -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 <math.h>
#include <time.h>
#include <string.h>
#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<v.size();i++){ if(v[i].link!=l) continue;
uint8_t a=*(const uint8_t*)p,b=*(const uint8_t*)pr; if(a!=b){cb_soe_write(i,a,(uint32_t)time(NULL),0); *(uint8_t*)const_cast<void*>(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;i<v.size();i++){ if(v[i].link!=l) continue;
float f=*(const float*)p,lf=*(const float*)pr; if(fabsf(f-lf)>0.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;i<v.size();i++){ if(v[i].link!=l) continue;
float f=*(const float*)p,lf=*(const float*)pr; if(fabsf(f-lf)>0.1f){cb_dd_disturb_write(i,f,(uint32_t)time(NULL),0); *(float*)const_cast<void*>(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<stru_iec_sig> &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;i<v.size();i++) if(v[i].link==l){cb_soe_write(i,e->status,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;i<v.size();i++) if(v[i].link==l){so.info_addr=i;break;}
so.status=1;so.sec=e->tm_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;i<v.size();i++) if(v[i].link==l){cb_dd_disturb_write(i,e->f_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<void *>(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<stru_iec_sig> &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<stru_iec_sig> &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<void *>(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<stru_iec_sig> &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<stru_iec_sig> &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<stru_iec_sig> &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;
}