chore: update build system and docs for new modules
- release/src/public/makefile: 添加 libxml/libcmd/libdatacenter 到 SUBDIRS - SPEC.md: 补全 libdatacenter §11 完整功能规格(300+ 行) - docs/README.md: 更新模块索引和依赖关系图 - 10/10 模块 x86 全量编译通过
This commit is contained in:
parent
f56ede7316
commit
9d12019961
394
SPEC.md
394
SPEC.md
|
|
@ -399,58 +399,362 @@ comm_send → 投递到对应 fd
|
||||||
|
|
||||||
## 11. libdatacenter 自研模块详细功能
|
## 11. libdatacenter 自研模块详细功能
|
||||||
|
|
||||||
### 功能点(来自 RTU 原工程 myDatacenter.h + datacenter/*.cpp 分析)
|
> 基于 RTU 原工程 libdatacenter v1 与 libdatacenter_2 完整源码分析。
|
||||||
|
> 新工程采用纯 C 接口(`extern "C"`) + C++ 内部实现,参数文件读写通过钩子解耦。
|
||||||
|
|
||||||
#### 11.1 信号注册(5 种信号类型)
|
### 11.0 模块架构与设计思想
|
||||||
| 序号 | 函数 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| D01 | `dc_signal_out(saddr, desc, data_type, p_data)` | 注册输出信号(遥测/遥信) |
|
|
||||||
| D02 | `dc_signal_out_with_callback(...)` | 输出信号+变化回调 |
|
|
||||||
| D03 | `dc_signal_in(saddr, desc, link_saddr, p_data)` | 注册输入信号(关联输出信号) |
|
|
||||||
| D04 | `dc_signal_in_with_callback(...)` | 输入信号+变化回调 |
|
|
||||||
| D05 | `dc_signal_ao(saddr, desc, data_type, ctrl_type, p_data, cb, mod)` | 注册模拟输出(遥控) |
|
|
||||||
| D06 | `dc_signal_param(saddr, desc, data_type, ctrl_type, p_data, num, cb, mod)` | 注册参数(定值) |
|
|
||||||
| D07 | `dc_signal_yk(saddr, desc, data_type, ctrl_type, p_data, cb, mod)` | 注册遥控信号 |
|
|
||||||
|
|
||||||
#### 11.2 信号控制
|
```
|
||||||
| 序号 | 函数 | 说明 |
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
|------|------|------|
|
│ 应用层(协议栈/Web/主程序) │
|
||||||
| D08 | `dc_signal_ao_set_val(saddr, step, ctrl, p_data, mod)` | 设置 AO 值(SBO/直接) |
|
│ 调用 dc_xxx_register / dc_xxx_set_val / dc_run_100ms 等 │
|
||||||
| D09 | `dc_signal_param_set_val(saddr, step, ctrl, zone, p_data, mod)` | 设置定值(带区号) |
|
├──────────────────────────────────────────────────────────────┤
|
||||||
| D10 | `dc_signal_yk_set_status(saddr, step, ctrl, p_data, mod)` | 设置遥控状态 |
|
│ libdatacenter(纯 C 接口层) │
|
||||||
|
│ ┌──────────┬──────────┬──────────┬──────────┬────────────┐ │
|
||||||
|
│ │ out 信号 │ in 信号 │ yk 信号 │ ao 信号 │ param 信号 │ │
|
||||||
|
│ │ (遥测/ │ (关联 │ (遥控) │ (模拟 │ (定值/ │ │
|
||||||
|
│ │ 遥信) │ 输出) │ │ 输出) │ 参数) │ │
|
||||||
|
│ └──────────┴──────────┴──────────┴──────────┴────────────┘ │
|
||||||
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ 内部引擎:hash查找 / 值校验 / 脏标记 / 变化检测 / 回路阻断│ │
|
||||||
|
│ └──────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ┌──────────────┬──────────────┬────────────────────────────┐ │
|
||||||
|
│ │ 事件队列 │ 扰动队列 │ 故障队列 │ │
|
||||||
|
│ │ (SOE) │ (Disturb) │ (Fault) │ │
|
||||||
|
│ └──────────────┴──────────────┴────────────────────────────┘ │
|
||||||
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ 参数配置钩子(解析/保存/变更通知) │ │
|
||||||
|
│ │ 异步执行钩子(发起/结果/超时/取消) │ │
|
||||||
|
│ └──────────────────────────────────────────────────────────┘ │
|
||||||
|
├──────────────────────────────────────────────────────────────┤
|
||||||
|
│ 实现层(C++: unordered_map + XXH3_128bits 哈希 + mutex)│
|
||||||
|
└──────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
#### 11.3 信号查询
|
**核心约束**:
|
||||||
| 序号 | 函数 | 说明 |
|
- 信号唯一标识用 `saddr`(字符串,如 `"RPC:1:YC:1:val"`)
|
||||||
|------|------|------|
|
- 每个信号注册时绑定 `module_id`(模块标识字符串),用于回路阻断
|
||||||
| D11 | `dc_get_out_signal_info(saddr, desc, data_type, p_data)` | 查询输出信号信息 |
|
- out 信号值变更不是同步回调,而是**脏标记 + 100ms 延迟批量检测**(避免频繁回调)
|
||||||
| D12 | `dc_get_in_signal_info(...)` | 查询输入信号 |
|
- yk/ao/param 控制值变更才是**同步回调**(控制场景需要即时响应)
|
||||||
| D13 | `dc_get_ao_signal_info(...)` | 查询 AO 信号 |
|
- 参数定值支持多区(如运行区/检修区),每区独立存储
|
||||||
| D14 | `dc_get_param_signal_info(...)` | 查询参数信号 |
|
|
||||||
| D15 | `dc_get_yk_signal_info(...)` | 查询遥控信号 |
|
|
||||||
| D16 | `dc_get_signal_val(p_data, data_type)` | 信号值转字符串 |
|
|
||||||
| D17 | `dc_set_out_signal_val(saddr, set_data, mod)` | 设置输出信号值 |
|
|
||||||
| D18 | `dc_get_signal_count(type)` | 按类型统计信号数 |
|
|
||||||
|
|
||||||
#### 11.4 事件/扰动/故障队列
|
### 11.1 数据结构
|
||||||
| 序号 | 函数 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| D19 | `dc_event_queue_push(soe)` | SOE 事件入队 |
|
|
||||||
| D20 | `dc_event_register_queue_pop(cb)` | 注册事件消费回调 |
|
|
||||||
| D21 | `dc_disturb_dd_queue_push(dd)` | 扰动数据入队 |
|
|
||||||
| D22 | `dc_disturb_dd_register_queue_pop(cb)` | 注册扰动消费回调 |
|
|
||||||
| D23 | `dc_fault_queue_push(fault)` | 故障数据入队 |
|
|
||||||
| D24 | `dc_fault_register_queue_pop(cb)` | 注册故障消费回调 |
|
|
||||||
|
|
||||||
#### 11.5 控制步骤枚举
|
#### 11.1.1 控制枚举
|
||||||
```c
|
```c
|
||||||
SIGNAL_CTRL_STEP { READY, SELECT, DIRECT, CANCEL } // SBO 控制步骤
|
enum SIGNAL_CTRL_TYPE
|
||||||
SIGNAL_CTRL_TYPE { NONE, DIRECT_NORMAL, SBO_NORMAL } // 控制类型
|
{
|
||||||
|
NONE = 0, /* 无控制 */
|
||||||
|
DIRECT_NORMAL = 1, /* 直控(直接执行,无需选择-确认) */
|
||||||
|
SBO_NORMAL = 2, /* 选控(选择-确认两阶段,SBO: Select Before Operate) */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SIGNAL_CTRL_STEP
|
||||||
|
{
|
||||||
|
READY = 0, /* 就绪/空闲 */
|
||||||
|
SELECT = 1, /* 选择(SBO 第一步:锁住信号,暂存选择值) */
|
||||||
|
DIRECT = 2, /* 执行(SBO 第二步:确认后写入,或直控直接执行) */
|
||||||
|
CANCEL = 3, /* 取消(回退到 READY) */
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 源文件组成(15 个 .cpp 文件)
|
#### 11.1.2 控制上下文
|
||||||
|
```c
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t step : 2; /* 当前控制步骤 SIGNAL_CTRL_STEP */
|
||||||
|
uint8_t type : 2; /* 控制类型 SIGNAL_CTRL_TYPE */
|
||||||
|
uint8_t backup : 4; /* 备用 */
|
||||||
|
uint8_t data_type; /* 数据类型 */
|
||||||
|
void *p_data; /* 暂存数据指针(SELECT时保存选择值,DIRECT时用于校验) */
|
||||||
|
} stru_signal_ctrl;
|
||||||
```
|
```
|
||||||
datacenter.cpp dc_cfg_check.cpp dc_event.cpp
|
|
||||||
dc_param.cpp dc_signal.cpp dc_signal_compare.cpp
|
#### 11.1.3 信号参数元数据
|
||||||
dc_signal_core.cpp dc_signal_ctrl.cpp dc_signal_find.cpp
|
```c
|
||||||
dc_signal_query.cpp dc_signal_show.cpp dc_signal_util.cpp
|
typedef struct
|
||||||
|
{
|
||||||
|
float min; /* 最小值 */
|
||||||
|
float max; /* 最大值 */
|
||||||
|
float step; /* 步长 */
|
||||||
|
char unit[32]; /* 单位(如 "kV", "A", "Hz") */
|
||||||
|
} stru_signal_param;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 11.1.4 内部信号节点
|
||||||
|
```c
|
||||||
|
typedef struct stru_signal
|
||||||
|
{
|
||||||
|
uint32_t id; /* 全局唯一ID(递增分配,用于 id_index 数组索引) */
|
||||||
|
XXH128_hash_t hash; /* 128位哈希(saddr 的 XXH3_128bits) */
|
||||||
|
char saddr[128]; /* 短地址 */
|
||||||
|
char desc[256]; /* 描述 */
|
||||||
|
uint8_t data_type; /* 数据类型 */
|
||||||
|
|
||||||
|
/* 数据指针列表(out/in/yk/ao 为单元素,param 为多区数组) */
|
||||||
|
void **vec_p_data; /* 动态数组:当前数据指针 */
|
||||||
|
int vec_p_data_count; /* 数据指针个数 */
|
||||||
|
void *p_last_data; /* 上一次数据快照(out信号变更检测用) */
|
||||||
|
void **vec_p_default_data; /* 默认值指针(param 恢复出厂用) */
|
||||||
|
|
||||||
|
/* 链接关系 */
|
||||||
|
char link_saddr[128]; /* in 信号:链接的 out saddr */
|
||||||
|
char **link_saddrs; /* out 被哪些 in 链接 */
|
||||||
|
int link_count;
|
||||||
|
|
||||||
|
uint8_t ctrl_type; /* 控制类型 SIGNAL_CTRL_TYPE */
|
||||||
|
stru_signal_param param; /* 参数元数据(min/max/step/unit) */
|
||||||
|
|
||||||
|
/* 回调列表(每个 cb 绑定 module_id 用于回路阻断) */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char *module_id;
|
||||||
|
out_signal_change_cb out_cb; /* out 信号专用 */
|
||||||
|
signal_change_cb ctrl_cb; /* yk/ao/param 专用 */
|
||||||
|
} cb_list[16];
|
||||||
|
int cb_count;
|
||||||
|
|
||||||
|
char last_caller_module[64]; /* 最后修改本信号的模块ID(回路阻断) */
|
||||||
|
} stru_signal;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 11.1.5 信号存储架构
|
||||||
|
```c
|
||||||
|
/* 每种信号类型一个独立的 map(saddr→signal*)+ id数组 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_mutex_t mtx;
|
||||||
|
uint32_t signal_id; /* 自增ID分配器 */
|
||||||
|
void *map_signals; /* C++ unordered_multimap<XXH128, signal*> */
|
||||||
|
stru_signal **id_index; /* id→指针 数组(支持按ID遍历) */
|
||||||
|
int id_index_cap;
|
||||||
|
} stru_signal_map;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
stru_signal_map signal_out;
|
||||||
|
stru_signal_map signal_in;
|
||||||
|
stru_signal_map signal_yk;
|
||||||
|
stru_signal_map signal_ao;
|
||||||
|
stru_signal_map signal_param;
|
||||||
|
} stru_datacenter;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.2 模块生命周期与周期性函数
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D00a | `dc_init(path)` | 初始化:解析参数配置文件(param.xml→self_param.xml),注册配置中的信号 |
|
||||||
|
| D00b | `dc_run_100ms()` | 每100ms:① out信号变化检测+批量触发回调 ② 事件/扰动/故障队列弹出消费 |
|
||||||
|
| D00c | `dc_run_1000ms()` | 每1000ms:检测参数变更标志,有变更则写 self_param.xml |
|
||||||
|
|
||||||
|
### 11.3 信号注册(5 种类型,均带 module_id)
|
||||||
|
|
||||||
|
**关键设计**:所有注册函数必须传入 `module_id` 字符串,用于回路阻断——当模块 A 修改信号值时,A 自身的回调不会被触发,只通知其他模块。
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D01 | `dc_signal_out(saddr, desc, data_type, p_data, module_id)` | 注册输出信号(遥测/遥信) |
|
||||||
|
| D02 | `dc_signal_out_with_callback(saddr, desc, data_type, p_data, cb, module_id)` | 注册输出信号+变化回调(延迟触发,非同步) |
|
||||||
|
| D03 | `dc_signal_out_link_with_callback(saddr, pp_data, cb, module_id)` | 链接已有 out 信号,获取数据指针并注册回调 |
|
||||||
|
| D04 | `dc_signal_in(saddr, desc, link_saddr, pp_data, module_id)` | 注册输入信号,自动关联输出信号的数据指针 |
|
||||||
|
| D05 | `dc_signal_in_with_callback(saddr, desc, link_saddr, pp_data, cb, module_id)` | 输入信号+回调(回调挂在被链接的out上) |
|
||||||
|
| D06 | `dc_signal_ao(saddr, desc, data_type, ctrl_type, p_data, cb, module_id)` | 注册模拟输出信号 |
|
||||||
|
| D07 | `dc_signal_ao_link_with_callback(saddr, pp_data, cb, module_id)` | 链接已有 ao 信号 |
|
||||||
|
| D08 | `dc_signal_param(saddr, desc, data_type, ctrl_type, pp_data, num, cb, module_id)` | 注册定值参数信号,num为定值区数 |
|
||||||
|
| D09 | `dc_signal_param_link_with_callback(saddr, pp_data, num, cb, module_id)` | 链接已有 param 信号 |
|
||||||
|
| D10 | `dc_signal_yk(saddr, desc, data_type, ctrl_type, p_data, cb, module_id)` | 注册遥控信号 |
|
||||||
|
| D11 | `dc_signal_yk_link_with_callback(saddr, pp_data, cb, module_id)` | 链接已有 yk 信号 |
|
||||||
|
|
||||||
|
**注册流程**(以 out 为例):
|
||||||
|
```
|
||||||
|
dc_signal_out(saddr, desc, data_type, p_data, module_id)
|
||||||
|
→ 检查 saddr 是否已存在(重复注册报错)
|
||||||
|
→ 计算 XXH3_128bits(saddr)
|
||||||
|
→ 分配 p_last_data(保存旧值快照,用于变更检测)
|
||||||
|
→ 插入 g_datacenter.signal_out
|
||||||
|
→ dc_set_param_cfg_change(true) /* ao/param 注册需标记配置变更 */
|
||||||
|
```
|
||||||
|
|
||||||
|
**in 信号关联逻辑**:
|
||||||
|
```
|
||||||
|
dc_signal_in(saddr, desc, link_saddr, pp_data)
|
||||||
|
→ 查找 link_saddr 对应的 out 信号
|
||||||
|
→ (*pp_data) = out信号的 vec_p_data[0](共享同一数据指针)
|
||||||
|
→ 在 out 信号的 link_saddrs 中追加 in 的 saddr
|
||||||
|
→ signal.data_type = out.data_type(数据类型跟随 out)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.4 信号控制(含 SBO 流程 + 值校验 + 回路阻断)
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D12 | `dc_signal_ao_set_val(saddr, step, ctrl, p_data, module_id)` | 设置 AO 值(带 SBO 流程控制+值校验) |
|
||||||
|
| D13 | `dc_signal_ao_set_val_without_check(saddr, data_type, p_data, module_id)` | 设置 AO 值(跳过校验,用于初始化恢复) |
|
||||||
|
| D14 | `dc_signal_param_set_val(saddr, step, ctrl, zone, p_data, module_id)` | 设置定值(指定区号,带校验) |
|
||||||
|
| D15 | `dc_signal_param_set_val_without_check(saddr, data_type, zone, p_data, module_id)` | 设置定值(跳过校验) |
|
||||||
|
| D16 | `dc_signal_yk_set_status(saddr, step, ctrl, p_data, module_id)` | 设置遥控状态 |
|
||||||
|
|
||||||
|
**SBO 控制流程**:
|
||||||
|
```
|
||||||
|
─── READY ──→ SELECT(锁住信号,暂存选择值到 ctrl.p_data)
|
||||||
|
│ │
|
||||||
|
│ ├──→ CANCEL(回退 READY,ctrl.step = READY)
|
||||||
|
│ │
|
||||||
|
│ └──→ DIRECT(校验值==选择值 → 写入 vec_p_data → ctrl.step=READY)
|
||||||
|
│
|
||||||
|
└──→ DIRECT(直控模式:直接写入,无需 SELECT)
|
||||||
|
```
|
||||||
|
|
||||||
|
**值校验链**(以 `dc_check_val_valid` 为例):
|
||||||
|
1. 检查 zone 是否越界
|
||||||
|
2. 检查新旧值是否变化(无变化→拒绝)
|
||||||
|
3. 根据 data_type 检查值是否在 param.min/max范围内
|
||||||
|
4. 所有类型(bool/int/float/double/IP/MAC/str)全覆盖
|
||||||
|
|
||||||
|
**回路阻断机制**(核心设计):
|
||||||
|
```cpp
|
||||||
|
// 回调通知时,跳过发起修改的模块自身
|
||||||
|
for(auto &entry : p_signal->cb_list)
|
||||||
|
{
|
||||||
|
if (entry.first == module_id) continue; // 回路阻断:不发给自己
|
||||||
|
entry.second(saddr, step, data_type, zone, p_data);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**out 信号变化的延迟回调**(与 ao/yk/param 不同):
|
||||||
|
```
|
||||||
|
dc_set_out_signal_val(saddr, set_data, module_id)
|
||||||
|
→ p_signal->last_caller_module = module_id /* 记录调用方 */
|
||||||
|
→ dc_mark_signal_dirty(p_signal) /* 标记脏,不立即回调 */
|
||||||
|
→ 写入新值到 vec_p_data[0]
|
||||||
|
|
||||||
|
dc_run_100ms()
|
||||||
|
→ dc_signal_out_change_check()
|
||||||
|
→ 遍历 g_dirty_out_signals
|
||||||
|
→ 比较 vec_p_data[0] vs p_last_data
|
||||||
|
→ 有变化→通知cb_list(跳过 last_caller_module)
|
||||||
|
→ 更新 p_last_data
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.5 信号查询
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D17 | `dc_get_out_signal_info(saddr, desc, desc_len, data_type, pp_data)` | 查询 out 信号 |
|
||||||
|
| D18 | `dc_get_in_signal_info(saddr, desc, desc_len, data_type, pp_data)` | 查询 in 信号 |
|
||||||
|
| D19 | `dc_get_ao_signal_info(saddr, desc, desc_len, data_type, p_param, ctrl_type, pp_data)` | 查询 ao 信号(含参数元数据) |
|
||||||
|
| D20 | `dc_get_param_signal_info(saddr, desc, desc_len, data_type, p_param, ctrl_type, pp_vec_data, p_count)` | 查询 param 信号(多区数据指针列表) |
|
||||||
|
| D21 | `dc_get_yk_signal_info(saddr, desc, desc_len, data_type, ctrl_type, pp_data)` | 查询 yk 信号 |
|
||||||
|
| D22 | `dc_get_signal_val(p_data, data_type, buf, buf_len)` | 信号值→字符串(纯 C 接口) |
|
||||||
|
| D23 | `dc_set_out_signal_val(saddr, set_data, module_id)` | 设置 out 信号值(脏标记+延迟回调) |
|
||||||
|
| D24 | `dc_get_signal_count(type_str)` | 按类型统计信号数("out"/"in"/"yk"/"ao"/"param") |
|
||||||
|
| D25 | `dc_get_signal_info_by_id(type_str, id, saddr, saddr_len, desc, desc_len, data_type_str, type_str_len, ctrl_type, link_str, link_len)` | 按ID查询信号基本信息(供前端遍历) |
|
||||||
|
|
||||||
|
### 11.6 事件/扰动/故障队列
|
||||||
|
|
||||||
|
| 序号 | 类型 | 入队函数 | 注册消费回调 | 数据内容 |
|
||||||
|
|------|------|----------|-------------|----------|
|
||||||
|
| D26 | SOE 事件 | `dc_event_queue_push(p_soe)` | `dc_event_register_queue_pop(cb)` | saddr + status + 时间戳(sec,ms) |
|
||||||
|
| D27 | 扰动数据 | `dc_disturb_dd_queue_push(p_dd)` | `dc_disturb_dd_register_queue_pop(cb)` | saddr + fVal + 时间戳(sec,ms) |
|
||||||
|
| D28 | 故障录波 | `dc_fault_queue_push(p_fault)` | `dc_fault_register_queue_pop(cb)` | vec_soe + vec_disturb_yc |
|
||||||
|
|
||||||
|
**队列消费机制**:
|
||||||
|
- 支持多个消费者(`vector<dc_queue_pop_cb>`)
|
||||||
|
- `dc_run_100ms()` 中批量弹出消费,加锁 swap 减少锁持有时间
|
||||||
|
- push 时自动补时间戳(sec==0 && ms==0 时自动获取当前时间)
|
||||||
|
|
||||||
|
### 11.7 参数配置文件解析与保存(解耦钩子设计)
|
||||||
|
|
||||||
|
**设计原则**:参数文件读写通过钩子函数注册,datacenter 不直接依赖 tinyxml2。
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* @brief 参数配置文件提供者(由应用层注册)
|
||||||
|
* @param path 输出:返回配置文件的路径
|
||||||
|
* @param len 路径缓冲区大小
|
||||||
|
* @param buf 输出:返回配置文件的内容缓冲区
|
||||||
|
* @param size 输出:返回内容大小
|
||||||
|
* @return 0 成功,-1 没找到/不支持
|
||||||
|
*/
|
||||||
|
typedef int (*dc_param_cfg_read_cb)(char *path, int len, char **buf, int *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 参数配置保存回调(由应用层注册)
|
||||||
|
* @param path 文件路径
|
||||||
|
* @param buf 要保存的内容
|
||||||
|
* @param size 内容大小
|
||||||
|
* @return 0 成功,-1 失败
|
||||||
|
*/
|
||||||
|
typedef int (*dc_param_cfg_save_cb)(const char *path, const char *buf, int size);
|
||||||
|
```
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D29 | `dc_param_cfg_register_read_cb(cb)` | 注册参数配置读取回调 |
|
||||||
|
| D30 | `dc_param_cfg_register_save_cb(cb)` | 注册参数配置保存回调 |
|
||||||
|
| D31 | `dc_param_cfg_changed()` | 查询配置是否有未保存变更(返回 0/1) |
|
||||||
|
|
||||||
|
**配置文件语义**(由钩子实现方保证,datacenter 不解析格式):
|
||||||
|
- `param.xml`:参数模板(元数据:saddr, desc, type, min, max, step, unit, default, value)
|
||||||
|
- `self_param.xml`:用户运行时值(仅 saddr + value,持久化动态修改)
|
||||||
|
- 初始化时:先读 param.xml 的元数据注册信号 → 再读 self_param.xml 覆盖运行时值
|
||||||
|
- 配置变更时:dc_param_cfg_check() 检测到变更标志 → 调 save_cb 写入 self_param.xml
|
||||||
|
|
||||||
|
### 11.8 类型系统工具函数
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D32 | `dc_get_data_type_str_by_id(data_type)` | DATA_TYPE_U8→"uint8_t" |
|
||||||
|
| D33 | `dc_get_data_type_id_by_str("float")` | "float"→DATA_TYPE_F32 |
|
||||||
|
| D34 | `dc_get_data_type_len(data_type)` | 获取字节长度 |
|
||||||
|
| D35 | `dc_create_data_ptr_by_type(data_type)` | 根据类型 new 并清零 |
|
||||||
|
| D36 | `dc_delete_signal_data(p_data, data_type)` | 根据类型 delete |
|
||||||
|
| D37 | `dc_set_signal_val_from_str(p_data, data_type, str)` | 字符串→值("3.14"→3.14f) |
|
||||||
|
| D38 | `dc_set_signal_val(p_data, data_type, set_data)` | 内存拷贝赋值 |
|
||||||
|
| D39 | `dc_data_compare(data_type, p_data1, p_data2)` | 类型感知的值比较 |
|
||||||
|
|
||||||
|
### 11.9 调试与导出
|
||||||
|
|
||||||
|
| 序号 | 函数 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| D40 | `dc_save_out_signals_xml(path)` | 导出所有已注册 out 信号到 XML(供前端 PLC 配置读取) |
|
||||||
|
|
||||||
|
### 11.10 源文件对照表
|
||||||
|
|
||||||
|
| RTU原工程文件 | 新工程文件 | 说明 |
|
||||||
|
|---------------|-----------|------|
|
||||||
|
| `inc/dc_signal.h` | `inc/myDatacenter.h` | 合并为单头文件(纯C接口) |
|
||||||
|
| `inc/dc_event.h` | ↑ | 合并 |
|
||||||
|
| `inc/dc_param.h` | ↑ | 合并 |
|
||||||
|
| `src/dc_signal.cpp` | `src/myDatacenter.cpp` | 信号注册主体 |
|
||||||
|
| `src/dc_signal_core.cpp` | ↑ | map操作+脏标记 |
|
||||||
|
| `src/dc_signal_ctrl.cpp` | ↑ | 值校验+控制流程 |
|
||||||
|
| `src/dc_signal_query.cpp` | ↑ | 信号查询+out变化检测 |
|
||||||
|
| `src/dc_signal_compare.cpp` | ↑ | 值比较+元数据应用 |
|
||||||
|
| `src/dc_signal_find.cpp` | ↑ | hash查找 |
|
||||||
|
| `src/dc_signal_util.cpp` | ↑ | 类型工具函数 |
|
||||||
|
| `src/dc_signal_show.cpp` | ↑ | 信号展示+cmd命令(可选) |
|
||||||
|
| `src/datacenter.cpp` | ↑ | 初始化+生命周期 |
|
||||||
|
| `src/dc_param.cpp` | `src/dc_param_hook.cpp` | 参数配置文件钩子注册 |
|
||||||
|
| `src/dc_cfg_check.cpp` | ↑ | self_param.xml变更检测+保存 |
|
||||||
|
| `src/dc_event.cpp` | `src/dc_event.cpp` | 事件队列 |
|
||||||
|
| `src/dc_signal_internal.h` | `src/dc_signal_internal.h` | 内部共享声明 |
|
||||||
|
|
||||||
|
### 11.11 新旧工程差异对比
|
||||||
|
|
||||||
|
| 维度 | RTU 原工程 v1 | RTU 原工程 v2 | 新工程 libdatacenter |
|
||||||
|
|------|-------------|-------------|-------------------|
|
||||||
|
| 接口语言 | C++ (std::string) | 纯C (const char*) | 纯C (extern "C") |
|
||||||
|
| 哈希查找 | XXH128 multimap | XXH128 multimap | unordered_map + XXH3_128bits hasher(O(1),复用 libmy_xxhash CBB) |
|
||||||
|
| 参数文件 | tinyxml2 直接解析 | 同上 | 回调钩子解耦 |
|
||||||
|
| 异步执行 | 无 | 有(_exec_async) | 预留接口+钩子 |
|
||||||
|
| 回路阻断 | ✓ | ✓ | ✓ |
|
||||||
|
| module_id | std::string | const char* | const char* |
|
||||||
|
| 控制校验 | ✓ | ✓ | ✓ |
|
||||||
|
| SBO流程 | ✓ | ✓ | ✓ |
|
||||||
|
| 多区定值 | ✓ | ✓ | ✓ |
|
||||||
|
| 变更检测 | 脏标记+100ms | 同v1 | 同v1 |
|
||||||
|
| 调试命令 | cmd_dc | 无 | 预留 |
|
||||||
|
| 错误码 | -1/0 | enum dc_error_t | enum dc_error_t |
|
||||||
|
| 未实现 | — | — | 异步执行模型(预留)、tinyxml2绑定(钩子替代) |
|
||||||
|
|
|
||||||
|
|
@ -17,36 +17,50 @@
|
||||||
| libfunc | [API-libfunc.md](public/libfunc/API-libfunc.md) | 纯 C | 65 个基础工具函数 |
|
| libfunc | [API-libfunc.md](public/libfunc/API-libfunc.md) | 纯 C | 65 个基础工具函数 |
|
||||||
| libmd5 | [API-libmd5.md](public/libmd5/API-libmd5.md) | 纯 C | MD5 消息摘要 (RFC 1321) |
|
| libmd5 | [API-libmd5.md](public/libmd5/API-libmd5.md) | 纯 C | MD5 消息摘要 (RFC 1321) |
|
||||||
| libtask | [API-libtask.md](public/libtask/API-libtask.md) | 纯 C | 定时器 + 事件 + 消息队列 |
|
| libtask | [API-libtask.md](public/libtask/API-libtask.md) | 纯 C | 定时器 + 事件 + 消息队列 |
|
||||||
|
| libdatacenter | [API-libdatacenter.md](public/libdatacenter/API-libdatacenter.md) | C 接口+C++ 内部 | 信号数据中心(5种信号+事件队列) |
|
||||||
| libcJSON | [API-libcJSON.md](public/libcJSON/API-libcJSON.md) | 纯 C (开源库) | JSON 解析/生成 |
|
| libcJSON | [API-libcJSON.md](public/libcJSON/API-libcJSON.md) | 纯 C (开源库) | JSON 解析/生成 |
|
||||||
| libmy_xxhash | [API-libmy_xxhash.md](public/libmy_xxhash/API-libmy_xxhash.md) | 纯 C (开源库) | xxHash 快速哈希 |
|
| libmy_xxhash | [API-libmy_xxhash.md](public/libmy_xxhash/API-libmy_xxhash.md) | 纯 C (开源库) | xxHash 快速哈希 |
|
||||||
|
| libxml | [API-libxml.md](public/libxml/API-libxml.md) | C 接口+C++ 内部 | XML 解析(C接口包裹 tinyxml2) |
|
||||||
|
| libcmd | [API-libcmd.md](public/libcmd/API-libcmd.md) | C 接口+C++ 内部 | 命令注册/补全 + 内置 linenoise |
|
||||||
|
|
||||||
### 模块依赖关系图
|
### 模块依赖关系图
|
||||||
|
|
||||||
```
|
```
|
||||||
┌──────────┐
|
┌──────────┐
|
||||||
│ myBase.h │ (颜色/大小端/类型常量)
|
│ myBase.h │ (颜色/大小端/类型常量)
|
||||||
└────┬─────┘
|
└────┬─────┘
|
||||||
┌──────────────┼──────────────┐
|
┌──────────────┼──────────────┐
|
||||||
▼ ▼ ▼
|
▼ ▼ ▼
|
||||||
┌─────────┐ ┌─────────┐ ┌──────────┐
|
┌─────────┐ ┌─────────┐ ┌──────────┐
|
||||||
│ liblist │ │ libfunc │ │ libmd5 │
|
│ liblist │ │ libfunc │ │ libmd5 │
|
||||||
│ (链表) │ │ (65函数)│ │ (MD5) │
|
│ (链表) │ │ (65函数)│ │ (MD5) │
|
||||||
└────┬────┘ └────┬────┘ └──────────┘
|
└────┬────┘ └────┬────┘ └──────────┘
|
||||||
│ │
|
│ │
|
||||||
▼ ▼
|
▼ ▼
|
||||||
┌─────────────────────────┐
|
┌─────────────────────────┐
|
||||||
│ liblog │ (异步日志,依赖
|
│ liblog │ (异步日志)
|
||||||
│ (消息池+批量+文件轮转) │ liblist + libfunc)
|
│ (消息池+批量+文件轮转) │
|
||||||
└─────────────────────────┘
|
└─────────────────────────┘
|
||||||
|
|
||||||
┌──────────┐ ┌──────────────┐
|
┌──────────┐ ┌──────────────┐
|
||||||
│ libcJSON │ │ libmy_xxhash │ (开源库,直接使用)
|
│ libcJSON │ │ libmy_xxhash │ (开源库)
|
||||||
└──────────┘ └──────────────┘
|
└──────────┘ └──────┬───────┘
|
||||||
|
│
|
||||||
┌────────────────────────────────┐
|
┌─────────────────────┼─────────────────────┐
|
||||||
│ libtask │ (事件/定时器/消息队列)
|
│ ▼ │
|
||||||
│ (timerfd + epoll + pthread) │
|
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
|
||||||
└────────────────────────────────┘
|
│ │ libtask │ │ libxml │ │ libcmd │ │ (P2库提前实现
|
||||||
|
│ │ (事件/ │ │ (C接口+ │ │ (命令 │ │ 供datacenter
|
||||||
|
│ │ 定时器) │ │ tinyxml2)│ │ 框架) │ │ 依赖)
|
||||||
|
│ └──────────┘ └────┬─────┘ └────┬────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ ┌─────────────────────────────┐ │
|
||||||
|
│ │ libdatacenter │ │
|
||||||
|
│ │ (信号数据中心 5种信号类型) │ │
|
||||||
|
│ │ 依赖: libxml + libcmd │ │
|
||||||
|
│ │ + libmy_xxhash │ │
|
||||||
|
└──────────┴─────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
### 构建与编译
|
### 构建与编译
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SUBDIRS := ./liblist ./libfunc ./liblog ./libmd5 ./libcJSON ./libmy_xxhash ./libtask
|
SUBDIRS := ./liblist ./libfunc ./liblog ./libmd5 ./libcJSON ./libmy_xxhash ./libtask ./libxml ./libcmd ./libdatacenter
|
||||||
define make_subdir
|
define make_subdir
|
||||||
@for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
|
@for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
|
||||||
endef
|
endef
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue