API-libiec — IEC 60870-5-104 服务端模块
版本: v1.0
日期: 2026-07-10
来源: 基于原工程 12 个 IEC 子文件聚合重构
状态: ✅ 已实现,x86 + ARM 双平台编译通过(零警告)
1. 模块概述
libiec 是 RTU 通讯装置的 IEC 60870-5-104 服务端(从站)模块,作为 X-Macro 框架的线程模块运行。通过 com_router 的 bind_app="iec" 机制接收 TCP :2404 端口的主站连接数据,底层协议栈复用 lib60870 自研库。
| 功能 |
说明 |
| IEC-104 从站协议 |
支持 CS101 / CS104 两种链路类型 |
| 并发连接管理 |
最多 3 路并发主站连接 (MAX_IEC_NUM=3),槽位复用 |
| 超时回收 |
链路 600s 无活动自动回收 slot |
| XML 点表解析 |
从 config/IEC60870/iec1014.xml 解析 St/Mx/Co/Dd/Ao/Param 六类信号 |
| 数据中心桥接 |
信号变更回调自动写入 SOE/扰动遥测/故障/电度环形缓冲区 |
| 多主站分发 |
环形缓冲区多出指针 (out_ptrs),每路连接独立消费位置 |
| MQ 桥接 |
COM_TO_IEC / IEC_TO_COM 双队列,通过 com_router 转发 |
| 26 个 CS10x 回调 |
完整实现总召、遥测、遥控、电度、参数、定值、文件传输、扰动 |
架构
com_router (bind_app=iec)
│
▼ MQ_COM_TO_IEC
iec104_data_rx()
│
▼
CS10x_104Init / CS10x_DoRecv
│
▼ ┌──────────────────────────────────────────┐
│ │ 26 个回调 (protocol_register_callbacks) │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ │总召/遥信 │ │遥测/电度 │ │遥控/参数 │ │
│ │ │定值/对时 │ │故障/扰动 │ │文件传输 │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │
│ └──────────────────────────────────────────┘
│
▼ MQ_IEC_TO_COM → com_router → TCP → 主站
与原工程对比
| 维度 |
原工程 (12 文件) |
重构后 (3 文件) |
| 文件数 |
12 |
3 (~75% 减少) |
| 代码行数 |
~2500+ |
1474 |
| 槽位管理 |
分散在多文件 |
统一 g_iec[MAX_IEC_NUM] |
| 环形缓冲区 |
5 个独立结构体 |
4 个模板化 ring_*_t (sem + out_ptrs) |
| 回调注册 |
分散初始化 |
protocol_register_callbacks() 集中 |
| 命令支持 |
无 |
CMD_REGISTER_C 测试命令 |
| EV_STOP |
无 |
支持优雅退出 |
2. 文件结构
src/system/libiec/
├── inc/
│ ├── iec104.h # 公共头: stru_iec, iec_soe_info_t, iec_yc_info_t, API 声明
│ └── iec104_cfg.h # 点表配置: stru_iec_sig, stru_iec_cfg
└── src/
├── iec104.cpp # CS10x 初始化 + slot 管理 + 26 回调 + 收发桥接 (1252行)
├── iec104_cfg.cpp # XML 点表解析 (148行)
└── iec104_point.cpp # 数据中心桥接 — 信号变更回调 → 环形缓冲区 (290行)
release/
└── {x86,arm}/lib/
└── libiec.a # 编译产物
3. 核心数据结构
3.1 槽位结构 (stru_iec)
每路并发连接占用一个槽位,全局数组 g_iec[MAX_IEC_NUM] (MAX_IEC_NUM=3):
| 字段 |
类型 |
说明 |
is_busy |
uint8_t |
槽位占用标志,0=空闲 |
iec_type |
CS10x_Type |
CS104_TYPE_S / CS101_TYPE_S |
interface |
uint32_t |
通道唯一标识 (ch_id<<16 | fd) |
tm_out |
uint32_t |
超时计数器 (ms),超过 600s 自动回收 |
rx[IEC_BUF_SIZE] |
uint8_t[1024] |
接收缓冲区 |
tx[IEC_BUF_SIZE] |
uint8_t[1024] |
发送缓冲区 |
pub[IEC_BUF_SIZE] |
uint8_t[1024] |
自主上传缓冲区 (总召/扰动) |
bak[IEC_BUF_SIZE] |
uint8_t[1024] |
备用缓冲区 |
cs10x |
CS10x |
lib60870 协议栈句柄 |
3.2 环形缓冲区
4 个环形缓冲区均带独立信号量 (sem_t) 和多出指针 (out_ptrs),支持多主站并发消费:
| 缓冲区 |
容量 |
记录类型 |
用途 |
g_soe_ring |
300 |
SOE (时标+状态) |
遥信变位事件 |
g_yc_ring |
200 |
扰动遥测 (idx+val) |
遥测越限扰动 |
g_fault_ring |
200 |
故障 (SOE+遥测) |
故障录波事件 |
g_dd_ring |
50 |
电度 (CP56Time2a+val) |
电度累计 |
3.3 点表配置 (stru_iec_cfg)
从 config/IEC60870/iec1014.xml 解析,6 类信号向量:
| 向量 |
信号类型 |
IOA 起始 |
默认类型 |
vec_st |
遥信 (St) |
0x0001 |
DATA_TYPE_U8 |
vec_mx |
遥测 (Mx) |
0x4001 |
DATA_TYPE_F32 |
vec_co |
遥控 (Co) |
— |
DATA_TYPE_U8 |
vec_dd |
电度 (Dd) |
0x6401 |
DATA_TYPE_F32 |
vec_ao |
参数 (Ao) |
— |
无默认 (XML 必须指定) |
vec_param |
定值 (Param) |
— |
无默认 (XML 必须指定) |
每条信号 (stru_iec_sig) 含: link (数据中心路径), desc (描述), inf (IOA), type (数据类型), invert (遥信取反), factor/offset (遥测系数偏移), p_data (数据指针)。
4. API 参考
4.1 公共头 API (iec104.h)
| 函数 |
功能 |
参数 |
返回值 |
iec104_get_by_interface() |
按 interface 查找 IEC 实例 |
uint32_t interface |
stru_iec * 或 NULL |
iec104_data_rx() |
MQ 数据入口 (从 com_router 接收) |
uint8_t *msg |
0=成功, -1=失败 |
iec104_task() |
10ms 定时器处理 |
uint16_t gap (恒10) |
void |
4.2 线程入口
| 函数 |
功能 |
说明 |
app_iec_init1() |
第一阶段初始化 |
解析 XML 点表 (iec_cfg_parse) |
app_iec_init2() |
第二阶段初始化 |
注册数据中心回调 (iec104_point_init) |
app_iec() |
主循环 |
while(1) 收 MQ_COM_TO_IEC + 10ms 定时处理 |
4.3 点表 API (iec104_cfg.h)
| 函数 |
功能 |
参数 |
返回值 |
iec_cfg_ptr_get() |
获取全局配置指针 |
void |
stru_iec_cfg * |
iec_cfg_parse() |
解析 XML 点表文件 |
const char *xml_path |
0=成功, -1=失败 |
4.4 环形缓冲区回调 (iec104_point.cpp → iec104.cpp)
| 函数 |
功能 |
cb_soe_write() |
写入 SOE 记录 (遥信变位) |
cb_yc_disturb_write() |
写入扰动遥测记录 |
cb_dd_disturb_write() |
写入电度记录 |
cb_fault_write() |
写入故障事件记录 |
5. CS10x 回调清单 (26 个)
5.1 时间 & 初始化 (4)
| 回调 |
功能 |
CS10x 注册 |
cb_get_time |
获取当前时间 (CP56Time2a) |
时钟回调 |
cb_set_time |
设置系统时间 (对时) |
时钟回调 |
cb_104init_callback |
接收 CS104 初始化完成通知 |
104 专用 |
cb_tm_send_result |
对时报文发送结果通知 |
COI 回调 |
5.2 总召 (3)
| 回调 |
功能 |
cb_st |
遥信总召 — 遍历 vec_st 打包 SQ=1 报文 |
cb_mx |
遥测总召 — 遍历 vec_mx 打包浮点报文 |
cb_dd |
电度总召 — 遍历 vec_dd 打包 CP56Time2a 报文 |
5.3 遥控 (5)
| 回调 |
功能 |
cb_yk_set |
遥控选择/执行 — 遍历 vec_co 查找 IOA, 写入 datacenter |
cb_yk_confirm_func |
遥控确认回调 |
cb_yk_termination_func |
遥控终止回调 |
cb_yk_order_func |
遥控命令通知 |
cb_yx_over_time_confirm_func |
遥信超时确认 |
5.4 参数 & 定值 (4)
| 回调 |
功能 |
cb_param_get_func |
参数 (Ao) 读取 — 遍历 vec_ao |
cb_param_set_func |
参数 (Ao) 设置 — 写 datacenter |
cb_offset_get_func |
定值 (Param) 读取 — 遍历 vec_param |
cb_offset_set_func |
定值 (Param) 设置 — 写 datacenter |
5.5 扰动 & 故障 (5)
| 回调 |
功能 |
cb_dir_num |
目录数量查询 |
cb_soe_ring_get_one |
从 SOE 环形缓冲区读取一条 |
cb_yc_ring_get_one |
从扰动遥测环形缓冲区读取一条 |
cb_fault_ring_get_one |
从故障环形缓冲区读取一条 |
cb_dd_ring_get_one |
从电度环形缓冲区读取一条 |
5.6 文件传输 (5)
| 回调 |
功能 |
cb_file_read |
文件读回调 |
cb_file_write |
文件写回调 |
cb_file_wr_finish |
文件写入完成回调 |
cb_file_call_func |
文件服务调用 |
cb_dir_num |
目录服务 (与扰动共用) |
6. MQ 消息流
主站 → TCP :2404 → com_router (bind_app=iec)
→ MQ_COM_TO_IEC
→ app_iec() 主循环收
→ CS10x_DoRecv()
→ 对应回调 → datacenter
datacenter 信号变更 (St/Mx)
→ on_st_change / on_mx_change 回调
→ cb_soe_write / cb_yc_disturb_write → 环形缓冲区
总召/扰动触发:
→ iec104_data_tx() → MQ_IEC_TO_COM
→ com_router → TCP → 主站
7. 配置依赖
| 配置文件 |
用途 |
config/CHANNEL/channel_cfg.json |
TCP :2404 配置 bind_app="iec" |
config/IEC60870/iec1014.xml |
IEC 点表 (St/Mx/Co/Dd/Ao/Param) |
config/SYSTEM/app_config.json |
X-Macro 框架启停控制 |
8. 已知限制
- 扰动文件 (COMTRADE) 上传/下载: 回调已注册但无实际文件系统实现
- 遥控执行超时: 使用固定 30s 超时,不支持配置
- 缓冲区满: 环形缓冲写满后丢弃最早记录 (无 overflow 告警回调)
- 只有 IEC-104 从站模式,未实现主站模式 (CS10x_Type 预留 CS104_TYPE_M/CS101_TYPE_M)