305 lines
8.3 KiB
Markdown
305 lines
8.3 KiB
Markdown
# libiec61850_MMS客户端API开发手册
|
||
|
||
**日期**: 2026-06-12
|
||
**基于源码**: `release/inc/myMms_m.h`, `src/system/libiec61850m/`
|
||
|
||
---
|
||
|
||
## 1. 模块层次
|
||
|
||
RTU 的 MMS 客户端分为两层:
|
||
|
||
```
|
||
┌─────────────────────────────┐
|
||
│ iec61850m (系统层) │ ← 本文档描述
|
||
│ - 配置解析、信号初始化 │
|
||
│ - 回调转发给 datacenter │
|
||
├─────────────────────────────┤
|
||
│ libmms_m (协议层) │ ← 底层 API,详见《libmms_m模块分析》
|
||
│ - IED 连接、定时器、事件 │
|
||
│ - MMS 协议编解码 │
|
||
└─────────────────────────────┘
|
||
```
|
||
|
||
`iec61850m` 负责解析 XML 配置(`mms_m.xml`),编排信号初始化流程,将 `libmms_m` 的数据通过回调桥接到数据中心(`datacenter`)。
|
||
|
||
---
|
||
|
||
## 2. 核心 API(`release/inc/myMms_m.h`)
|
||
|
||
### 2.1 `mms_m_out_init`
|
||
|
||
```c
|
||
int mms_m_out_init(stru_cfg *p_cfg, int debug_print_flag, uint32_t connectionTimeout);
|
||
```
|
||
|
||
**功能**: 创建一个 IED 连接。
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `p_cfg` | 配置文件结构体指针,必须包含 `path`(配置文件路径) |
|
||
| `debug_print_flag` | 调试打印开关(1=开, 0=关),开启后打印 ICD 发现详情和 MMS 值 |
|
||
| `connectionTimeout` | 连接超时(毫秒) |
|
||
|
||
**返回值**: 成功返回 `obj_fd`(>0),失败返回 `-1`。
|
||
|
||
**副作用**: 创建 `stru_mms_m_obj` 实例,启动独立工作线程 `mms_m_run_thread`,开始异步连接远方 IED。
|
||
|
||
---
|
||
|
||
### 2.2 `mms_m_out_get_connect_status`
|
||
|
||
```c
|
||
int mms_m_out_get_connect_status(int app_fd, mms_m_out_status_cb p_func);
|
||
```
|
||
|
||
**功能**: 注册连接状态回调。
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `app_fd` | `mms_m_out_init` 返回的句柄 |
|
||
| `p_func` | 回调函数 `void(int fd, int status)`,status: `MMS_M_ON_LINE` 或 `MMS_M_OFF_LINE` |
|
||
|
||
---
|
||
|
||
### 2.3 `mms_m_out_debug_print_swicth`
|
||
|
||
```c
|
||
int mms_m_out_debug_print_swicth(int app_fd, int debug_print_flag);
|
||
```
|
||
|
||
**功能**: 运行时开关调试打印。
|
||
|
||
---
|
||
|
||
### 2.4 `mms_m_out_do_set_yk`
|
||
|
||
```c
|
||
int mms_m_out_do_set_yk(stru_mms_m_event *p_event);
|
||
```
|
||
|
||
**功能**: 下达遥控命令(Select/Direct/Cancel)。
|
||
|
||
```c
|
||
typedef struct
|
||
{
|
||
int app_fd; // IED 句柄
|
||
char ied[64]; // IED 名称(app_fd = 0 时按名称匹配)
|
||
char saddr[256]; // 信号地址
|
||
uint8_t ctrl_type; // 操作类型
|
||
char data[128]; // 操作数据
|
||
int set_fd; // 操作序号
|
||
}stru_mms_m_event;
|
||
```
|
||
|
||
`ctrl_type` 取值:
|
||
- `_MMS_M_EVENT_CO_SELECT`: 选择(SBO 模式第一步)
|
||
- `_MMS_M_EVENT_CO_DIRECT`: 执行(Direct 或 SBO 第二步)
|
||
- `_MMS_M_EVENT_CO_CANCEL`: 取消
|
||
|
||
**注意**: `app_fd > 0` 时按句柄查找;`app_fd = 0` 时按 `ied` 名称查找。
|
||
|
||
---
|
||
|
||
### 2.5 `mms_m_out_read_ao_or_params`
|
||
|
||
```c
|
||
int mms_m_out_read_ao_or_params(int app_fd, uint8_t type, const char *saddr);
|
||
```
|
||
|
||
**功能**: 读取 AO 或 Param 值。
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `type` | `_MMS_M_EVENT_AO_READ` 或 `_MMS_M_EVENT_PARAM_READ` |
|
||
| `saddr` | 指定信号地址(`nullptr` 时读取全部) |
|
||
|
||
---
|
||
|
||
### 2.6 `mms_m_out_get_value`
|
||
|
||
```c
|
||
int mms_m_out_get_value(int fd, mms_m_out_value_cb p_func);
|
||
```
|
||
|
||
**功能**: 注册数据推送回调。所有读取到的 ST/MX/AO/Param 值都通过此回调向外推送。
|
||
|
||
```c
|
||
typedef void (*mms_m_out_value_cb)(stru_mms_m_out_value &val);
|
||
```
|
||
|
||
`stru_mms_m_out_value` 字段:
|
||
```c
|
||
typedef struct
|
||
{
|
||
int app_fd; // IED 句柄
|
||
char name[256]; // 信号 saddr
|
||
char desc[256]; // 信号描述
|
||
char reference[256]; // MMS 对象引用
|
||
void *p_value; // 数据指针
|
||
uint8_t type; // MMS 数据类型(BOOLEAN/INTEGER/UNSIGNED/FLOAT/STRING)
|
||
int quality; // 品质位
|
||
stru_mms_m_time time; // 时标
|
||
int reason; // 原因码(ALL_CALL/GI/dchg/qchg 等)
|
||
}stru_mms_m_out_value;
|
||
```
|
||
|
||
---
|
||
|
||
### 2.7 `mms_m_out_bind_param_zone_signal`
|
||
|
||
```c
|
||
int mms_m_out_bind_param_zone_signal(int app_fd, const char *zone_saddr);
|
||
```
|
||
|
||
**功能**: 绑定定值区号信号。定值区号变化时自动触发参数重读。
|
||
|
||
---
|
||
|
||
### 2.8 `mms_m_out_set_rcb_numbers`
|
||
|
||
```c
|
||
int mms_m_out_set_rcb_numbers(int app_fd, const char *rcb_numbers);
|
||
```
|
||
|
||
**功能**: 设置 RCB 订阅编号。
|
||
|
||
| 输入 | 行为 |
|
||
|------|------|
|
||
| 不调用 | 默认订阅 `"01"` |
|
||
| `"01"` | 只订阅 01 号 |
|
||
| `"01,02,03"` | 订阅多个编号 |
|
||
| `"*"` | 订阅全部 RCB |
|
||
| `"abc"` / `"1"` / `"012"` | 非法,返回 -1 |
|
||
|
||
---
|
||
|
||
### 2.9 工具函数
|
||
|
||
```c
|
||
void *mms_m_create_data_ptr(uint8_t type); // 创建数据指针(需手动 delete)
|
||
int mms_m_set_data_value(void *srt, void *dst, uint8_t type); // 类型化赋值
|
||
int mms_m_get_data_value_str(void *data, uint8_t type, char *s); // 转字符串
|
||
int mms_m_set_data_by_str(void *data, uint8_t type, const char *s); // 从字符串设置
|
||
char *mms_m_out_reason_str(int reason); // 原因码→字符串
|
||
```
|
||
|
||
`type` 取值: `MMS_BOOLEAN`, `MMS_INTEGER`, `MMS_UNSIGNED`, `MMS_FLOAT`, `MMS_STRING`
|
||
|
||
---
|
||
|
||
## 3. iec61850m 初始化流程
|
||
|
||
### 3.1 两阶段初始化
|
||
|
||
```
|
||
app_iec61850m_init1:
|
||
1. 获取进程目录
|
||
2. 解析 config/MMS/mms_m.xml(点表配置)
|
||
- St/Mx/Co/Ao/Param 各信号点的 saddr/type/ctrl_model/desc
|
||
3. 为每个 IED 调用 mms_m_out_init → 获取 obj_fd
|
||
4. 注册数据回调: mms_m_out_get_value → 桥接到 datacenter
|
||
5. 注册连接状态回调
|
||
|
||
app_iec61850m_init2:
|
||
1. 调用 mms_m_out_debug_print_swicth(传入调试标志)
|
||
2. 调用 mms_m_out_set_rcb_numbers(传入 RCB 编号配置)
|
||
3. 调用 mms_m_out_bind_param_zone_signal(绑定定值区信号)
|
||
```
|
||
|
||
### 3.2 数据回调桥接
|
||
|
||
iec61850m 的数据回调完成 MMS 值 → datacenter 的转换:
|
||
|
||
```
|
||
mms_m_out_get_value_callback(out_val):
|
||
→ 根据 reason 分类处理:
|
||
ALL_CALL: dc_set_out_signal_val(name, p_value, type, quality)
|
||
GI: dc_set_out_signal_val(name, p_value, type, quality)
|
||
dchg/qchg: // 报告触发,同上
|
||
→ 对 CO/AO/Param: 转发到对应的 datacenter 写接口
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 配置文件格式(mms_m.xml)
|
||
|
||
```xml
|
||
<IED name="PCS9700" ip="192.168.1.100" port="102" rcb_numbers="01,02">
|
||
<St>
|
||
<Signal no="1" link="ST_Signal_1" reference="PCS9700CTRL/GGIO1$ST$Ind1$stVal" /> <!-- (1) -->
|
||
</St>
|
||
<Mx>
|
||
<Signal no="1" link="MX_Signal_1" reference="PCS9700MEAS/MMXU1$MX$PhV$phsA$cVal$mag$f" />
|
||
</Mx>
|
||
<Co>
|
||
<Signal no="1" link="YK_Signal_1" reference="PCS9700CTRL/CSWI1$CO$Pos$Oper$ctlVal" />
|
||
</Co>
|
||
<Ao>
|
||
<Signal no="1" link="SG_Signal_1" reference="PCS9700PROT/LLN0$SG$sg1$StrVal" />
|
||
</Ao>
|
||
<Param>
|
||
<Signal no="1" link="Param_Signal_1" reference="PCS9700PROT/PTOC1$SG$sg1$StrVal" />
|
||
</Param>
|
||
</IED>
|
||
```
|
||
|
||
- `link`: 信号 saddr,对应 datacenter 中的信号地址
|
||
- `reference`: IEC 61850 对象引用,用于 `IedConnection_readObject`
|
||
- `name`: IED 名称,用于连接日志
|
||
- `rcb_numbers`: RCB 编号过滤(逗号分隔,可选)
|
||
|
||
---
|
||
|
||
## 5. 常见使用场景
|
||
|
||
### 5.1 读取遥测/遥信
|
||
|
||
```
|
||
// 自动完成 — 定时器 T0 (120s) 触发 All-Call,T1 (60s) 触发 GI
|
||
// 数据通过 mms_m_out_get_value 注册的回调推送
|
||
// 用户只需在 iec61850m_init1 中调用 mms_m_out_get_value 注册回调
|
||
```
|
||
|
||
### 5.2 手动读取 AO 值
|
||
|
||
```cpp
|
||
// 读取指定 AO
|
||
mms_m_out_read_ao_or_params(fd, _MMS_M_EVENT_AO_READ, "AO_Signal_1");
|
||
// 读取全部 AO
|
||
mms_m_out_read_ao_or_params(fd, _MMS_M_EVENT_AO_READ, nullptr);
|
||
```
|
||
|
||
### 5.3 下达遥控命令
|
||
|
||
```cpp
|
||
// SBO 模式
|
||
stru_mms_m_event event = {};
|
||
event.app_fd = fd;
|
||
event.ctrl_type = _MMS_M_EVENT_CO_SELECT;
|
||
strncpy(event.saddr, "YK_Signal_1", sizeof(event.saddr));
|
||
mms_m_out_do_set_yk(&event);
|
||
|
||
// 确认后执行
|
||
event.ctrl_type = _MMS_M_EVENT_CO_DIRECT;
|
||
mms_m_out_do_set_yk(&event);
|
||
```
|
||
|
||
### 5.4 写入定值
|
||
|
||
```cpp
|
||
// 定值写入通过 mms_m_out_read_ao_or_params 触发 O→Param 流程
|
||
// libmms_m 内部自动处理 SG/SE 编辑-确认流程
|
||
```
|
||
|
||
### 5.5 RCB 编号配置
|
||
|
||
```cpp
|
||
// 只订阅 01 号 RCB
|
||
mms_m_out_set_rcb_numbers(fd, "01");
|
||
// 订阅 01, 02, 03 号
|
||
mms_m_out_set_rcb_numbers(fd, "01,02,03");
|
||
// 订阅全部
|
||
mms_m_out_set_rcb_numbers(fd, "*");
|
||
```
|