267 lines
8.5 KiB
Markdown
267 lines
8.5 KiB
Markdown
# 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
|
||
<mms_s>
|
||
<St>
|
||
<Signal no="1" link="ST_Signal_1" />
|
||
<Signal no="2" link="ST_Signal_2" />
|
||
</St>
|
||
<Mx>
|
||
<Signal no="1" link="MX_Signal_1" />
|
||
</Mx>
|
||
<Co>
|
||
<Signal no="1" link="YK_Signal_1" />
|
||
</Co>
|
||
<Ao>
|
||
<Signal no="1" link="SG_Signal_1" />
|
||
</Ao>
|
||
<Param>
|
||
<Signal no="1" link="Param_Signal_1" />
|
||
</Param>
|
||
</mms_s>
|
||
```
|
||
|
||
- `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` 的 `<Mx>` 中添加 `<Signal link="新sAddr" />`
|
||
3. 在 datacenter 初始化中注册该信号
|
||
4. 重启 RTU,初始化时自动绑定
|
||
|
||
### 7.2 添加新的遥控信号
|
||
|
||
1. ICD 中定义含 `ctlModel` 的 CO DO
|
||
2. `mms_s.xml` 的 `<Co>` 中添加信号
|
||
3. datacenter 中注册 yk 信号
|
||
4. `iec61850s_control_signals_init` 自动通过 sAddr 找到对应的 ModelNode 安装控制回调
|
||
|
||
### 7.3 配置多定值区参数
|
||
|
||
1. ICD 中 SG 定义多组 SE
|
||
2. `mms_s.xml` 的 `<Param>` 中添加信号
|
||
3. datacenter 中注册 param 信号(`dc_signal_param_reg` 需指定定值区数)
|
||
4. `iec61850s_param_signals_init` 自动获取各定值区数据指针
|