RTU/mimo/工程/libiec61850s模块分析.md

6.6 KiB
Raw Permalink Blame History

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) 仅定值区同步