共计 2640 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点:从寄存器到信息模型
传统变电站协议如 Modbus 采用简单的寄存器地址映射机制,就像用 Excel 表格记录数据——每个点表对应固定的寄存器地址。而 IEC 61850 带来的变革相当于从纸质档案升级到数据库系统:

- 数据对象化:将断路器、变压器等设备抽象为 LogicalDevice/LogicalNode,例如 XCBR1 代表 1 号断路器
- 自描述特性 :通过 SCL 文件(Substation Configuration Language) 明确定义数据属性,比如 Modbus 需要查点表才能知道 40001 地址的含义,而 61850 的 MMS 报文直接携带
IED1/XCBR1.Pos.stVal这样的语义化路径 - 服务抽象:ACSI 服务如 GetDirectory、GetVariableValue 被映射到 MMS 的 Read/Write 服务原语,就像把具体操作(打开文件)转化为通用 API 调用
协议栈解剖:从应用到以太网帧
用分层视角看 61850 通信,就像快递包裹的层层包装:
@startuml
skinparam monochrome true
frame 应用层 {[ACSI 服务]
(GetVariableValue)
}
frame 表示层 {[MMS 协议]
(ReadRequest)
}
frame 传输层 {[TCP 102 端口]
}
frame 网络层 {[IP 协议]
}
frame 数据链路层 {[Ethernet II]
}
[ACSI 服务] --> [MMS 协议] : 映射
[MMS 协议] --> [TCP 102 端口] : 承载
[TCP 102 端口] --> [IP 协议]
[IP 协议] --> [Ethernet II]
@enduml
关键点在于 MMS 如何封装 ACSI 服务:当客户端请求读取IED1/MMXU1.PhV.phsA.cVal.mag.f(A 相电压幅值)时:
- ACSI 层生成 GetVariableValue 服务请求
- MMS 层转换为 ReadRequest PDU,包含 ObjectName 和 VariableSpecification
- 通过 BER 编码规则转换为 ASN.1 二进制流
- TCP 层拆分为多个 Segment 传输
抓包实战:Wireshark 技巧与 Python 解码
抓包过滤器配置
针对不同报文类型的 BPF 语法:
# 抓取 MMS 报文(TCP 102 端口)tcp port 102
# 抓取 GOOSE 报文(目的 MAC 01-0C-CD-01 开头)ether dst 01:0c:cd:01:00:00/ff:ff:ff:ff:00:00
# 抓取 SV 报文(APPID 范围 4000-7FFF)ether[16:2] >= 0x4000 and ether[16:2] <= 0x7fff
Python 解析 MMS 响应示例
安装依赖库:
pip install asn1tools scapy
解析 GetVariableAccessAttributes 响应的关键代码:
import asn1tools
from scapy.all import rdpcap
# 加载 61850 标准 ASN.1 定义
mms_asn = asn1tools.compile_files('61850-8-1.asn', 'ber')
# 从抓包文件提取 MMS PDU
pcap = rdpcap('mms_traffic.pcap')
mms_pdu = bytes(pcap[0][TCP].payload)
# 解码 MMS PDU
decoded = mms_asn.decode('MMSpdu', mms_pdu)
# 提取变量属性
if 'confirmed-ResponsePDU' in decoded:
var_attrs = decoded['confirmed-ResponsePDU']['response']['getVariableAccessAttributes']
print(f"变量名: {var_attrs['name']}")
print(f"数据类型: {var_attrs['typeDescription']['structure']['components'][0]['type']}")
print(f"是否可读: {'mmsDeletable'in var_attrs['accessControl']}")
代码执行后会输出类似结果:
变量名: IED1/MMXU1.PhV.phsA
数据类型: AnalogueValue
是否可读: True
避坑指南:工程实践中的血泪经验
CID 文件版本冲突
常见报错 Association model mismatch 往往因为:
- IED 设备升级后未导出新 CID
- SCL 文件中的 LN 实例数与设备实际不符
- DataSet 成员顺序与设备内部不一致
解决方案:
- 使用 IED 配置工具重新导出 CID
- 比对 SCL 文件中
Communication段与设备实际通信配置 - 使用报文比对工具验证 DataSet 成员顺序
TCP 窗口优化
当传输大量报告 (Report) 或日志时,默认 TCP 窗口可能成为瓶颈:
- 在 Linux 客户端调整窗口大小:
# 查看当前值 sysctl net.ipv4.tcp_rmem # 临时设置为 2MB echo 2097152 > /proc/sys/net/core/rmem_max - 在 Windows 注册表修改
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的TcpWindowSize值
扩展思考:设备指纹识别
通过分析 MMS 交互特征可识别 IED 设备类型:
- 服务支持矩阵:某些厂商设备不支持 Write 服务
- 响应时延特征:老型号设备处理 GetDirectory 响应通常 >50ms
- 对象命名风格:如西门子设备常用大写 LN 前缀(
CBSW1),ABB 设备带厂商标识(ABB_ROCK) - TCP 参数特征:初始窗口大小、MSS 值等
实现思路示例:
def fingerprint_ied(mms_pdu):
vendor = 'Unknown'
if b'SIEMENS' in mms_pdu:
vendor = 'Siemens SIPROTEC'
elif len(mms_pdu) > 200 and b'ABB' in mms_pdu[100:150]:
vendor = 'ABB REF615'
return vendor
结语
理解 61850 通信就像学一门外语——需要同时掌握语法(SCL 模型)和发音规则(MMS 编码)。建议从实际报文中逆向学习:先用 Wireshark 捕获正常通信流量,再尝试修改 CID 文件观察报文变化,最后动手实现简单的客户端程序。当你能准确预测每个字节的含义时,就真正掌握了智能变电站的通信脉搏。
正文完
