6.6 KiB
6.6 KiB
libiec61850s 模块分析
日期: 2026-06-12
基于源码: src/system/libiec61850s/ (iec61850s.cpp, parse_xml.cpp, 共4个文件)
1. 模块定位
libiec61850s 位于系统层,是 libmms_s 的上层封装。它负责将 datacenter 中的信号注册到 MMS 服务端模型中,使远方客户端能通过 IEC 61850 MMS 协议读取 RTU 数据并下发控制命令。
与其他模块的关系:
远方 MMS 客户端
↓ MMS 协议
libmms_s (协议层, IedServer)
↑↓ 回调
libiec61850s (本模块)
↑↓ dc_signal_* API
datacenter (信号存储)
2. 配置解析(parse_xml.cpp)
2.1 XML 结构
<mms_s>
<St>
<Signal no="1" link="signal_saddr_1" />
</St>
<Mx>
<Signal no="1" link="signal_saddr_2" />
</Mx>
<Co>
<Signal no="1" link="signal_saddr_3" />
</Co>
<Ao>
<Signal no="1" link="signal_saddr_4" />
</Ao>
<Param>
<Signal no="1" link="signal_saddr_5" />
</Param>
</mms_s>
解析函数 parse_mms_xml(path) 使用 tinyxml2 遍历五类信号元素,提取 link 属性存入 stru_mms_cfg。
2.2 数据结构
typedef struct
{
char saddr[MMS_S_STR_LEN];
char desc[MMS_S_STR_LEN];
uint8_t type;
uint8_t ctrl_model;
}stru_mms_s_signal_base;
typedef struct
{
std::vector<stru_mms_s_signal_base> vec_st;
std::vector<stru_mms_s_signal_base> vec_mx;
std::vector<stru_mms_s_signal_base> vec_co;
std::vector<stru_mms_s_signal_base> vec_ao;
std::vector<stru_mms_s_signal_base> vec_param;
}stru_mms_cfg;
配置保存在全局变量 g_cfg 中,通过 mms_cfg_ptr_get() 获取。
3. 两阶段初始化
3.1 app_iec61850s_init1(第一阶段)
1. 获取进程目录
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(&g_mms_s_value_update_cb) // 注册值更新回调
此时仅完成配置解析和底层回调注册,datacenter 尚未就绪。
3.2 app_iec61850s_init2(第二阶段)
1. iec61850s_signals_init(): // 核心信号初始化
- iec61850s_st_signals_init:
对每个 ST 信号调用 dc_signal_out_link_with_callback
→ 获取 datacenter 信号指针 + 注册变更回调
→ 回调: st_mx → mms_s_value_update (更新 MMS 模型)
- iec61850s_mx_signals_init:
同上(MX 信号)
- iec61850s_control_signals_init:
对每个 CO 信号:
dc_get_yk_signal_info → 获取类型和 ctrl_model
mms_s_control_register → 向 libmms_s 注册控制回调
回调接收远方控制命令 → dc_signal_yk_set_status
- iec61850s_setting_signals_init:
对每个 AO 信号:
dc_signal_ao_link_with_callback → 绑定 SP 定值
mms_s_setting_register → 注册写入回调
回调接收客户端修改 → dc_signal_ao_set_val
- iec61850s_param_signals_init:
对每个 Param 信号:
dc_get_param_signal_info → 获取各定值区指针
mms_s_param_register → 注册 ConfirmEditSG 回调
回调接收定值确认 → dc_signal_param_set_val
2. mms_s_init(PCS.icd, 102):
解析 ICD → 创建模型 → 启动 IedServer(端口 102)
3. mms_s_bind_param_zone_signal(zone_saddr, iec61850s_sg_change_callback):
绑定定值区号 → 定值区切换时自动同步
4. 信号方向与回调链
4.1 数据上行(datacenter → MMS 客户端)
datacenter 信号变化
→ iec61850s_st_mx_change_callback(saddr, type, p_data, p_last_data)
→ dc_get_signal_val → 格式化为字符串
→ g_mms_s_value_update_cb(saddr, val_str) // 即 mms_s_value_update
→ IedServer_updateAttributeValue → 更新模型值 → 触发 RCB 报告 → 通知订阅客户端
4.2 控制下行(MMS 客户端 → datacenter)
远方客户端控制命令
→ libmms_s control_handler
→ iec61850s_control_callback(p_control, state):
state == 1 (命令到达):
根据 ctrl_model:
DIRECT/SBO: dc_signal_yk_set_status(SELECT + DIRECT)
STATUS_ONLY: 日志记录
4.3 SP 定值修改(MMS 客户端 → datacenter)
远方客户端修改 SP 定值
→ libmms_s setting writeAccessHandler
→ iec61850s_setting_callback(p_setting, p_data):
dc_set_signal_val_from_str → 解析字符串值
dc_signal_ao_set_val(SELECT + DIRECT or DIRECT only)
4.4 定值组修改(MMS 客户端 → datacenter)
远方客户端 ConfirmEditSG
→ libmms_s confirmEditSG_callback
→ iec61850s_param_callback(p_param, p_data, zone):
dc_set_signal_val_from_str → 解析
dc_signal_param_set_val(zone, data)
4.5 定值区切换同步
datacenter 定值区号变化
→ iec61850s_sg_change_callback(zone_saddr, new_act_sg):
找到对应的 setting 信号
dc_signal_ao_set_val: 同步新值到 AO 信号
设置 g_sg_zone_saddr / g_sg_zone_act_sg
→ check_sg_zone_change() (EV_TIMER3 中):
mms_s_value_update: 更新 MMS 模型中 SGCB.ActSG 值
5. 主线程循环
void *app_iec61850s(void *arg):
while(1):
task_event_recv(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. 全局变量
| 变量 | 类型 | 说明 |
|---|---|---|
g_vec_st |
vector<stru_local_st_mx> |
ST 信号列表(含 datacenter 指针) |
g_vec_mx |
vector<stru_local_st_mx> |
MX 信号列表 |
g_vec_control |
vector<stru_mms_s_control> |
控制信号列表 |
g_vec_setting |
vector<stru_mms_s_setting> |
SP 定值信号列表 |
g_vec_param |
vector<stru_mms_s_param> |
定值组参数列表 |
g_mms_s_value_update_cb |
函数指针 | MMS 值更新回调(= mms_s_value_update) |
g_sg_zone_saddr |
string | 待同步的定值区信号地址 |
g_sg_zone_act_sg |
string | 待同步的新定值区号 |
7. 与 libiec61850m 的对比
| 特性 | libiec61850m (客户端) | libiec61850s (服务端) |
|---|---|---|
| 角色 | 主动读取/控制远方 IED | 被动响应远方客户端请求 |
| 数据方向 | 拉取(All-Call/GI) | 推送(RCB 报告触发) |
| 控制 | 下发控制命令 | 接收并执行控制命令 |
| 连接 | 每个 IED 一个连接 | 监听端口,接受多客户端 |
| 定时器 | T0(120s)/T1(60s)/T2(30s) | EV_TIMER3(1s) 仅定值区同步 |