# libiec61850_MMS服务端API开发手册
**日期**: 2026-06-12
**基于源码**: `src/system/libiec61850s/`, `src/protocol/libmms_s/inc/`
---
## 1. 模块层次
```
┌─────────────────────────────┐
│ iec61850s (系统层) │ ← 本文档描述
│ - XML配置解析、信号注册 │
│ - 回调桥接到 datacenter │
├─────────────────────────────┤
│ libmms_s (协议层) │ ← 底层 API,详见《libmms_s模块分析》
│ - ICD解析、模型创建、IedServer│
│ - 控制/定值/文件服务 │
└─────────────────────────────┘
```
---
## 2. 核心概念
### 2.1 sAddr(信号地址)
sAddr 是 IEC 61850 标准中的短地址字段,在 ICD 文件中定义。RTU 用它作为 datacenter 中信号的唯一标识,打通 "MMS 数据属性 ↔ datacenter 信号" 的映射。
### 2.2 信号类型
| 分类 | ICD FC | datacenter 表 | 说明 |
|------|--------|-------------|------|
| ST(状态) | ST | signal_out | 遥信/双点状态 |
| MX(测量) | MX | signal_out | 遥测/测量值 |
| CO(控制) | CO | signal_yk | 遥控输出 |
| AO(模拟输出) | 自定义 | signal_ao | 定值区号/SP定值 |
| Param(参数) | SG/SE | signal_param | 定值组参数(多区) |
---
## 3. 配置文件格式(mms_s.xml)
```xml
```
- `no`: 序号
- `link`: sAddr,对应 datacenter 中的信号地址和 ICD 中的 sAddr 字段
配置解析后存入 `stru_mms_cfg`,包含 `vec_st`, `vec_mx`, `vec_co`, `vec_ao`, `vec_param` 五个向量。
---
## 4. 初始化流程
### 4.1 两阶段初始化
```
app_iec61850s_init1:
1. 获取进程目录(通过 /proc/self/exe)
2. 解析 config/MMS/mms_s.xml → stru_mms_cfg(信号点表)
3. 设置调试开关: mms_s_dbg_switch(false)
4. 设置文件路径: mms_s_file_path_set(base_path)
5. 注册值更新回调: mms_s_value_update_register(&cb)
app_iec61850s_init2:
1. iec61850s_signals_init:
- iec61850s_st_signals_init:
dc_signal_out_link_with_callback → 获取 ST 信号指针并注册变更回调
回调: iec61850s_st_mx_change_callback → mms_s_value_update → 更新 MMS 模型值
- iec61850s_mx_signals_init: 同上(MX 信号)
- iec61850s_control_signals_init:
dc_get_yk_signal_info → 获取控制信号信息
mms_s_control_register → 向 libmms_s 注册控制回调
回调: iec61850s_control_callback → dc_signal_yk_set_status
- iec61850s_setting_signals_init:
dc_signal_ao_link_with_callback → 绑定 AO 信号
mms_s_setting_register → 注册 SP 定值回调
回调: iec61850s_setting_callback → dc_signal_ao_set_val
- iec61850s_param_signals_init:
dc_get_param_signal_info → 获取 Param 信号指针
mms_s_param_register → 注册定值组回调
回调: iec61850s_param_callback → dc_signal_param_set_val
2. 解析 ICD 文件: config/MMS/PCS.icd
3. 调用 mms_s_init(icd_path, 102) 启动 MMS 服务器
4. 绑定定值区信号: mms_s_bind_param_zone_signal(zone_saddr, iec61850s_sg_change_callback)
```
### 4.2 信号初始化详细流程
**ST/MX 信号**(单向:datacenter → MMS):
```
datacenter 信号值变化
→ iec61850s_st_mx_change_callback(saddr, type, p_data, p_last_data)
→ dc_get_signal_val(p_data, type) → 字符串值
→ mms_s_value_update(saddr, val) → 更新 MMS 模型 → 触发 RCB 报告
```
**控制信号**(双向:MMS 客户端 → datacenter):
```
远方 MMS 客户端发送控制命令
→ libmms_s control_handler → iec61850s_control_callback(control, state)
→ 判断 ctrl_model:
DIRECT: dc_signal_yk_set_status(DIRECT)
SBO: dc_signal_yk_set_status(SELECT) + dc_signal_yk_set_status(DIRECT)
STATUS_ONLY: 仅记录日志
```
**AO/SP 定值信号**(双向:MMS → datacenter):
```
远方客户端修改 SP 定值
→ libmms_s setting writeAccessHandler → iec61850s_setting_callback(setting, data)
→ dc_set_signal_val_from_str → 解析字符串
→ dc_signal_ao_set_val(SELECT+DIRECT or DIRECT only)
```
**Param 定值组信号**(双向,支持多区):
```
远方客户端 ConfirmEditSG
→ libmms_s confirmEditSG_callback → iec61850s_param_callback(param, data, zone)
→ dc_signal_param_set_val(zone, data)
```
---
## 5. 核心 API
### 5.1 信号注册(iec61850s 内部)
```cpp
int iec61850s_signals_init();
```
**功能**: 从 XML 配置初始化全部五类信号,注册各类回调到 libmms_s。在 `app_iec61850s_init2` 中调用。
### 5.2 值更新(libmms_s 提供)
```cpp
void mms_s_value_update_register(mms_s_value_update_cb *pp_cb);
int mms_s_value_update(const char *saddr, const char *value_str);
```
**功能**: 更新 MMS 模型中指定 sAddr 的 DA 值,自动更新时标和品质。
### 5.3 控制注册(libmms_s 提供)
```cpp
int mms_s_control_register(stru_mms_s_control *p_control, int count, mms_s_control_cb p_callback);
```
**功能**: 注册控制 DO 的回调处理函数。
`stru_mms_s_control`:
```c
typedef struct
{
stru_mms_s_signal_base base; // saddr, desc, type, ctrl_model
void *p_data; // 信号数据指针(指向 datacenter)
}stru_mms_s_control;
```
### 5.4 SP 定值注册(libmms_s 提供)
```cpp
int mms_s_setting_register(stru_mms_s_setting *p_setting, int count, mms_s_setting_cb p_callback);
```
**功能**: 注册 SP(fc=SP)定值的写入回调。
### 5.5 定值组注册(libmms_s 提供)
```cpp
int mms_s_param_register(stru_mms_s_param *p_param, int count, mms_s_param_cb p_callback);
```
**功能**: 注册定值组参数(SG/SE)的确认回调。
`stru_mms_s_param`:
```c
typedef struct
{
stru_mms_s_signal_base base; // saddr, desc, type, ctrl_model
void *p_data[MAX_ZONE]; // 各定值区的数据指针
uint8_t param_num; // 定值区数量
}stru_mms_s_param;
```
### 5.6 其他 libmms_s API
```cpp
int mms_s_init(const char *icd_path, int stack_size); // 启动 MMS 服务器
void mms_s_dbg_switch(bool on); // 调试开关
void mms_s_file_path_set(const char *base_path); // 文件路径
int mms_s_bind_param_zone_signal(const char *zone_saddr, mms_s_sg_change_cb cb); // 绑定定值区
struct _sIedModel_wrapper *mms_s_get_icd_ptr(); // 获取 IedModel
IedServer mms_s_get_ied_server_ptr(); // 获取 IedServer
```
---
## 6. 运行时流程
### 6.1 主线程循环
```cpp
void *app_iec61850s(void *arg):
while(1):
task_event_recv(p_event, EV_TIMER1 | EV_TIMER2 | EV_TIMER3, ...)
EV_TIMER1 (10ms): 空闲
EV_TIMER2 (100ms): 空闲
EV_TIMER3 (1000ms):
- check_sg_zone_change(): 检测定值区号变化,更新 MMS 模型
- p_app->run_cnt++: 运行计数
```
### 6.2 定值区切换检测
```
ie61850s_sg_change_callback(zone_saddr, new_act_sg):
→ 遍历 g_vec_setting 找到匹配的 saddr
→ dc_signal_ao_set_val(SELECT + DIRECT) 通过 datacenter 更新值
→ 设置 g_sg_zone_saddr 和 g_sg_zone_act_sg
check_sg_zone_change() (EV_TIMER3 中):
→ 如果有待更新信号 → mms_s_value_update(saddr, val)
→ 更新 MMS 模型,通知所有订阅客户端
```
---
## 7. 常见配置场景
### 7.1 添加新的遥测信号
1. 在 ICD 中定义 DA 的 sAddr
2. 在 `mms_s.xml` 的 `` 中添加 ``
3. 在 datacenter 初始化中注册该信号
4. 重启 RTU,初始化时自动绑定
### 7.2 添加新的遥控信号
1. ICD 中定义含 `ctlModel` 的 CO DO
2. `mms_s.xml` 的 `` 中添加信号
3. datacenter 中注册 yk 信号
4. `iec61850s_control_signals_init` 自动通过 sAddr 找到对应的 ModelNode 安装控制回调
### 7.3 配置多定值区参数
1. ICD 中 SG 定义多组 SE
2. `mms_s.xml` 的 `` 中添加信号
3. datacenter 中注册 param 信号(`dc_signal_param_reg` 需指定定值区数)
4. `iec61850s_param_signals_init` 自动获取各定值区数据指针