ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

一个人啃下12种工控协议:从Modbus到OPC UA的实战避坑指南

一个人啃下12种工控协议:从Modbus到OPC UA的实战避坑指南 1. 一个人啃下12种工控协议到底难在哪先说说我自己的情况。我不是自动化科班出身大学学的是计算机毕业后在一家小公司做上位机开发。第一次接触工控协议是2019年客户拿着一台西门子S7-1200过来说“你把这个PLC的数据读到我的系统里”我当时连PLC是什么都不知道。从Modbus RTU开始到后来陆续啃下西门子S7协议、OPC UA、CIP、Modbus TCP、IEC 104、DL/T 645、Profinet、EtherCAT、CANopen、BACnet、MQTT前后大概花了三年多的业余时间。这篇文章不是教程是我自己踩坑、填坑、再踩坑的过程记录适合那些跟我一样单枪匹马、没有师傅带、但又必须把设备数据接进自己系统的个人开发者。工控协议这个东西跟互联网协议最大的区别在于它们大多诞生于上世纪七八十年代设计初衷是“稳定、简单、能在恶劣环境下跑”而不是“优雅、通用、好扩展”。这就导致每个协议都有自己的脾气——Modbus简单到粗暴但功能码和寄存器地址的映射能把你绕晕西门子S7协议性能好但文档几乎不公开全靠抓包逆向OPC UA标准极其完备但光是理解信息模型就够你看一个星期。一个人要啃下12种最大的难点不是每种协议有多深而是你需要在脑子里建立一套“协议分类框架”否则学一个忘一个最后全搅在一起。我后来总结出一个分类维度对我帮助极大按传输层分串口/以太网/总线按数据模型分寄存器型/对象型/文件型按实时性分周期轮询/事件订阅/发布订阅。比如Modbus RTU和Modbus TCP本质是同一个应用层协议只是传输层不同西门子S7和CIP都是对象型数据模型但一个走ISO-on-TCP一个走EtherNet/IP。有了这个框架学新协议时我第一件事就是把它往这三个维度里塞塞进去之后就知道该重点看什么、可以跳过什么。提示不要试图一次性学完12种。我的做法是“用一学一”项目需要哪个就学哪个学完立刻写一篇自己的笔记记录这个协议最坑的三个点和最顺手的调试工具。三年下来笔记攒了12篇比任何教程都管用。2. 协议分类框架先建地图再走路2.1 按传输层分串口、以太网、现场总线串口类协议是我最早接触的因为成本低、设备多。Modbus RTU、DL/T 645、部分BACnet MS/TP都走RS-485或RS-232。串口协议的核心痛点是物理层调试——线接错了、终端电阻没加、波特率不匹配软件层面再怎么调都没用。我刚开始调Modbus RTU时用USB转485模块接PLC死活读不到数据后来发现是A/B线接反了。这种坑在以太网协议里基本不会遇到因为网线插上就能通。以太网类协议包括Modbus TCP、西门子S7、OPC UA、CIP、IEC 104、Profinet、EtherCAT。这里面又分两种一种是基于TCP/UDP的普通以太网协议用普通网卡和交换机就能跑另一种是实时以太网协议比如Profinet和EtherCAT需要专用网卡或芯片才能达到微秒级同步。个人开发者如果只是做数据采集基本只碰前者后者通常是设备厂商的领域。现场总线类包括CANopen、DeviceNet、Profibus DP等。这类协议的特点是多主站或主从轮询物理层用CAN或RS-485速率不高但抗干扰强。我接触CANopen是因为一个车载项目需要读电机控制器的数据。CANopen的PDO过程数据对象和SDO服务数据对象概念跟Modbus的寄存器和线圈有点像但对象字典的索引方式更复杂。2.2 按数据模型分寄存器型、对象型、文件型寄存器型协议最典型的就是Modbus。它的数据模型极其简单线圈1位读写、离散输入1位只读、保持寄存器16位读写、输入寄存器16位只读。所有数据都映射到这四个区的地址上地址从0到65535。简单是优点也是缺点——没有数据类型没有结构体一个32位浮点数要拆成两个寄存器字节序还分ABCD和CDAB不同厂商实现还不一样。对象型协议包括西门子S7、CIP、OPC UA、BACnet。这类协议把数据抽象成“对象”每个对象有属性、方法、事件。比如CIP里一个模拟量输入是一个对象有值、状态、单位等属性。OPC UA更是把对象模型做到了极致你可以自定义类型、继承、引用。对象型协议的学习曲线更陡但一旦理解扩展性极好。文件型协议比较少见比如Modbus的文件记录功能码0x14/0x15以及部分PLC的FTP文件传输。这类协议适合批量数据传输比如上传一段历史记录。我做过一个项目用Modbus文件记录读电表的历史电量比逐寄存器轮询效率高很多。2.3 按实时性分轮询、订阅、发布轮询是最常见的Modbus、S7、CIP都是主站主动问、从站被动答。轮询的痛点是周期和超时——周期太短设备扛不住太长数据不及时超时太短容易误判掉线太长故障响应慢。我一般把轮询周期设在设备手册推荐值的1.5倍超时设在周期的3倍。订阅型以OPC UA为代表客户端订阅一个节点服务端数据变化时主动推送。这种方式省带宽、实时性好但需要服务端支持。很多老PLC不支持OPC UA订阅只能轮询。发布订阅型是MQTT、OPC UA PubSub等适合多对多、跨网络场景。MQTT在工控里越来越多用于云端上传但它的QoS机制和遗嘱消息需要仔细配置否则断线重连时容易丢数据。注意分类框架不是绝对的。比如OPC UA既可以轮询也可以订阅Modbus TCP既可以走普通以太网也可以走实时以太网。框架的目的是帮你快速定位学习重点不是给你贴标签。3. 逐个啃12种协议的实操要点与避坑记录3.1 Modbus RTU/TCP最该先啃的硬骨头Modbus是我建议所有个人开发者第一个学的协议没有之一。原因很简单它足够简单能让你快速建立“主从轮询”的思维它足够普及学会了能接一大半的电表、温控器、变频器它足够坑能让你提前踩到字节序、地址偏移、CRC校验这些通用问题。Modbus RTU的实操要点串口参数一般是9600/19200/38400波特率8数据位1停止位无校验或偶校验。我习惯用Modbus Poll做主机模拟Modbus Slave做从站模拟两个软件配合能快速验证报文。CRC校验是RTU的灵魂算法不复杂但容易写错。我见过有人用查表法有人用位移法实测位移法在STM32上跑一圈大概几十微秒够用。Modbus TCP的实操要点默认端口502报文比RTU多了MBAP头7字节去掉了CRC。TCP的好处是不用担心CRC和字节间隔坏处是粘包问题——一次recv可能收到两个响应。我的处理方式是先读MBAP头里的长度字段再按长度读剩余数据。地址偏移的坑Modbus文档里经常写“保持寄存器40001”但实际报文里的地址是0。40001是“PLC地址”0是“协议地址”差1。更坑的是有些厂商文档写40001对应协议地址1有些写0。我的做法是拿到设备先读一个已知寄存器用Modbus Poll试试出正确偏移再写代码。字节序的坑32位数据在Modbus里占两个寄存器字节序有ABCD、CDAB、BADC、DCBA四种。我遇到过同一品牌不同型号字节序都不一样的情况。解决办法是在代码里做一个可配置的字节序转换函数现场调试时改配置就行。# Modbus 32位浮点数字节序转换示例 import struct def modbus_to_float(regs, byte_orderABCD): # regs是两个16位寄存器按读取顺序 if byte_order ABCD: data struct.pack(HH, regs[0], regs[1]) elif byte_order CDAB: data struct.pack(HH, regs[1], regs[0]) elif byte_order BADC: data struct.pack(HH, regs[0], regs[1]) elif byte_order DCBA: data struct.pack(HH, regs[1], regs[0]) return struct.unpack(f, data)[0]3.2 西门子S7协议抓包逆向的必修课西门子S7协议是我啃得最痛苦的一个因为官方不公开文档。S7-200/300/400/1200/1500用的都是S7comm或S7comm-plus走ISO-on-TCP端口102。我学它的方法只有一个抓包。用Wireshark抓西门子PLC和上位机的通信然后逐字节分析。S7协议的核心结构TPKT头4字节 COTP头3字节 S7 PDU。TPKT头里的长度字段是整个包的长度COTP头里的LI字段是COTP头长度。S7 PDU里的功能码有读0x04、写0x05、读诊断等。读操作里有个“传输大小”参数决定一次读多少字节。S7-1200/1500的优化块访问这是个大坑。老S7-300/400的DB块是“标准访问”可以直接按偏移读S7-1200/1500默认是“优化块访问”DB块里的变量没有固定偏移不能直接读。解决办法是在TIA Portal里把DB块的“优化的块访问”取消勾选或者用符号名通过S7comm-plus读。我一般选前者因为简单。S7comm-plus的加密S7-1500的固件版本2.0以上S7comm-plus通信有加密和签名抓包也看不懂。这时候要么降固件要么用OPC UA。我后来学OPC UA很大原因就是被S7comm-plus逼的。调试工具Snap7是我用过最好的开源S7库支持S7-200到S7-1500C/C/Python/Java都有绑定。我用Python的python-snap7读S7-1200的DB块稳定跑了两年多。注意Snap7需要设置PLC的“允许来自远程对象的PUT/GET通信访问”否则连不上。3.3 OPC UA标准最全但最重OPC UA是我花时间最多的协议没有之一。它的标准文档有十几部分从信息模型到安全到传输全看完不现实。我的策略是先跑通一个客户端再回头补理论。OPC UA的核心概念地址空间AddressSpace、节点Node、节点IDNodeId、引用Reference、属性Attribute。节点ID是访问数据的钥匙格式有ns2;sTemperature这种字符串型也有ns2;i1234这种数值型。我一般用UaExpert浏览服务端的地址空间找到需要的节点ID再写代码。安全策略OPC UA的安全策略有None、Basic128Rsa15、Basic256、Basic256Sha256等。None就是不加密调试时用生产环境至少用Basic256Sha256。证书配置是新手最大的坑——客户端和服务端要互相导入证书还要设置信任列表。我见过有人调了一整天最后发现是证书过期了。订阅与监控OPC UA的订阅Subscription和监控项MonitoredItem是它的精华。创建一个订阅设置发布间隔PublishingInterval然后往订阅里加监控项服务端数据变化时会推送。发布间隔不是越小越好太小服务端压力大太大实时性差。我一般设100ms到1000ms看数据变化频率。调试工具UaExpert是免费的OPC UA客户端功能全支持浏览、读、写、订阅。Prosys OPC UA Simulation Server是免费的模拟服务端用来练手很合适。python-opcua和open62541是两个常用的开源库前者纯Python后者C实现性能更好。# python-opcua 订阅示例 from opcua import Client client Client(opc.tcp://192.168.1.10:4840) client.connect() node client.get_node(ns2;sTemperature) handler MyHandler() sub client.create_subscription(500, handler) handle sub.subscribe_data_change(node) # ... 运行一段时间后 sub.unsubscribe(handle) client.disconnect()3.4 CIP/EtherNet-IP罗克韦尔的地盘CIPCommon Industrial Protocol是罗克韦尔Rockwell主推的协议走EtherNet/IP时叫CIP over TCP/UDP。我接触它是因为一个美国客户的AB PLC项目。CIP的数据模型是对象型每个对象有类ID、实例ID、属性ID。比如读一个模拟量输入要指定类0x04、实例1、属性3。CIP的显式消息和隐式消息显式消息走TCP用于配置和诊断隐式消息走UDP用于实时I/O数据。个人开发者做数据采集主要用显式消息。显式消息的报文结构是封装头24字节 CIP命令。封装头里有命令码、长度、会话句柄等。标签访问AB PLC的变量叫“标签”Tag有原子标签和结构体标签。读标签用CIP的“Read Tag”服务0x4C写标签用“Write Tag”0x4D。标签名要带Program作用域比如Program:MainProgram.MyTag。我踩过的坑是标签名大小写敏感而且不能有空格。调试工具EtherNet/IP的调试工具不多我用过Wireshark的CIP解析插件能看报文结构。代码库方面OpENer是开源的CIP从站实现但文档少。商业库有pycomm3Python写的支持AB PLC的标签读写我用它做过几个项目还算稳定。3.5 Modbus TCP与RTU的网关转换这个单独拎出来说因为太常见了。现场很多设备只有RS-485但上位机在以太网里就需要Modbus RTU转TCP的网关。网关的坑在于透明传输和协议转换的区别。透明传输是把串口数据原样封装成TCP上位机要自己处理CRC协议转换是网关把RTU转成TCP上位机直接收TCP报文。我一般选协议转换模式省事。网关的配置串口参数波特率、数据位、停止位、校验要和设备一致TCP端口默认502IP地址要在同一网段。有些网关支持多主机但Modbus本身是单主站多主机同时轮询会冲突。我的做法是网关只接一个主站或者用轮询调度器分时复用。超时和重试网关转换会引入额外延迟一般5到20毫秒。超时时间要设得比直连大一些我一般设500ms到1秒。重试次数设2到3次太多会阻塞后续轮询。3.6 IEC 60870-5-104电力行业的规矩IEC 104是电力系统远动协议走TCP端口2404。它的数据模型是“信息对象地址”IOA每个遥测、遥信、遥控点都有一个IOA。报文类型有I帧信息传输、S帧确认、U帧控制。我学它是因为一个光伏电站项目需要读逆变器和电表的数据。IEC 104的核心机制总召唤General Interrogation是主站上电后先问一遍所有数据然后从站变化时主动上传COS。这个机制比Modbus轮询高效但实现复杂。k值和w值是发送和接收的窗口大小默认k12w8意思是发12帧没确认就停收8帧要确认。时标问题IEC 104的遥测带时标时标格式是CP56Time2a7个字节包含毫秒、秒、分、时、日、月、年。解析时要注意年份是两位2000年以后要加2000。我见过有人解析成1900年数据全乱。调试工具IEC 104的调试工具比较少我用过lib60870的开源库C语言写的有Python绑定。商业工具如Kepware支持IEC 104但贵。我的做法是自己写一个简单的客户端用Wireshark抓包对照。3.7 DL/T 645国内电表的标配DL/T 645是国内多功能电表的标准协议走RS-485波特率一般2400。它的数据域是BCD码地址是表号数据标识是4个字节。我做过一个园区电表集抄项目200多块电表全是DL/T 645。DL/T 645的坑数据标识不同厂商有差异比如读电压有的用0x02010100有的用0x0201FF00。我的做法是拿到电表先读一遍所有数据标识对照厂商文档确认。BCD码解析要注意0x12是12不是18。表号是12位BCD广播地址是999999999999。抄表策略200块表如果逐块轮询一块表读10个数据每个数据100ms一轮下来要200秒。我的优化是只读变化的数据电压电流这种变化快的读电量这种变化慢的半小时读一次。另外用广播地址做校时一次广播所有表都收到。3.8 BACnet楼宇自控的通用语言BACnet是楼宇自控协议有BACnet/IP、BACnet MS/TP、BACnet Ethernet等。我接触它是因为一个智能楼宇项目需要读空调、照明、电梯的数据。BACnet的数据模型是对象型有模拟输入、模拟输出、二进制输入、二进制输出等对象类型。BACnet/IP的实操走UDP端口47808。设备发现用Who-Is和I-Am广播读属性用ReadProperty写属性用WriteProperty。对象标识符是“对象类型实例号”比如AnalogInput:1。属性标识符有PresentValue、StatusFlags、Units等。BACnet MS/TP走RS-485波特率9600到76800。MS/TP有主站和从站主站轮询令牌。我踩过的坑是MS/TP的令牌超时主站等不到令牌会重新初始化导致通信中断。解决办法是调整令牌超时和重试次数。调试工具BACnet的调试工具我用过BACnet Scan和YabeYabe是Java写的功能全支持设备发现、读属性、写属性。代码库有bacpypesPython写的我用它做过一个楼宇数据采集网关。3.9 CANopen车载和运动控制CANopen走CAN总线速率最高1Mbps。它的数据模型是对象字典每个对象有16位索引和8位子索引。PDO用于实时数据SDO用于配置参数。我学它是因为一个AGV小车项目需要读电机驱动器的位置和速度。CANopen的PDO配置PDO映射是把对象字典里的对象映射到PDO报文里。比如把位置实际值0x6064映射到TPDO1驱动器就会周期发送位置。PDO的传输类型有同步和异步同步是收到SYNC报文后发送异步是事件触发。我一般用异步周期设10ms。CANopen的心跳和节点保护心跳是节点周期发送0x700节点ID的报文主站监控。节点保护是主站问、从站答。我用心跳因为简单。心跳时间设100ms到1s超时后主站报警。调试工具CANopen的调试工具我用过CANopen Magic和CANanalyzer前者是商业的后者便宜。代码库有CANopenNodeC语言写的开源我用它做过从站模拟。3.10 MQTT上云的最后一步MQTT不是工控协议但在工业物联网里用得越来越多。它的发布订阅模型适合多对多、跨网络的数据传输。我一般用MQTT把边缘网关采集的数据上传到云平台。MQTT的核心概念Broker、Topic、QoS、Retain、Will。QoS有0、1、20是最多一次1是至少一次2是恰好一次。工控数据我一般用QoS 1保证不丢但可能重复。Retain是保留最后一条消息新订阅者能立刻收到。Will是遗嘱消息客户端断线时Broker发布。MQTT的坑Topic设计要合理我一般用工厂/车间/设备/数据的层级。ClientID要唯一重复会导致互相踢下线。KeepAlive要设太短费流量太长断线发现慢。我一般设60秒。调试工具MQTT的调试工具我用过MQTTX和Mosquitto前者是客户端后者是Broker。代码库有paho-mqttPython写的简单好用。3.11 Profinet和EtherCAT实时以太网的边界这两个我放在一起说因为个人开发者很少直接碰。Profinet和EtherCAT都是实时以太网需要专用硬件才能达到微秒级同步。我接触它们是因为一个运动控制项目客户要求用EtherCAT伺服。Profinet走标准以太网但需要支持Profinet的网卡或芯片。个人开发者如果只是做数据采集可以用Profinet的“非实时”通道NRT读数据但需要协议栈。开源实现有p-net但文档少。EtherCAT需要专用从站控制器ESC比如ET1100、ET1200。主站有SOEM和IgH EtherCAT Master都是开源的。我用SOEM做过一个简单的数据采集能读伺服的位置和状态。但EtherCAT的配置复杂需要XML设备描述文件ESI新手不建议直接上。我的建议如果项目不是硬实时用OPC UA或Modbus TCP替代。如果必须用Profinet或EtherCAT找设备厂商要协议栈或网关。3.12 协议网关与边缘计算最后说说协议网关。一个人啃12种协议不可能每种都写一遍代码。我的做法是用边缘网关做协议转换把不同协议统一成MQTT或OPC UA上位机只对接一种协议。边缘网关的选型我用过Kepware、Ignition Edge、Node-RED。Kepware支持最全但贵Ignition Edge便宜些支持Modbus、OPC UA、MQTTNode-RED免费但工控协议支持靠插件稳定性一般。我现在的方案是Node-RED做快速原型Kepware做生产。边缘计算的逻辑网关不只是协议转换还可以做数据清洗、报警判断、断线缓存。我一般把变化死区、量程转换、报警阈值放在网关里上位机只收处理后的数据。这样上位机简单网关压力也不大。4. 常见问题与排查技巧实录4.1 通信不通的排查顺序通信不通是最常见的问题我的排查顺序是物理层→网络层→协议层→应用层。物理层串口的话先量电压RS-485的A/B线之间应该有2到6V的差分电压。网线的话看指示灯Link灯亮说明物理连接正常。CAN的话量CAN_H和CAN_L之间的电阻应该是60欧姆左右。网络层ping一下设备IP通的话说明网络层没问题。不通的话检查IP、子网掩码、网关。我见过有人IP设成192.168.1.10子网掩码255.255.0.0结果和192.168.2.10通不了。协议层用调试工具发一帧最简单的报文看有没有响应。Modbus的话读一个寄存器S7的话读一个DB块OPC UA的话浏览根节点。有响应说明协议层通没响应看错误码。应用层协议层通了但数据不对检查地址、数据类型、字节序。我一般用调试工具读原始字节再对照文档解析。4.2 数据不对的常见原因数据不对比通信不通更隐蔽。我遇到过的情况有地址偏移差1、字节序不对、数据类型不匹配、量程没转换、时标解析错。地址偏移Modbus的40001对应协议地址0还是1不同厂商不一样。我的做法是读一个已知值比如设备铭牌上的序列号试出正确偏移。字节序32位浮点数的字节序有四种我一般用调试工具试试出正确顺序再写代码。有些设备支持字节序配置改配置比改代码方便。数据类型16位整数和16位无符号整数负数会解析错。32位整数和32位浮点数解析方式完全不同。我一般先读原始寄存器再对照文档确认类型。量程转换很多设备传的是原始值比如0到32767对应0到100度。要线性转换。我一般把量程参数放在配置文件里现场可调。时标IEC 104的CP56Time2a年份是两位2000年以后要加2000。我见过有人解析成1900年数据全乱。4.3 性能优化的几个手段轮询周期太长数据不及时太短设备扛不住。我的优化手段有分组轮询、变化上传、批量读取、缓存。分组轮询把数据按变化频率分组变化快的100ms轮询变化慢的1s轮询。比如电压电流100ms电量1s。变化上传支持订阅的协议用订阅比如OPC UA。不支持订阅的读回来和上次比较变化超过死区才上传。批量读取Modbus一次最多读125个寄存器S7一次最多读PDU大小减头部。我一般把相邻地址合并成一次读减少报文数量。缓存上位机缓存最近的数据界面刷新从缓存读不直接读设备。这样界面刷新频率可以高设备轮询频率可以低。4.4 常见问题速查表问题现象可能原因排查方法解决措施串口通信不通A/B线接反、波特率不对、终端电阻没加量差分电压、换线、加120欧姆电阻调换A/B线、统一波特率、加终端电阻Modbus读不到数据地址偏移差1、从站ID不对、功能码不对用Modbus Poll试不同偏移和ID确认协议地址、从站ID、功能码Modbus数据不对字节序不对、数据类型不对读原始寄存器对照文档调整字节序、确认数据类型S7连不上PUT/GET没允许、机架槽号不对检查TIA Portal设置允许PUT/GET、确认机架槽号OPC UA连不上证书不信任、安全策略不匹配看客户端日志导入证书、统一安全策略OPC UA订阅不推送发布间隔太大、监控项没激活看服务端日志调小发布间隔、激活监控项IEC 104数据乱时标解析错、IOA不对抓包对照文档修正时标解析、确认IOADL/T 645读不到表号不对、数据标识不对用广播地址试确认表号、对照厂商文档BACnet发现不了设备广播地址不对、端口不对用Yabe试确认广播地址、端口47808CANopen通信中断心跳超时、PDO配置错看CAN分析仪调整心跳时间、检查PDO映射MQTT断线重连丢数据QoS 0、没设Retain看Broker日志用QoS 1、设Retain网关转换延迟大网关性能不足、轮询周期太长测网关延迟换高性能网关、优化轮询提示排查问题时我习惯从最简单的地方开始。先ping再telnet端口再用调试工具发报文。不要一上来就怀疑代码大部分问题是物理层和配置。5. 个人开发者的学习路径与工具链5.1 学习路径从Modbus到OPC UA如果让我重新走一遍我会这样安排第一个月只学Modbus RTU和TCP用Modbus Poll和Slave把主从都玩一遍理解寄存器、功能码、CRC、字节序。第二个月学西门子S7用Snap7读S7-1200的DB块理解ISO-on-TCP和S7 PDU。第三个月学OPC UA用UaExpert和open62541理解地址空间、节点、订阅。这三个月打底后面学其他协议就是套框架。Modbus是基础它教会你主从轮询、寄存器映射、字节序、CRC。这些概念在大多数工控协议里都有影子。S7是进阶它教会你抓包逆向、PDU结构、优化块访问。这些技能在学其他不公开文档的协议时很有用。OPC UA是天花板它教会你信息模型、安全、订阅。学完OPC UA再看其他协议会觉得简单。5.2 工具链调试、开发、测试我的工具链分三类调试工具、开发库、测试工具。调试工具ModbusModbus Poll、Modbus Slave、Modbus调试助手S7Snap7 Client Demo、WiresharkOPC UAUaExpert、Prosys OPC UA Simulation ServerCIPWireshark CIP插件、pycomm3IEC 104lib60870、WiresharkBACnetYabe、BACnet ScanCANopenCANopen Magic、CANanalyzerMQTTMQTTX、Mosquitto开发库Modbuspymodbus、libmodbusS7python-snap7、Snap7OPC UApython-opcua、open62541CIPpycomm3、OpENerIEC 104lib60870BACnetbacpypesCANopenCANopenNodeMQTTpaho-mqtt测试工具模拟从站Modbus Slave、Prosys OPC UA Simulation Server模拟主站Modbus Poll、UaExpert抓包Wireshark、tcpdump串口串口调试助手、ComAssistant5.3 代码组织一个网关的架构我做过一个多协议网关架构是这样的底层是协议驱动每个协议一个模块统一接口read()和write()中间是数据映射把不同协议的地址映射到统一的数据点上层是输出支持MQTT、OPC UA、REST。这样加新协议只要写一个驱动不影响其他部分。协议驱动接口class ProtocolDriver: def connect(self): pass def read(self, address, count): pass def write(self, address, values): pass def disconnect(self): pass数据映射用配置文件定义比如{modbus: {slave_id: 1, address: 0, type: float32, byte_order: ABCD}}。输出MQTT用paho-mqttOPC UA用open62541REST用Flask。5.4 避坑心得少走弯路的几个建议不要重复造轮子能用开源库就用开源库除非有特殊需求。我见过有人自己写Modbus协议栈结果CRC算错调了一周。先跑通再优化不要一开始就追求完美架构。先让数据通再考虑性能、稳定性、扩展性。文档和抓包结合文档不全的协议抓包是最好的老师。Wireshark能解析大部分工控协议不能解析的看原始字节。现场调试留后路现场调试时我一般带一个已知好的设备做对照。比如调Modbus带一个Modbus Slave模拟器调OPC UA带一个UaExpert。版本控制协议配置、代码、文档都放Git。现场改的配置要提交否则下次忘了改了什么。写笔记每学一个协议写一篇笔记记录最坑的三个点和最顺手的工具。三年下来笔记比任何教程都管用。注意工控协议的学习没有捷径但有方法。我的方法就是“用一学一、抓包对照、写笔记”。一个人啃12种协议靠的不是智商是耐心和记录。最后再分享一个小技巧如果你要学一个新协议先找它的“最小可用报文”。比如Modbus的最小可用报文是读一个保持寄存器S7的最小可用报文是读一个DB块的一个字节OPC UA的最小可用报文是浏览根节点。把这个最小报文跑通再扩展。这个技巧帮我省了很多时间希望对你也有用。
返回列表