# 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)
