ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

个人开发者如何啃下12种工控协议:从Modbus到OPC UA的全流程实战

2026/9/20 7:27:05 拓冰建站 浏览量
个人开发者如何啃下12种工控协议:从Modbus到OPC UA的全流程实战 经常有同行问我你一个做边缘采集的个人开发者是怎么敢接那种带12种PLC、CNC、电表和变频器项目的说实话三年前我也觉得“工控协议”这四个字自带劝退属性。每家设备厂都有自己的封闭协议手册动辄几百页有的还不对外公开网上能搜到的资料经常是互相抄的旧版本。但2025年初我自己盘了一遍手上的交付项目发现我在同一个采集盒子里已经把 Modbus RTU、Modbus TCP、S7comm、OPC UA、Profinet、EtherCAT、EtherNet/IP、CANopen、DL/T645、BACnet、三菱MC协议、Focas发那科CNC这12种协议全部跑通了其中好几套还在产线上稳定跑了一年多。这篇东西不聊虚的就把我一个个人开发者啃下12种协议的全过程拆开写怎么给协议定优先级、怎么用抓包逆推报文结构、怎么写一个能塞下多种协议的多协议网关、怎么在没有真实PLC的情况下把环境调通以及那些文档里永远查不到、只能靠现场踩坑换来的经验。想接工厂数采、做协议转换网关、或者只是被客户逼着去对接某个冷门设备的人都能从这里抄到点作业。1. 先盘清楚12种协议到底在解决什么问题很多个人开发者一上来就上网搜“XX协议教程”然后被各种概念砸晕其实方向错了。代码可以后面写但你必须先搞清楚一个根本问题工控协议是用来干什么的说白了就是设备与设备之间、设备与上位机之间交换数据的“语言”。PLC要告诉触摸屏这里温度高了上位机要通知变频器把转速降下来电表要定时把电量上传给管理系统——这些事情都靠协议完成。不同厂商、不同年代的设备选了什么“语言”你就得学什么“语言”。这跟做Web开发只需要懂HTTP不一样工控现场是几十种协议并存的而且它们之间彼此不能通信所以你才需要一个中间节点去做翻译这种节点就是个人开发者最常见的切入点数采网关、协议转换器、边缘采集盒子。1.1 按通信层级给协议做一张地图初学者最大的误区是拿到一种协议就从头到尾啃。我建议先把12种协议按通信层级分个类因为它们的底层承载方式完全不同调试时的思路也完全不同。我自己的分类方式是四类第一类是串口型协议。最典型的是Modbus RTU、DL/T645、三菱早期编程口协议走的是RS232/RS485这种串口物理链路数据量小、实时性要求低、帧结构简单非常适合入门。第二类是工业以太网协议。包括Modbus TCP、S7comm、OPC UA、Profinet、EtherCAT、EtherNet/IP、三菱MC协议走以太网时它们都跑在标准以太网上但应用层格式差异巨大有的用TCP承载有的用UDP承载还有EtherCAT这种直接在以太网帧里塞过程数据的现场总线。第三类是现场总线协议比如CANopen这种走CAN物理层一般出现在伺服、步进、传感器和阀岛这类设备上调试它需要CAN卡或者支持SocketCAN的Linux环境。第四类是行业级规约比如DL/T645是电力行业的电表通信规约BACnet是楼宇自控领域的协议它们的字段定义和行业业务强绑定做能源管理和楼宇项目时绕不开。它们之间的区别用生活里的话类比就是Modbus RTU像两个人用对讲机喊话内容简短、距离有限OPC UA像两个人用邮件系统往来格式规范、还能加附件EtherCAT像一列在铁轨上高速循环跑的火车每站只装卸自己那一节车厢的货效率极高但路轨必须是专用的。1.2 个人开发者优先啃哪几类优先级排序逻辑12种协议不可能平均用力时间也不允许。我的排序逻辑非常简单以项目出现频率和上手成本为准而不是以协议本身的技术含量为准。排在第一位的是Modbus RTU和Modbus TCP。为什么因为几乎所有工业设备不管多老的型号都会留一个Modbus接口当“保底方案”。电表、温控器、变频器、UPS、传感器甚至很多PLC也支持Modbus从站或主站。你把这个协议学透了至少能解决现场60%的对接需求而且它最容易搭环境做实验我后面会详细讲。第二梯队是S7comm、三菱MC协议、OPC UA和EtherNet/IP。这些是在项目里出现频率最高的几种因为国内市场西门子和三菱的PLC存量太大了而OPC UA是近年新建工厂做数据采集的标配接口。如果你接的工厂项目比较多这四个大概率会不断遇到值得花时间深耕。第三梯队是Profinet、EtherCAT和CANopen。它们主要出现在运动控制和伺服驱动场景Profinet和EtherCAT通常需要专门的硬件网卡或者软PLC仿真环境上手门槛比前两类高但一旦你开始接视觉定位、CNC联动、机器人控制这类项目就躲不掉了。最后是DL/T645、BACnet和Focas。这三个跟具体行业强绑定做电力采集会碰到DL/T645做楼宇自控会碰到BACnet做机床联网会碰到Focas。它们的学习曲线反而平缓都是跟着行业需求走就行。这里插一句我自己的心得个人开发者不要试图“学完”协议再去找项目而是“接到什么项目就学什么协议”把协议学习嵌入到交付过程里效率至少翻倍。因为你带着真实需求去读手册一眼就知道哪些章节要精读、哪些章节可以直接跳过比空啃一本书强太多。2. 新协议上手只要三步抓包、比对、逆向推结构很多人拿到新协议习惯先去下载官方SDK、看文档、调库结果被封装好的库拖住反而搞不清楚协议底层在干什么。我现在的做法刚好反过来先不管SDK直接抓包看原始报文等理解了协议本质再决定要不要用库。这个方法的核心步骤就三步第一步确认端口和传输方式第二步用Wireshark或串口抓包把请求和响应帧抓下来第三步对照官方手册把报文里的每个字段对号入座。做完这三步你对这个协议的了解已经胜过80%只会调SDK的人。2.1 从 Modbus 报文看“协议到底长什么样”我以最经典的Modbus TCP报文为例给完全没接触过的人开个窍。假设我要读PLC里从地址0开始的2个保持寄存器Wireshark里抓到的请求帧是这样的02 00 00 00 00 06 01 03 00 00 00 02看第一眼是不是觉得全是乱码其实拆开就清楚了。前6个字节是Modbus TCP特有的MBAP头02 00 事务标识符这条请求的编号同一事务的响应里这个值必须一样 00 00 协议IDModbus固定为0 00 06 后续字节长度表示从站号开始一共有6个字节 01 从站号这条请求发给1号从站 03 功能码3代表“读保持寄存器” 00 00 起始寄存器地址的偏移这里是0 00 02 要读的寄存器数量读2个与之对应响应帧通常是这样的02 00 00 00 00 05 01 03 04 0A 0B 0C 0D前6个字节还是MBAP头其中00 05说明后面有5个字节。接着是01 03从站号和功能码原样返回04表示后面有4个字节的数据然后0A 0B 0C 0D就是两个寄存器的原始值。就这么简单一次“读数据”的完整过程就是上位机发一个请求PLC回一个响应。你可能已经发现了Modbus TCP的报文结构异常规整这其实是很多老牌工控协议的共同特点。所以我的建议是新手入门工控协议千万要从Modbus开始因为它能让你在半小时内建立起“协议报文到底长什么样”的感觉。有了这个底子你再去啃S7comm、OPC UA那些结构复杂的协议理解成本会低很多。2.2 用 Wireshark 拆解 S7comm 和 OPC UAS7comm是西门子PLC的私有协议端口是102。第一次用Wireshark抓S7comm报文的人经常会被吓一跳因为它的头部叠了三层TPKT、COTP、S7 PDU。这也是工业协议跟互联网协议的一个明显区别工业协议经常基于TCP但在应用层里再套一层自己的“包装”。抓包时Wireshark的过滤器直接写tcp.port 102就能只显示S7comm流量。你看第一个包TPKT头固定以03开头后面跟着总长度COTP层里最关键是TPDU类型和TSAP字段TSAP的作用是告诉PLC“我要用哪种方式访问你”S7-1200/1500默认的本地TSAP通常是0x0100远程TSAP是0x0102。很多人连接S7comm报错排查到最后都是TSAP没配对这个后面踩坑部分我再细说。再往下看S7 PDU层你会看到一个类似函数的调用格式里面有功能码如0x04代表读请求、数据类型区域、DB块号、起始偏移和长度。你只要把这些字段映射到西门子PLC的变量表就能明白上位机读取M区变量和读取DB块数据时报文里的“区域号”是不同的。理解了这一点你再去调python-snap7这类库心里就有底了知道它内部到底帮你拼了什么报文。OPC UA的端口是4840逻辑比S7comm更复杂因为它是面向服务架构的握手流程长。抓包看的话连接建立后你先会看到Hello消息然后是OpenSecureChannel、CreateSession、ActivateSession一套流程走完才能做Read或Subscribe。我第一次看OPC UA二进制协议时也是一脸懵后来我用Prosys的OPC UA模拟服务器配合Wireshark把握手流程一步一步拆开看再回头看实现的库函数就完全对上了。2.3 建立自己的“协议对照笔记模板”学协议最大的敌人是“学了后面忘前面”。所以我很早开始就维护一个协议对照笔记每接触一种新协议都按固定模板记录。模板长这样协议名称 承载方式串口 / TCP / UDP / 其他 默认端口 帧边界判断方式固定长度 / 结束符 / 时间间隔 字节序大端 / 小端 / 可配置 是否有状态机有/无状态列表 握手流程 关键报文示例请求响应 常用功能码或命令字 异常返回格式 官方文档获取方式 模拟器或调试工具 我踩过的坑这个模板的价值在于它能帮你快速横向比较不同协议。比如你会发现Modbus RTU按时间间隔判断一帧结束DL/T645按固定帧头和帧尾加结束符判断而CANopen则是CAN帧天然有固定边界。这些差异就是你后续设计多协议网关时最需要关注的地方。我还有一个小习惯每学完一种协议就尝试亲手构造一个最小可用的请求帧用脚本发出去看看设备会不会回应。如果你连一个协议里的最核心读请求和写请求都能闭着眼拼出来那就说明你是真的入门了。3. 多协议网关架构把12种协议拧进一个框架啃完12种协议不是终点终点是让它们在一个采集程序里和谐共存。很多个人开发者的项目做到一半就死在“协议越加越多代码越来越乱”这种问题上。这跟盖房子一样一开始没打地基后面每加一层墙就塌一次。我自己的方案是用一套分层架构把12种协议当成不同的“翻译官”全部塞进同一个面孔的采集框架里。核心思路是底层不管是什么协议最终都转成统一的点位值上层不管是连数据库、MQTT还是MES系统都只跟统一的点位模型打交道。3.1 协议适配层设计新增一种协议只写一个 Codec网关的第一层我称之为适配层负责把每种协议封装成一个独立模块。每个模块对外暴露统一的接口比如connect、disconnect、read、write、subscribe。你不需要每个模块都从零写很多协议都有成熟的库比如python-snap7做S7comm、opcua库做OPC UA、pymodbus做Modbus你要做的只是把它们的差异封装起来。我习惯用注册表模式来组织这些模块。在代码里维护一个字典把协议名映射到对应的会话类PROTOCOL_CODECS { modbus_tcp: ModbusTCPSession, modbus_rtu: ModbusRTUSession, s7comm: S7commSession, opcua: OpcUaSession, profinet: ProfinetSession, ethercat: EthercatSession, ethernet_ip: EthernetIpSession, canopen: CanopenSession, dl645: Dl645Session, bacnet: BacnetSession, mitsubishi_mc: MitsubishiMcSession, focas: FocasSession, }这样带来的好处是显而易见的新增一种协议时只需要写一个新的Session类然后在注册表里加一行其他调度代码、点位表、数据上报逻辑完全不用动。我在实际项目中通常一个周末就能把一种新协议的接入搞定大部分时间花在调试抓包上而不是改框架。3.2 设备模型与点位表让上层不关心底层是什么协议适配层之上我放了一个“设备模型”的概念。不管底层是485串口接的电表还是TCP连接的PLC我在配置里都把它描述为一个统一的设备对象。设备对象的重点是一个点位表也就是这个设备上要采集哪些变量每个变量的协议地址是什么数据类型是什么要不要乘系数。常见的点位表配置是这样的{ device_name: 一号车间3号变频器, protocol: modbus_tcp, endpoint: 192.168.10.15:502, poll_interval_ms: 1000, points: [ { name: current_freq, address: 40001, data_type: uint16, scale: 0.01 }, { name: run_status, address: 10001, data_type: bool } ] }这个点位的地址是逻辑地址适配层在读取时自动把逻辑地址换算成协议里的实际地址。这样设计还有一个额外的好处如果客户现场更换了设备品牌你不必改上层代码只需要在配置里把protocol字段从modbus_tcp改成s7comm再把点位表地址改一下就行。对于个人开发者来说这就是救命稻草因为你永远不知道客户会在验收前一周换什么设备。3.3 真实网关的线程模型和内存布局有了分层架构紧接着要考虑的是并发模型。工控现场通常同时连接几十台设备但有些PLC的连接数有限轮询太快会直接把PLC搞死轮询太慢又会丢数据这个平衡需要仔细调。我用的线程模型是“每连接一线程 共享数据区”。每个设备的采集会话跑一个独立线程线程里按点位表依次发送请求收到响应后把值更新到一块共享内存里。共享内存本质上是一个字典key是设备名加点位名value是带时间戳和数据质量标记的结构体。上层服务MQTT推送、REST API、告警逻辑只读这块共享内存不直接跟协议打交道。这样隔离之后某个协议卡死或者超时影响的只是它自己那个线程不会拖垮整个系统。我在代码里还加了一个看门狗机制每5秒检查一次所有采集线程的健康状态发现某个线程超过3个轮询周期没有更新时间就会自动重启这个协议会话同时在上报数据里把该设备标记为离线。这套机制让我省了不少半夜去现场处理的麻烦。对个人开发者来说线程数不用管太多但有一个原则必须记住永远不要在协议回调函数里做耗时操作比如写数据库、发HTTP请求。回调里只做解析把结果扔给队列或者共享内存其他事情让别的线程去做。4. 调试环境搭建没有真实PLC也能把协议调通个人开发者最尴尬的地方在于手里没有西门子、倍福、AB这些设备但实战调试又必须有目标对象可以对话。好在现在有不少模拟器和软PLC方案能让你在电脑上把协议链路打通剩下的事就是带上U盘去现场联调。搭建调试环境不是可有可无的步骤它直接决定了你写协议代码的效率。我第一次做EtherCAT时因为没有仿真环境只能在客户现场边改边试一个状态机问题折腾了我两天。后来我学会了在电脑上先搭一套仿真环境在酒店里就把问题消掉了现场基本一遍过。4.1 软PLC和模拟器选型清单下面这份清单是我自己调试时用的组合免费、稳定、覆盖面广个人开发者够用了协议调试工具/模拟器说明Modbus RTU/TCPmodpoll / Modbus Slavemodpoll是命令行工具适合写自动化脚本Modbus Slave能模拟从站S7comm西门子PLCSIM Advanced可以模拟S7-1200/1500支持S7comm但需要对应版本的仿真授权OPC UAProsys OPC UA Simulation Server免费版支持99个节点做测试够用ProfinetCODESYS软PLC在Windows下可以跑软PLC做Profinet IO设备仿真EtherCATTwinCAT EtherCAT虚拟从站倍福TwinCAT可以做软主站配合虚拟从站工具练手EtherNet/IPcpppo库Python有现成的模拟器脚本能模拟AB PLCCANopenPython-CAN vcan虚拟CANLinux下用vcan虚拟CAN口不需要真实CAN卡DL/T645部分电表厂商提供模拟软件或者用串口助手配合报文模板手工模拟BACnetYABEYet Another BACnet Explorer能模拟BACnet设备也能做浏览器发现三菱MC协议GX Works2/3仿真三菱官方PLC编程软件自带的仿真器Focas发那科官方Focas库 模拟CNC没有现成模拟器但可以用官方库自带demo连模拟数据我个人的实验环境主力是两台机器一台Windows跑软PLC和模拟器一台Linux跑采集网关和Wireshark。Windows的模拟器选择多Linux的抓包和自动化脚本能力强两者配合基本无敌。4.2 Docker化部署和网络隔离的坑代码写完最终要部署到Linux工控机上。我现在所有网关项目都打成Docker镜像目的有两个一是交付现场环境千差万别Docker能保证跑起来的行为一致二是自己本地开发和现场部署之间没有环境差异省去“明明本地好的到现场就崩”这种经典事故。一个典型的最小化docker-compose配置长这样version: 3 services: gateway: build: . network_mode: host devices: - /dev/ttyUSB0:/dev/ttyUSB0 volumes: - ./config:/etc/gateway restart: unless-stopped这里有一个坑必须踩过才知道工控场景一般不建议用Docker默认的bridge网络因为很多PLC摆在内网固定IP段bridge网络会导致容器里的程序找不到设备。我直接用了network_mode: host让容器共享宿主机网络栈省去端口映射和网络转发带来的异常。另一个经常踩的坑是串口设备映射。如果你用USB转485接电表一定要在docker-compose里把对应的/dev/ttyUSB0设备文件映射进容器否则容器里根本看不到串口。多台设备时你还需要通过udev规则把USB设备绑定为固定名称比如/dev/rs485_meter_1不然Linux重启后设备名会随机变化程序就会连错设备。这个细节我在现场吃过亏后来用udev规则加USB序列号绑定解决了。5. 踩坑实录个人开发者最容易栽的 5 个地方协议文档永远只会教你理想情况怎么用但现实是设备固件版本、接线方式、PLC组态、防火墙设置都可能让代码跑不起来。这几年的项目里我整理了一堆“非典型”故障挑5个最常见的分享出来每一个都是真金白银换来的经验。5.1 寄存器地址偏移PLC地址和协议地址隔着一位很多第一次写Modbus的人拿着点位表看到“40001”就在协议帧里填地址40001结果设备永远返回异常。原因在于点位表里的40001是PLC编程软件里的“逻辑地址”而Modbus协议帧里的地址是从0开始的偏移量。40001对应的协议地址实际上是040002对应1以此类推。你要是把40001当协议地址填进去等于用了越界地址设备当然不给读数。这个换算关系不同PLC品牌还不一样有的要减1有的要减40001有的直接就是16进制地址。我的做法是在点位表里约定好使用“协议原始地址”然后写一个转换函数所有逻辑地址在适配层完成换算不要在点位表里混用两套体系否则后续维护必炸。5.2 RS485的常见坑接线、终端电阻、帧超时RS485是老生常谈但每次都能撂倒一批人。常见故障包括A/B线接反导致超时、通信距离太远线缆质量差导致乱码、没有终端电阻导致总线反射、波特率设置不同导致设备无响应。最难受的是帧超时问题。Modbus RTU协议规定一帧的结束通过“3.5个字符时间的静止”来判断所以如果你上位机读串口时一次只读一个字节就立刻交给解析器那你很可能把一帧拆成好几块永远解析不出来。正确做法是持续读取直到串口空闲时间超过一帧间隔再按帧处理。我自己写了一个简易的串口接收器用超时判断帧边界实测下来比固定读字节数稳定得多。这里还想多说一句不要图便宜买十几块钱的USB转485模块。工业现场的干扰和地电位差便宜的模块很容易丢包甚至烧毁。我用的是带磁隔离的USB转485模块价格贵几十块但能帮你省掉大量排查时间。5.3 EtherCAT状态机不动的排查EtherCAT在初始化时会走一套状态机Init - PreOP - SafeOP - Op。刚到现场的EtherCAT设备经常会卡死在PreOP或者安全态导致主站收不到过程数据。排查思路先看AL状态码寄存器0x0130它会把卡住的详细原因打出来然后重点检查PDO映射对不对、DC同步是否配置、从站是否完成了参数配置。还有一个特别常见的坑是用USB网卡跑EtherCAT主站工具直接提示“没有可用的实时网卡”因为EtherCAT对以太网卡的实时性要求很高USB网卡的中断延迟完全不合格。最好使用板载Intel千兆网卡或者支持EtherCAT的主站专用网卡。5.4 S7comm连接挂不上的排查S7comm连接不上十有八九是TSAP配置出了问题。TSAP的作用是传播场景信息西门子PLC会根据本地和远程TSAP来决定是否允许连接。S7-1200/1500通常要求本地TSAP为0x0100、远程TSAP为0x0102但有些老S7-300项目会用0x0100和0x0100的组合。如果你在文档里看到两个TSAP值却不知道选哪个直接用Wireshark抓一次PLC与其他上位机的正常通信看看成功连接的包是怎么写的照抄就行。另一个坑是S7-1500的访问保护。新出厂的1500默认启用访问保护你从外部读取数据会被拒绝。现场处理办法是在PLC组态里把“允许在无证书的情况下访问”打开或者用官方工具把设备证书导出来配置到你自己的程序里。5.5 上位机采集与平台对接的时序问题这个坑不讲协议本身而是讲采集和上报之间的数据一致性问题。我用过一段时间在每个采集线程里直接把点值推送到云平台结果某天用户反馈数据跳变排查后发现是多个线程同时读写同一个变量的内存导致读到半新半旧的数据。后来我改造了数据访问方式共享内存里每个点位保存为一个包含值、时间戳、质量戳的对象写入时整体赋值读取时整体快照。这样即使某个时刻值正在更新读到的一定是上一版的完整状态不会出现半个新值。给上层推送数据时也统一从快照模块读取不要直接访问底层的临时变量。这个问题在协议数量变多之后尤其明显因为不同协议的刷新周期不一样Modbus可能1秒刷一次EtherCAT可能10毫秒就刷一次如果上层按自己的节奏去拉数据很容易遇到“旧包新包”混合的脏数据。统一快照是解决这个问题的基本思路也是做一个稳定网关的底线要求。6. 啃完这12种协议之后可以做什么产品经常有开发者问我花这么大力气啃协议除了接外包还能做点啥我的回答是能做的事太多了前提是你别把自己定位成“写协议解析的人”而是定位成“工业数据链路的打通者”。协议本身不值钱值钱的是你基于协议能力做出来的产品和解决方案。6.1 工业协议转换网关最常见的落地方向是协议转换网关。现场一个设备只有Modbus RTU接口但管理系统只认OPC UA怎么连这就需要一台设备从Modbus RTU侧采集数据转换成OPC UA服务端让管理系统来读。这种网关做出来之后无论是作为硬件盒子卖还是作为Docker镜像部署在客户服务器里附加值都远高于单纯的编码服务。我做这类项目时的一个体会是转换网关最容易出问题的地方不是协议解析而是点位映射关系太复杂。客户往往有几百个点要映射你让他们在配置文件里挨个手敲一定会出错。所以我后来在网关里加了一个web配置界面客户自己在浏览器里点点就能建立两边点位的映射交付时的沟通成本降了一大截。6.2 边缘数采盒子的实际落地另一个方向是边缘数采盒子本质上是一个小型Linux设备加采集程序再加云上送模块。它和转换网关的区别在于转换网关强调“协议到协议”数采盒子强调“协议到平台”。数采盒子前端的协议能力和网关是一样的后面则通常接MQTT、InfluxDB、MySQL或者企业自己的API。客户工厂里几十台不同品牌设备通过盒子采集后平台里看到的是统一格式的设备模型和实时数据。这个方向的市场需求很旺盛因为很多中小工厂没有能力自建一套完整OT数据链路。做数采盒子时我踩过的一个坑是离线缓存。现场网络抖一抖数据传不上去如果不上缓存客户后台就会看到断档的数据体验很差。后来我加了本地SQLite缓存断网时数据先落盘恢复联网后按时序补传到平台这个功能几乎成了所有客户的硬性要求。6.3 代码之外更值钱的设备调试经验和现场沟通最后聊点代码之外的东西。啃下12种协议之后我发现自己真正的竞争优势不是能从报文里解析出数据而是具备了提起工具包就能去现场把问题搞定的能力。客户不会因为你“懂12种协议”而多付一分钱但会因为你“在30分钟内把一台陌生设备接到系统里”而对你产生信任。这种能力由两部分组成一部分是设备调试的经验知道先看通信灯、再抓包、再查文档另一部分是现场沟通能力能跟电工师傅说清楚“我需要你把PLC的IP改成这个段”能跟车间主任解释“你这台设备的数据要经过一个网关才能上云”。个人开发者单兵作战没有大公司那种售前支持唯一能依赖的就是这种复合能力。协议是敲门砖但真正让你在行业里站住脚的是你把协议落地到真实产线的本领。我个人的体会是协议学习这条路没有捷径但也不需要天赋它更像跑马拉松前几公里最痛苦等你把Modbus啃透、亲手抓过几个包、踩过几次串口和TCP的坑之后后面的协议就是触类旁通的事。很多人被“12种”这个数字吓住实际上你真正需要做的是把第一个吃透然后用一套方法和框架去复制成功经验。做工业数据这条线永远在跟老旧设备和新旧协议打交道但每一次打通一个“不可能”的设备那种快感是写普通业务代码完全没法比的。