
简介面向电力自动化领域的通信协议学习与开发人员围绕南自电气以太网103规约IEC 60870-5-103 的网络化改进及上位机实现展开帮助读者理解规约帧结构、透明传输机制并为实际编写与南自设备通信的应用程序提供代码级参考。资源共2个文件由一个zip压缩包和一个C源代码文件组成总大小仅788KB精简聚焦便于快速定位协议关键逻辑。目前已有1442人学习浏览实用性得到验证。源码中可重点参考报文构造、数据编码解码、序列号管理、错误检测与重传、连接管理及心跳报文等模块基本覆盖以太网103规约上位机通信的核心流程结合协议要点读者既能弄清数据帧各字段含义与服务类型也能对照代码看清请求/响应、透明传输机制如何在真实项目中落地对变电站自动化、电网监控等场景的二次开发有直接帮助。整体以“协议解读源码实现”的组合降低学习门槛是南自103规约开发的不错起点。 “南自”这两个字搞电力系统通信的人不会陌生。尤其是做变电站后台、保护装置接入的老工程师看到“南自以太网103规约及上位机代码”这个压缩包名字基本就能猜到里面装的是什么。说实话这类资源并不算多网上能搜到的大多是零散报文说明或者某些论坛里贴出来的半截代码能凑成一套完整上位机工程的确实值得认真拆一拆。IEC 60870-5-103规约标准的说法是继电保护设备信息接口配套标准原本是跑在串行链路上的后来被改到以太网上变成了TCP/IP上的私有变体。这个“以太网103”本质上是把串口103的报文装进了TCP的壳里应用层的数据结构还保留着103的底子。如果你手头有南自的保护装置需要接入第三方平台或者你要在Linux或Windows上写一个采集程序去对接这类设备这套代码能省掉你大半周的抓包时间。打开看看发现它不只是一个通信库而是带界面、带实时刷新、带事件记录的完整上位机。对于刚接触电力规约的新手来说这套代码比单纯读规约文档直观得多对于老手来说里面有些报文细节处理也能勾起不少回忆。这篇文章我就从协议原理、代码结构、报文解析、调试踩坑四个角度把这份资源拆开聊透。1. 这个压缩包的本质103规约怎么“上以太网”1.1 103规约的出身与南自的改造先说背景。IEC 60870-5-103是IEC 60870-5系列里专门给继电保护设备定的一套通信标准早期的载体是RS-232和RS-485这样的串行链路物理层决定了它的传输速度慢、报文短数据量受限。变电站里各种保护装置、测控装置要往后台传遥信、遥测、事件报文串口多点轮询的方式虽然稳定但效率确实不高。南自的做法很直接把底层传输从串口换成TCP/IP链路层不再使用传统的FT1.2帧格式而是直接在TCP流里传应用层数据。这个思路和104规约把101规约移植到网络上有异曲同工之处但注意它不是标准104应用层的信息体结构和上传机制仍然保留了大量103的痕迹。也就是说你以为你在写103实际上也沾着104的边儿你以为能照搬标准103文档结果总会发现一些差异。这就是“以太网103”最需要留心的地方。从协议栈角度看它的分层大致是这样分层内容说明物理层以太网RJ45、光口传输层TCP/IP主动连接或被动监听应用层103变体ASDU结构基本沿用103但命令交互更接近1041.2 解压后先看什么目录与代码语言判断拿到这个zip第一件事不是急着编译而是先理清目录结构。我看到的这套工程大体上分几块协议库模块报文组帧、解帧TCP通信模块连接管理、收发线程界面模块实时数据、事件列表、报文监视配置文件设备参数、规约参数代码主体是C写的Visual Studio工程依赖项不多核心的协议处理逻辑在几个独立的类和源文件里没有过度耦合到界面代码中。这对学习来说是个优点你可以单独把协议模块抽出来移植到自己的项目里。如果你收到的版本和我看到的类似建议先编译一次跑一个虚拟连接测试确认通信底层没问题再去啃报文解析逻辑。我见过不少人一上来就扎进ASDU解析结果半天没搞懂收发状态机其实就是没先理清整体数据流。2. 报文结构拆解ASDU才是解析的核心2.1 帧结构从0x68启动符开始的链路层虽然以太网103不再依赖串口链路但很多实现仍然保留了类似的帧格式来保证报文完整性。最常见的可变帧长帧格式长这样字节偏移内容长度说明0启动符10x681长度L1后面的长度2长度L重复1与L一致校验用3启动符重复10x684控制域C1帧类型、功能码5地址域A1~2装置地址6链路用户数据可变ASDU末尾校验和CS1前面字节累加和最终结束符10x16这里有个容易犯迷糊的点长度L到底从哪个字节开始算。有的资料说L是从“控制域”开始到校验和前结束有的说是从“启动符重复”开始。不同厂家的实现存在差异我拆这套代码时专门验证过它是按第一种方式来计算的也就是L 控制域 地址域 数据 校验和。如果你自己解析时发现整帧长度对不上先检查这个定义。2.2 ASDU的三个关键字段ASDU是应用服务数据单元核心信息都装在它里面。理解ASDU只需要抓住三个字段类型标识、传送原因、信息体地址。类型标识Type标识一秒认得这条报文到底是遥信、遥测、还是总召唤命令。比如常见的单点信息、归一化测量值、时间标记报文等具体数值以协议文档为准。传送原因COT说明这条报文为什么发出来是自发上传、请求响应、还是激活确认。信息体地址具体到哪一路开关、哪一组遥测数据相当于点名寻址。这三个字段配合可变结构限定词VSQ就能确定后面跟着多少个信息体、每个信息体是多少字节。很多人在解析时容易犯的错误是死记某个类型标识对应的报文长度实际上信息体数量是VSQ的低6位决定的不含在类型标识里。正确做法是先解析VSQ再根据数量和单个信息体长度去切数据。2.3 以太网化之后的报文切分这是以太网103和串口103最大的区别。串口是字节流一次读一个字节状态机慢慢拼帧以太网上TCP本身也是字节流但接收缓冲区一次可能收到好几帧也可能一帧被拆成两次到达这就是经典的粘包和半包问题。处理思路很简单用状态机按帧格式匹配。先找0x68启动符拿到长度L然后校验L重复字节、校验和、结束符0x16确认整帧完整后再交给ASDU解析层。拆包时要注意长度L不一定等于TCP一次recv返回的长度需要维护一个环形缓冲区或滑动窗口把未消费的字节留给下一轮解析。这套代码里的处理方式我看了下是每次收完数据后先存进一个累积缓冲区再循环提取完整帧这个思路是稳的。3. 上位机代码的实现思路与关键模块3.1 通信连接与线程模型这套上位机在通信层分了几个线程主线程负责界面接收线程负责TCP收数据解析线程负责把收到的完整帧转成数据结构再通过信号槽机制通知界面刷新。这个模型虽然传统但足够稳定也容易理解。连接管理方面代码里做了设备地址配置支持主动连接装置侧端口。实际工程中南自的装置一般是服务端监听在固定端口上上位机作为客户端去连接。还有一种场景是装置主动上送报文上位机被动接收这时候就需要上位机自己监听端口。两种模式在这套代码里都有对应逻辑切换起来不算麻烦。重连机制也值得说。电力通信不像互联网应用设备重启、网线松动、交换机掉电这种事经常发生。代码里设置了心跳包周期用了应用层的心跳机制一段时间收不到数据就判定链路异常自动重连。这个细节对于长期挂在变电站现场的设备来说特别重要。3.2 总召唤流程一次完整的“握手”上位机启动后第一件事通常是发起总召唤把装置下所有遥信遥测的当前值全部拉上来。这套流程在代码里写得很清晰大致是这样构造总召唤ASDU类型标识用总召唤对应的值传送原因填激活。把ASDU封装成可变帧长格式通过TCP发送。装置收到后返回确认帧表示开始执行。装置逐条上送遥信、遥测数据。全部数据上送完毕后装置发一个总召唤结束帧传送原因是激活结束。这套流程里有几个细节要注意总召唤期间收到的数据不一定是全量可能有实时变化的数据夹在中间解析时要区分当前值还是变化值。如果超过一定时间没收到结束帧说明召唤过程异常需要重新发起或者告警。有些装置的地址是两字节有些是一字节总召唤报文里的公共地址必须匹配否则装置直接忽略。3.3 数据解析与界面展示从字节流到界面显示中间经过了几层转换理解这条数据链很重要。收到完整帧后先验证校验和然后解析控制域判断是监视方向还是控制方向的数据。接着进入ASDU解析提取类型标识、传送原因、公共地址、信息体地址。再根据信息体类型把原始字节换算成实际工程值。比如归一化测量值一般是一个有符号16位整数乘以变比系数才能得到实际的电流、电压值。有些还要处理品质位品质位的每一位对应数据是否有效、是否溢出、是否被取代界面展示时可以根据品质位来决定显示成正常值还是异常标记。这套代码里界面部分把数据分成了实时值列表和事件记录两个Tab。实时值列表负责遥测的刷新和遥信状态的翻转事件记录则保存带时标的告警和变位信息。这个划分和变电站后台的习惯一致实用性很高。4. 调试实录最容易踩的5个坑4.1 串口版思维留下的“长度错位”我第一次拿这套代码对接一个模拟装置时报文怎么都对不上。服务器那边一直报错检查发现是发送的帧长度字段和实际数据不一致。原因是我习惯了串口103里那种不带TCP头的报文把长度L按“从控制域到校验和”计算结果多算了两个字节。后来翻代码里的组帧函数才发现它计算L时把启动符重复也包含了进去也就是说它采用的是另一种长度约定。这件事给我的教训是拿到别人的代码先看组帧和拆帧是成对写的别拿标准的定义去套私有实现。4.2 TCP拆包粘包导致的“帧找不到”第二次出问题是在连续大量接收遥信变位时解析程序突然卡住表现为界面值不再刷新。排查后发现连续收到多帧报文时缓冲区里残留了一个半截帧而解析函数每次只取一帧剩下的数据没有正确保留下一轮接收上来又拼上了新数据结果长度对不上状态机进入死循环。解决方案也简单改成循环解析每解析完一帧就继续检查缓冲区里是否还有完整帧直到缓冲数据不足一帧为止。这个逻辑看起来基础但很多入门代码确实没写对。你要是自己写上位机这个位置值得多花点心思。4.3 字节序与ASDU长度的隐性错误还有一个容易踩的坑是字节序。103规约里很多字段是低字节在前但有些厂商的私有实现会做调整。更隐蔽的是ASDU长度有些人直接把整个帧长度减去固定头部长度就认为是ASDU长度实际上如果地址域是两字节这里的偏移就得加1。这类问题在报文里表现得很诡异数据内容都有但解析出来全是错的最终还是要靠逐字节对照抓包数据来定位。4.4 品质位和数值缩放遥测数值看起来不对不一定是协议解析的问题还可能是缩放系数没配对。我见过一个案例明明报文里解析出1638界面上却显示163.8所有遥测都大了十倍。后来查配置发现装置的遥测系数是0.1而上位机默认的是1.0。这种问题在规约调试里非常常见尤其是不同厂家对归一化值的定义差别很大。遇到数值不对先别怀疑报文去查工程量和原始值之间的换算关系。还有一个容易被忽略的是品质位。有些数据在装置侧已经被置为无效但上位机如果不看品质位直接把数值显示出来就会造成误导。好的实现是在界面上对无效品质的数据打灰色标记或者显示“无效”状态而不是给出一个看似正常的数值。这套代码里品质位的处理逻辑是有的不过藏得比较深新手容易找到解析函数但没注意到那几位bit的运算。4.5 重启后召唤不到原来是帧计数位最后一个坑和帧计数位FCB有关。串口103时代主站通过帧计数位的翻转来防止报文丢失或重复以太网版虽然没有那么严格但有些装置的实现仍然会校验这个位。如果上位机连续发了两帧同样FCB的报文装置会认为是重复帧直接丢弃表现就是总召唤发出去毫无回应。解决办法是在每次发送需要确认的控制帧时把FCB位取反然后等待确认。如果超时没收到确认重发时保持同样的FCB如果收到了确认下次发送时再翻转。这是老掉牙的状态机逻辑但在以太网103里照样适用也最容易写漏。问题现象可能原因排查方向连接正常但无数据总召唤未发或FCB重复抓包看链路层交互解析出来数据全乱长度字段定义不一致逐字节对照组帧代码过多帧后卡死TCP粘包残留未处理检查循环拆帧逻辑数值整体偏大偏小缩放系数未配置核对装置遥测变比界面显示但状态灰色品质位为无效检查ASDU品质字段5. 一点个人的使用体会这套代码我前后翻过几次每次都有新发现。第一次是急着对接设备只关注收发函数怎么调第二次是出了问题回头查解析逻辑才开始认真读ASDU的处理细节第三次纯粹是想把通信模块抽出来复用才发现它的分层做得比我预想的好。如果你想靠这套代码学习电力规约开发我的建议是先不要急着跑GUI把通信层和解析层单独拿出来配合一个模拟装置做交互测试。这样既能验证自己的理解也能快速定位问题。如果只是想在别人的项目里改改界面、加个报表功能那直接用原工程把设备地址和缩放系数配好就行。但如果你是像我一样想彻底搞懂以太网103的来龙去脉建议找一台南自的装置或者用脚本模拟装置端一步一步抓包分析总召唤、遥信变位、事件上送这几条完整链路。把这些流程跑通了以后再看其他厂家的私有规约几乎都是触类旁通的事。本文还有配套的精品资源点击获取