ARTICLE DETAIL

资讯详情

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

SECS/GEM协议实战:从HSMS配到S6F11调试的完整链路

SECS/GEM协议实战:从HSMS配到S6F11调试的完整链路 做半导体设备软件这行SECS/GEM协议是躲不开的一道坎。不管是晶圆搬运设备、薄膜沉积设备、刻蚀设备还是后道测试分选机要向上对接MES或APC系统有一套统一的通信规范要比每家厂商各玩各的方便得多。我最早接触SECS/GEM是在一套CVD设备改造项目上当时甲方只丢过来几份SEMI标准文档让我尽快把设备的上传数据和下发的控制指令跑通。那阵子从服务端配置到客户端调试来回折腾踩过不少坑也慢慢摸清了套路。这篇文章就把我在实践中走通的一条完整链路分享出来重点讲设备端服务端怎么配置、主机侧客户端怎么调试以及常见问题怎么排。适合刚接触SECS/GEM、拿着标准文档不知道从哪下手的工程师参考。1. 项目背景与核心思路拆解1.1 SECS/GEM不是单一协议而是一整套设备会话规则很多新手第一次接触SECS/GEM容易把它当成一个协议其实它是SEMI组织发布的一整套标准和模型的合称。核心包括SEMI E4SECS-I物理传输层定义早期用RS-232串口传输报文。SEMI E5SECS-II消息内容定义规定报文的格式、数据类型和编码。SEMI E30GEM设备通用模型规定设备与主机之间如何建立会话、如何上报状态和事件、如何响应远程命令。SEMI E37HSMS基于TCP/IP的高速消息服务属于E4在以太网时代的替代方案。我最常用的一句话形容这套标准MES是工厂的“大脑”设备是“手脚”SECS/GEM就是让两者沟通的“肢体语言”。主机的任务是发出请求、接收状态设备端的任务是响应请求、主动上报数据。协议本身解决的是“这句话语法怎么组织”“这个会话怎么建立”“这套消息怎么拆装”三个问题。在实际项目中服务端通常是设备设备作为被控制器客户端是主机MES/APC。但严格来说在SECS/GEM的语境里“服务端”表示提供监听的一方对应HSMS被动方“客户端”通常指主动发起TCP连接的Host侧。搞清楚这个概念后面的配置才不会绕晕。1.2 这个项目要打通的最短链路回到我当时的项目需求其实并不复杂设备端需要把关键工艺参数周期性上报同时能接收来自MES的启停控制。拆解下来只需要打通的链路有传输层通HSMS连接能建立SELECT握手成功。会话层通S1F13/S1F14建立通信设备进入在线状态。业务层通事件上报、设备常量读取、远程命令执行。整个方案里设备端作为HSMS被动方在固定端口上监听TCP连接主机侧用脚本模拟一个主动连接的客户端做调试。为什么这么选因为对于设备软件来说被动模式更稳定。设备不知道MES什么时候会重启被动监听让MES侧可以随时重连不用设备端做复杂的断线重连状态机。这个设计思路对后续很多项目都有借鉴意义。2. SECS/GEM协议栈关键概念速通2.1 HSMS与SECS-I两条物理链路怎么选先说传输层。老式半导体设备大多用SECS-I也就是RS-232串口通信波特率一般2400到38400报文之间有T3、T4这样针对串口的超时控制。串口通信的优点是可靠、稳定、抗干扰但劣势也很明显数据量一大就变成瓶颈。现在主流设备都转向HSMS走TCP/IP。默认端口号是5000这个端口在SEMI E37里并不强制但几乎所有设备默认都用它很多调试工具默认连的也是5000所以项目里没有特殊说明优先用5000。HSMS配置最核心的参数是这么几个参数说明常见取值IP地址设备侧监听地址设备网卡IP如192.168.1.50端口号TCP监听端口5000Device ID设备标识会话建立后在报文中出现通常Host是0设备是1范围0~32767主动/被动谁发起TCP连接设备端一般设为被动PassiveT5建立连接重试间隔4sT6等待回复超时5sT7会话空闲超时10sT8字节间超时5sTCP下影响较小这里面的坑在于T7和Linktest。很多项目配置完IP、端口、Device ID后连接一开始是通的放一个晚上就断了第二天醒来发现日志里全是“连接已关闭”。原因多半是T7超时——链路上一段时间没有消息设备判定会话失效主动把连接断掉。解决办法是在主机侧周期发送Linktest.reqHSMS控制消息SType5设备回复Linktest.rspSType6相当于一次心跳。心跳间隔一般小于等于T7比如T7设10s心跳设5s或者每次空闲超过5s就发一次实测比较稳。2.2 SECS-II报文到底长什么样SECS-II报文的格式是整个协议最需要啃的部分。一条完整的HSMS数据消息在TCP层是这样的4字节的消息总长度接着是10字节的HSMS头部最后是SECS-II的数据体。头部结构我用一张表列出来字节序号长度含义0~34B消息总长度包含10字节头部和整个数据体4~52BSession ID即Device ID61BStream号高位是W bit是否等待回复71BFunction号81BPTypeSECS-II固定为0x0091BSType数据消息为0x00控制消息为其他值比如主机发送S1F13 W报文十六进制就是这样的00 00 00 0A 00 00 81 0D 00 00 00拆开看总长度0x0A表示总长10字节没有数据体Session ID是0Stream/Function是0x81/0x0D其中最高位0x80就是W bit表示这是一条需要回复的主消息PType0x00SType0x00是一条SECS-II数据消息。这里最关键的是W bit。SECS/GEM里一个事务是“主消息Primary Message 副消息Secondary Message”的组合。主消息必然带W bit1对方收到后必须回一条W bit0的副消息。比如S1F13建立通信请求是主消息设备必须回S1F14S2F17时间和日期请求是主消息设备必须回S2F18。如果主机发出一条W1的消息后长时间没等到副消息就会触发T6超时设备侧甚至会上报S9F9锁死该事务。再说数据体的编码。SECS-II的数据内容由Data Item数据项组成每个Data Item的格式是1字节格式码 1~4字节长度 数据内容。格式码的低6位表示类型高2位表示长度字段占用几个字节。常用类型有这些格式码低6位类型说明0x00L列表方便嵌套数据0x01B二进制0x03AASCII字符串0x08I432位有符号整数0x0AF432位浮点数0x0EU432位无符号整数举个例子一个内容为字符串ABC的ASCII项编码是03 03 41 42 43。第一个0x03是ASCII类型且长度只占1字节第二个0x03表示长度是3后面就是A、B、C三个字节。列表则是把多个项按顺序放在一个L里面常用于事件上报、设备常量等复杂结构。初看这些字节有点吓人但用脚本解码后就是一目了然的字典。2.3 GEM核心模型速览GEM标准E30最大的贡献是把设备的“行为模式”给规范了让主机不用关心设备内部实现只要按标准模型操作就通用。里面有几个核心概念调试中会反复出现状态模型设备分为OFF-LINE离线、ONLINE-LOCAL在线但本地控制、ONLINE-REMOTE在线且远程控制等状态。主机通过S1F1/S1F2查询状态通过S1F15/S1F16、S1F17/S1F18切换在线/离线。事件Event设备有需要主动告知主机的时刻比如“一次配方执行完成”“发生报警”用CEIDCollection Event ID标识。报警Alarm报警也算一种特殊事件用ALID标识主机可以查询和使能/禁止。设备常量Equipment Constant可读可写的设备参数用ECID标识。比如工艺腔温度上限、报警开关等。远程命令Remote Command主机可以发的控制指令用RCMD标识比如START、STOP、PAUSE。状态变量Status Variable设备可被主机查询的数据点用SVID标识比如当前温度、当前步骤。和这些ID配套的还有报告Report用RPTID标识。事件上报时S6F11消息里会携带CEID和一组报告数据报告里可以包含多个SVID的值。要记住这些ID不是随便填的它们必须在设备端提前定义好并且在客户端调试时严格匹配否则主机解析出来的数据全是乱的。3. 服务端配置设备端怎么把SECS/GEM跑起来3.1 HSMS服务端参数配置要点别急着写代码先理清参数。设备端作为HSMS被动方最基础的配置就是上面那张表的IP、端口、Device ID。实际项目中设备可能有多张网卡有连车间内部网络的有连生产线的一定要确认HSMS监听在哪张网卡上端口不能被防火墙挡掉这个最容易忽略。设备ID这里多说一句。在HSMS头里SELECT握手阶段Session ID暂未建立用的是0xFFFF一旦SELECT成功后续所有SECS-II数据消息里的Session ID就是本设备的Device ID。如果主机侧配置的Device ID和设备侧不一致比如主机发来的消息里Device ID是2设备侧配置的是1这时候设备会直接不理你或者回一条S9F1“无法识别的设备ID”。调试时先确认两边的Device ID都一致最好写成常量配置部署时通过配置文件下发。T5、T6、T7这三个定时器设备端不同角色的行为不一样。设备作为被动方主要负责响应所以T6要重点配置——主机发来一条主消息后设备应在T6时间内回副消息否则主机会超时。T6设得太短在业务处理慢的时候容易误报太长主机侧可能已经放弃等待了。我习惯按标准默认值5s如果设备业务很重比如文件上传、工艺参数计算再放宽到8~10s但不要无脑放大否则主机侧也会等得不耐烦。T7主要影响的是连接保活设备端一般会实现一个看门狗超过T7没有收到任何消息就断开连接。如果现场根本没有心跳机制T7设10s就会经常断开此时要么把心跳加上要么把T7调大。但调大T7不是长久之计它掩盖了主机侧没有实现Linktest的问题。规范点做还是让主机发心跳。T8在HSMS场景下重要性没那么大。它是SECS-I遗留的字节间超时TCP传输本身不会出现字节级粘包的问题但有些实现仍然会用T8来防止TCP半连接状态下的假消息所以一般保留默认5s即可。3.2 通信建立与心跳维护设备端起来之后流程是这样的监听端口等待主机TCP连接。收到主机发来的SELECT.reqSType1回SELECT.rspSType2完成HSMS握手。主机发来S1F13 W设备回S1F14建立SECS-II会话。主机可以发S1F1 W查询在线状态设备回S1F2。后续进入正常业务事件、命令、查询等。设备周期检查有没有收到主机的心跳或业务消息超过T7就断开。这里有一个细节SELECT.rsp的回复内容里有一个状态码0表示成功1表示会话已被占用2表示连接尚未建立3表示连接已经存在。主机连上后如果一直收不到SELECT.rsp很可能是设备端在SELECT阶段就拒绝了——比如重复连接、连接数超限。服务端设计时要注意控制最大连接数一般只允许一个活动连接新连接来了先把旧的踢掉否则调试时多开几个客户端就会串线。S1F13/S1F14建立通信这一步返回值ACKC1也很关键。0是接受1是拒绝2是需要重试。很多设备会在设备状态不满足时返回1或2比如设备正在自检或者处于OFF-LINE不可通信状态。联调时如果卡在S1F14不要只看协议层要先查设备状态模型是否就绪。我自己的习惯是在设备端日志里把这几个关键节点都打出来TCP连接建立、SELECT收到、S1F13收到、发送S1F14、收到S1F1、进入ONLINE状态。每个节点都打上时间戳和方向后面排查问题能省一半时间。3.3 事件报告与数据收集配置事件上报是SECS/GEM最常用的功能配置逻辑可以理解为“定义数据点、组织报告、关联事件、使能上报”四步。第一步是定义状态变量SVID。比如温度、压力、流量每个变量有一个SVID配套的数据类型、长度、单位要记录完整。很多设备软件会把SVID定义做成一张配置文件格式类似于SVID101, NameChamberTemp, TypeF4, UnitCelsius SVID102, NameChamberPressure, TypeF4, UnitmTorr第二步是定义报告RPTID。一个报告可以包含多个SVID报告相当于一个数据组。比如“工艺参数报告”里包含SVID101、102、103RPTID设为1000。通过S2F33Define Report下发给设备端S2F34确认。第三步是定义事件CEID。每个事件要指定它触发时携带哪些报告。比如“RecipeCompleted”事件CEID2001关联报告RPTID1000。定义方法用S2F35Define Collection EventS2F36确认。第四步是使能事件。定义归定义不使能的话事件照样不报。主机发S2F37Enable Collection Event来使能指定的CEID列表。这批消息流程有点绕但逻辑挺清晰先有变量再有报告后有关联最后使能。我把常见操作列出来操作主消息副消息定义报告S2F33S2F34定义事件S2F35S2F36使能事件S2F37S2F38禁用事件S2F39S2F40事件真正发生时设备端发送S6F11给主机主机回S6F12确认。S6F11里必带的是DATAID、CEID以及报告数据。联调时最容易出的问题就是“事件确实触发了但主机收不到数据”或者“数据解析来不对”。前者多半是CEID没有使能后者多半是SVID和RPTID在设备端和主机端的映射不一致。我的排查方法很简单在S6F11发送前把要上报的原始数据结构打印出来和主机解析出来的数据逐一对照。S6F11是事件上报的核心消息但GEM300之后还引入了数据集Data Set、数据变量DVVAL、集合事件CEID的更细分模型涉及更多消息。实际项目里如果设备用的是老GEME30-1103之前流程就是上面这四步够用如果是GEM300设备可能还会涉及ProcessJob管理、Port管理这些扩展功能需要在项目启动时确认设备支持到哪个版本。3.4 设备常量与远程命令配置设备常量的读写走的是S2F13/S2F14读取和S2F15/S2F16修改。设备端的实现很简单收到S2F13后把请求的ECID列表转化成本地参数map取出当前值打包成S2F14返回。修改时要通过S2F16里的ACKC5告诉主机每个ECID是否修改成功0表示OK1表示拒绝2表示值超范围。这里有个细节设备常量往往有限制条件和联动逻辑比如修改“温度上限”时如果新值低于当前设定工艺温度设备要拒绝并返回对应错误码不能为了省事一律返回成功。远程命令走的是S2F41/S2F42。S2F41里字段包括RCMD命令名和一堆CPNAME/CPVAL命令参数。设备端收到后通过S2F42回ACKC60表示命令已接受1表示命令无法执行2表示命令未完成设备正在处理。如果命令涉及多个参数还要用BINACK字段逐项确认每个参数是否合法。我在一个项目里犯过的错是主机发来的RCMD是START设备端判断时用了全大写的字符串比较但主机实际发的是Start大小写不一致导致一直返回拒绝。后来统一约定RCMD由设备端文档定义原文主机端严格按文档发送并且设备端对字符串比较时不区分大小写一次治本。远程命令的处理要注意异步性。S2F41是主消息设备必须在T6时间内先回一条S2F42表示“我收到了”后续命令真正执行的结果再通过事件比如关联一个CEID上报给主机。很多初学的人会把S2F42回成“命令执行成功”导致主机以为动作完成了实际上设备才刚开始执行状态和数据都对不上。我一般建议把S2F42的ACKC6只理解为“命令接收与可执行性校验”真正的完成状态用事件来表达。4. 客户端调试主机侧怎么连接和验证4.1 调试工具选型脚本模拟器还是抓包服务端配置完剩下的重头戏是客户端调试。我的经验是先选一个趁手的工具不要一上来就对着协议文档手写报文。开源方案里Python的secsgem库很实用它封装了HSMS和SECS-II的大部分细节能快速模拟主机或设备。如果你的开发语言是Python用它做验证脚本很方便。但有几个前提环境能装第三方库且现场允许跑Python脚本。有些半导体Fab管理很严内网机器不允许随意安装工具那就只能用终端直接连TCP端口或者预编译的小工具了。商业模拟器和自研脚本各有取舍。商业模拟器的好处是图形化、能回放报文、能模拟各种异常贵在稳定和专业自研脚本的优势是灵活、好和现有测试框架集成。我在做设备端联调时通常是先用自研脚本跑通基本链路拿到一份可信的基准报文再拿这套报文去和第三方主机对接这样两边出问题时能快速定位是哪一方的解析问题。Wireshark可以作为辅助但我不推荐主力依赖。SECS/GEM报文不是明文Wireshark默认不带HSMS的完整解析器靠肉眼扒十六进制很痛苦。除非你自己写Lua解析器或者用专门的工业协议分析插件否则效率很低。我的习惯是让客户端脚本把收发报文完整打成十六进制日志自己写本地脚本解析反而更直观。4.2 用Python脚本快速打通链路下面这段代码是我常用的最小验证脚本原理不复杂建立TCP连接发送SELECT.req等待SELECT.rsp再发S1F13等待S1F14。import socket import struct import binascii def build_hsms_header(device_id, stream, func, wbitTrue, stype0, bodyb): hdr bytearray(10) msg_len 10 len(body) struct.pack_into(I, hdr, 0, msg_len) struct.pack_into(H, hdr, 4, device_id) hdr[6] (stream 0x7F) | (0x80 if wbit else 0) hdr[7] func hdr[8] 0x00 # PType: SECS-II hdr[9] stype # SType: 0data, 1SELECT, 2SELECT.rsp, 5LINKTEST... return bytes(hdr) body def recv_exact(sock, n): data b while len(data) n: chunk sock.recv(n - len(data)) if not chunk: raise ConnectionError(connection closed) data chunk return data def read_message(sock): length struct.unpack(I, recv_exact(sock, 4))[0] return recv_exact(sock, length) sock socket.create_connection((192.168.1.50, 5000), timeout5) # HSMS SELECT sock.sendall(build_hsms_header(0xFFFF, 0, 0, wbitFalse, stype1)) rsp read_message(sock) print(SELECT.rsp:, binascii.hexlify(rsp).decode()) # S1F13 W sock.sendall(build_hsms_header(0x0001, 1, 13, wbitTrue, stype0)) rsp read_message(sock) print(S1F14:, binascii.hexlify(rsp).decode()) sock.close()这段脚本打通链路后再往里面加上S1F1查询在线状态、S2F17查询时间就能验证设备端的会话层是否都正常。真正验证时我一般手里会提前准备好一份“标准报文清单”包含SELECT、S1F13、S1F1、S2F17、S2F33、S2F35、S2F37、S2F41逐条发送并检查响应这样能快速判断设备端实现了哪些功能、哪些没实现。我在现场实测的日志大概是这样的删掉敏感信息[INFO] connected to 192.168.1.50:5000 [INFO] send SELECT.req - 00 00 00 0A FF FF 00 00 00 01 00 00 00 [INFO] recv SELECT.rsp - 00 00 00 0A FF FF 00 00 00 02 00 00 00 [INFO] send S1F13 W - 00 00 00 0A 00 01 81 0D 00 00 00 [INFO] recv S1F14 - 00 00 00 26 00 01 81 0E 00 00 00 [INFO] S1F14 body: L[2] A[MDLNSECS-SIM-01] A[SOFTREV1.0]打到这份日志基本链路就通了。4.3 事件上报和远程命令的联调方法链路通了之后要验证业务功能。我的联调顺序是先看设备状态再测事件上报最后测远程命令。第一件事通常是用S1F1查询设备是否在线设备回S1F2里的ONLINEST是0还是1。如果设备还在OFF-LINE状态可以用S1F17请求ON-LINE等设备回S1F18确认设备进入ONLINE-REMOTE后再继续后面的业务测试。事件上报的联调方法先用S2F33/S2F35定义好报告和事件再用S2F37使能然后在设备侧人为触发一次真实事件比如手动跑一个空跑配方观察主机是否收到S6F11。如果事件没触发打开设备端日志看事件有没有真正产生、CEID是否被过滤、有没有关联到未使能的报告。S6F11里的DATAID一般不需要关注CEID和RPTID才是关键。当主机回S6F12的ACKC6为0时事件才算是完整闭环。远程命令的联调方法用S2F41发一条START命令设备回S2F42的ACKC60后观察设备端实际动作是否开始。如果设备端是PLC控制主机侧还可以周期性读取SVID确认设备状态变化。如果命令一直返回拒绝先把设备端日志打开看看RCMD解析逻辑是否匹配、参数校验是否通过同时注意命令名大小写和参数名是否和文档一致。这一步是最容易来回拉扯的最好是提前和设备厂商做一张“命令与参数对照表”避免两边各喊各的。5. 常见问题与排查技巧实录5.1 连接接不上、频繁断线怎么办这是最大的一类问题现象无非三种连不上、连上就断、过一阵才断。连不上先按这个顺序排查IP能ping通吗端口能telnet通吗很多厂区现场开了工控防火墙5000端口被过滤了。设备HSMS监听的是哪张网卡设备可能有多个IP确认你连的IP就是监听IP。SELECT.rsp回了吗如果回的是状态码1/2/3排查连接数超限、重复连接、连接未建立的问题。设备ID对上了吗SELECT之后所有数据消息都带设备ID设备ID不匹配会直接丢弃或报S9F1。连上就断先看心跳。设备端T7默认10s主机如果在10s内没发任何消息设备就会主动断开。解决办法是客户端在空闲时周期发Linktest.req间隔建议5s左右。如果用的是现成主机软件它应该自带这个功能如果是自己写的客户端要在主循环里加一个定时心跳。这个坑我前后踩了三回前两次都以为是防火墙问题最后看设备端T7日志才明白。还有一种是“过一阵才断”这种往往是主机或设备某一侧在处理大量数据时阻塞了主循环导致T6超时或者T7空闲超时。排查时把设备端日志里的时间戳和主机日志对上看看断线前最后一条消息是什么基本能定位到是哪一侧卡住了。5.2 报文能通但解析不对这类问题特征是消息能收发但主机解析出来的数据是乱码、错位或者长度异常。常见原因有三个。第一个原因是W bit搞反。主消息必须W1副消息W0。如果你把W bit放反了对方会认为这是一条不符合规范的响应可能直接丢弃或者回S9F1。检查方法很简单打印原始报文看Stream字节最高位。S1F13的Stream字节是0x81说明W1S1F14是0x01说明W0。第二个原因是数据体长度字段算错了。HSMS头部的总长度字段是“10字节头 数据体长度”不包含头部前面那4字节的长度字段本身。我见过不少实现把总长度直接按TCP一包实际收到的字节数填进去结果多算了4字节导致对方解析时多读或者少读。S1F13无数据体时总长度就是0x0A10如果填成0x0E14那必然出错。第三个原因是数据类型和长度字节的含义弄混。SECS-II里每个Data Item前面的格式码低6位是类型高2位是长度字节数。有的实现把长度字节数理解成最多4字节但格式码高2位如果是00就只占1字节长度这个非常容易踩坑。比如ASCII字符串Test正确编码是03 04 54 65 73 74如果把格式码按0x43理解成一个长长度类型解析就会错位。我的建议是写一个能打印每层Data Item结构的小工具把L、A、U4这些类型的起止字节范围标出来调试时一目了然。5.3 S6F11事件对不上、命令无响应S6F11收了但数据对不上先看CEID。事件触发后S6F11里的CEID必须和S2F35里定义的CEID一致。如果设备端内部有多个相同含义的事件比如“配方完成”在两条轨道上分别有CEID 2001和2002而主机只配置了2001另一条轨道的事件就一直“消失”。排查方法是在设备端打印触发事件时的CEID和主机配置比一比。数据内容对不上重点看RPTID和SVID。S6F11携带的报告数据是按定义报告时的顺序排列的如果设备端更新了SVID定义比如把SVID 101从F4改成了U4主机端的解析还是按F4那值就会错。建议在项目里维护一份SVID和RPTID的映射表设备端和主机端都按同一份表配置并做版本管理。命令无响应的情况先区分是完全没收到还是收到了但设备不执行。完全没收到检查S2F41里的RCMD和参数格式特别注意字符串比较大小写、列表嵌套结构收到了不执行看设备端日志里命令解析走到了哪一步是参数校验不过、状态不对还是命令内部抛异常被吞了。我习惯在设备端命令处理函数入口和出口都打日志入口记录原始数据出口记录执行结果“有没有进来、有没有出去”几分钟就查清了。5.4 高并发下的消息排队问题设备在处理高频事件上报和大量远程命令时会出现一个隐蔽问题主消息没回副消息又发了下一个主消息。SECS/GEM的事务机制要求一个事务必须严格配对。主机发了S1F13 W在收到S1F14之前不应该再发S2F17 W等新主消息否则设备端可能错乱或者触发T6超时。很多主机软件内部会实现一个“一次只允许一个未完成事务”的约束但自己写的客户端如果不加就会踩坑。服务端也一样。设备端收到主消息后要在T6时间内回副消息如果事件上报线程和命令处理线程共享同一个socket就要做锁或者独立发送队列。我见过一个问题事件上报线程正在处理一条S6F11还没发出去命令处理线程又收到一条S2F13需要回S2F14。如果两段代码同时往socket写报文就会粘包或者错位。解决办法是在发送端用一个线程安全的队列所有出站消息先进队列由单一发送线程真正写socket。这样既保证事务配对也避免并发写socket导致报文错乱。最后分享一个我自己的习惯不管服务端还是客户端日志一定要带完整的方向和原始字节。协议联调本质上是找双方理解不一致的过程没有原始报文的日志所有猜测都是在浪费时间。再加上时间戳和会话状态出问题一查一个准。另外如果你正在做的项目有多个设备型号建议把SECS/GEM通信模块抽成独立组件用统一配置管理设备ID、超时和SVID映射不同设备只改配置业务代码不动。这样后续新设备接入服务端和客户端的调试成本能降下来一大截。希望这篇实战记录能帮你少走几步弯路。
返回列表