ARTICLE DETAIL

资讯详情

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

SECS/GEM协议解析:从报文结构到设备集成实战

SECS/GEM协议解析:从报文结构到设备集成实战 简介SECS/GEM协议作为智能制造设备通信的关键标准最初源于半导体行业现已广泛应用于汽车制造、电子组装等各类生产环境。这份中文详解面向设备集成工程师、自动化与工艺技术人员针对网上资料零散、细节不足的问题按10个章节系统梳理协议全貌。资源为单一PDF文档压缩包大小955KB内容从协议发展背景与优势展开如降低设备集成成本、节省网络带宽、数据密度小、环路保证与安全机制随后依次覆盖消息日志方法、常用术语解释、Streams and Functions基础介绍及指令使用场景并在第四章对系统保留指令与自定义指令做了分类说明。文档逻辑清晰既讲清概念又贴近实际设备对接与调试需求。已有2252人学习适合希望快速建立SECS/GEM知识框架或正在推进设备互联、产线数据采集的从业者参考。1. SECS/GEM 是用在哪一层为什么说它天生双向SECS/GEM 是半导体设备与工厂主机MES之间的通信协议族它不是单独一个协议而是由 SEMI 标准 E5SECS-II 消息格式、E30GEM 设备行为、E37HSMS 传输等一起构成的。工厂里的炉管、光刻、量测设备靠近设备端你会看到 SECS/GEM 端口靠近信息化层你会看到 Equipment Integration 服务。第一次接触这个名词的人总会问“secs是单向的还是双向的”答案要看层级链路层和事务层是双向的主机会发 Primary Message设备必须回 Secondary Message但很多业务数据确实单向涌向某个方向比如报警和事件由设备发给主机远程命令反过来。先把“方向”理清后面看状态机才不容易晕。这篇文章按“先懂模型、再写代码、最后处理脏数据”的顺序把 SECS/GEM 的消息、连接参数、参数映射和排错讲透。适合设备软件工程师、MES 开发以及刚接手设备联网的自动化工程师。2. 从报文到状态机读懂 SxFy、Session、通信状态2.1 一条 SECS 消息里到底有什么SECS/GEM 的消息用 SxFy 表示S 是 StreamF 是 Function。S1F1 读作 Stream 1 Function 1消息自带一个 10 字节的消息头后面跟着用 SECS-II 编码的数据体。消息头里最关键的是 Device ID、W bit 和 System Bytes。W bit 决定要不要应答W0 表示不需要回包W1 表示对方必须回一条 Secondary Message。这个 bit 也是“secs是单向的还是双向的”争论来源链路本身允许任何方向主动发消息但事务总是成对出现。只要 W1发送方就会等响应超时之后才会报错。常见消息可以先背这张表SxFy名称典型方向用途S1F1/S1F2Are You There / On Line DataHost→Eq / Eq→Host探活和设备身份S1F13/S1F14Establish Communications Request/Rsp双向通信建立握手S2F23/S2F24Trace Initialize / Trace DataHost→Eq / Eq→Host周期采集变量S2F41/S2F42Host Command Send / AckHost→Eq / Eq→Host远程命令S6F11/S6F12Event Report Send / AckEq→Host / Host→Eq事件上报S9F1~S9F9Transaction FailureEq→Host报告解析失败表格里的“典型方向”是 GEM 场景下的约定协议本身允许不少消息由任意一侧发起但设备联网项目里几乎都用这些固定方向。2.2 事务、会话和状态机一个事务由 Primary Message 和对应的 Secondary Message 组成。SECS/GEM 靠 System Bytes 把它们配对System Bytes 是一个 4 字节序号。主机收到 S1F2 时必须看它的 System Bytes 是否匹配自己发出的 S1F1如果匹配不上就属于“未请求响应”通常要按异常处理。GEM 标准把设备状态分成通信状态和控制状态两类。通信状态只有 COMMUNICATING / NOT COMMUNICATING解决“网络通没通”的问题控制状态决定设备要不要听从主机的 REMOTE 指令具体枚举值各设备厂商实现不完全一致。集成第一步不是急着收发消息而是先把设备当前处于哪一组状态同步到 MES。Session 在 HSMS 上对应一条 TCP 连接Session ID 就是 Device ID。设备号和端口写错即使 TCP 能连上对端也会在 Select 阶段拒绝你。常见配置是 port5000、device_id1但每台设备到底用哪个 Device ID必须和设备供应商确认不能拍脑袋。2.3 用 tcpdump 和 Wireshark 看报文与其猜报文不如直接抓包。抓包是排错的第一手段。默认 HSMS 端口是 5000如果设备是主动连主机就在主机侧抓如果主机主动找设备就在设备侧抓。# 捕获 5000 端口的 TCP 流量保存成 pcap tcpdump -i eth0 -n tcp port 5000 -s 0 -w /tmp/secsgem.pcap # 不落盘直接看十六进制内容 tcpdump -i eth0 -n tcp port 5000 -X抓到后用 Wireshark 的 SECS/GEM 解析器能直接看到 S1F1、S6F11 等消息名命令行快速验证可以这样tshark -r /tmp/secsgem.pcap -Y secs -V | head -100看包时关注每帧是不是 Data Message、SType 是否为 0以及 System Bytes。TCP 三次握手之后第一个业务消息通常是 S1F13 或 S1F1不会一上来就是 S6F11。如果看到 S9F* 报警说明上一包格式不合法优先检查数据类型是不是写错了。3. 用 Python 和开源库把设备端接入主机3.1 先选主动还是被动HSMS 连接方向写代码前先确认设备角色。HSMS 有两种连接模式active 是设备端主动连 hostpassive 是设备端监听端口等 host 来连。两种模式只影响 TCP 连接方向SECS/GEM 业务层完全相同。做设备仿真器时一般选 passive因为 MES 集成测试总是先从 host 发起连接跑在真实机台上按设备厂商要求选择即可。连接超时 T5 和响应超时 T3 是必调参数。T3 太短设备稍微卡一点就会超时重发T5 太长网络断开后恢复很慢。常见 T345 秒、T510 秒不同协议栈默认值有差异联调前要和主机侧统一否则两边各等各的问题很难排查。3.2 最小设备端回调处理 S1F1/S1F2下面这段以开源库 secsgem 为例具体 API 以你安装的版本为准但流程是通用的。# 依赖开源库 secsgem先 pip install secsgem from secsgem import SecsGem gem SecsGem( ip0.0.0.0, # passive 模式监听所有网卡 port5000, # HSMS 默认端口 device_id1, # 和 host 约定的设备号 ) gem.on_message((1, 1)) def on_s1f1(msg): # S1F1 不携带参数回设备身份即可 return {MDLN: DemoEtcher, SOFTREV: 1.00} if __name__ __main__: gem.serve()这段代码让程序在 5000 端口等待 MES 发起 S1F1。收到消息后回调函数返回设备身份库会自动构造 Secondary Message。MDLN 和 SOFTREV 不要随意写最好和机台铭牌一致因为 MES 会拿它做设备指纹。如果你用的不是 secsgem换成内部封装里的add_handler或subscribe也一样回调签名只差一个上下文参数。如果设备需要主动连主机把参数改成这样gem SecsGem( ip192.168.1.100, # host 地址 port5000, device_id1, activeTrue, # 主动发起 TCP 连接 ) gem.serve()3.3 参数表连接、设备号、超时连接参数我一般按下面的表定初值参数常见默认推荐初值说明device_id1按设备台账两字节不能与别的设备冲突port50005000 或 5001与主机 MES 协商modepassive仿真器 passive实机 active谁先发起 TCPT345s45s逻辑卡顿可到 60s等待业务消息响应的超时T510s10s建立连接的超时T65s5s等待控制消息响应的超时linktest interval60s60s心跳保持长连接注意TCP 握手成功后还不到通信可用状态。HSMS 层有 Select 流程SType1 的 Select.req / Select.rsp 用来确认这条连接被登记为数据连接。很多库内部自动处理但抓包时你会看到三次握手后面紧跟 Select.req / Select.rsp之后才有 S1F13。如果只有 TCP 握手没有 Select说明 SECS/GEM 栈没起来多半是配置不对或端口被占用。4. 参数手册Collection Event、Alarm、Command 的映射与设置4.1 把工艺事件映射成 Collection EventGEM 为了避免 MES 不停轮询定义了一组采集事件。设备在工艺节点给主机发 S6F11消息体里带 CEID 和对应变量。CEID 由设备厂商定义不是 MES 想改就能改。我一般先把事件映射表维护成一份 JSON{ equipment_id: ETCHER-01, collection_events: { 101: { name: LOT_START, description: 晶圆批次开始加工, reports: [RPT_WAFER_ID] }, 207: { name: LOT_COMPLETE, reports: [RPT_LOT_ID, RPT_LOT_COUNT] } }, reports: { RPT_WAFER_ID: [LOTID, WAFERID], RPT_LOT_ID: [LOTID, EQPID], RPT_LOT_COUNT: [LOTID, RECIPE, GOOD_COUNT] } }这个 JSON 不是 SEMI 标准格式只是很多 MES 做 base 配置时的常见形式。核心思路是 CEID 和 Report 绑Report 和 Data Item 绑Data Item 对应 SECS 里的一个变量。设备触发 LOT_START 时实际发送的 S6F11 只带 CEID 和 Report 的实时值。设备侧触发事件时代码大致是这样# 设备内部触发 LOT_START 时发送 S6F11 gem.send((6, 11), [ 1, # DATAID每次上报递增 101, # CEID对应事件 ID [ [1, [LOT-20250417]], [2, [W12]] ] ])这里的 1、2 是设备侧 Report 里 Data Item 的索引索引顺序必须和 S2F33 定义 Report 时一致。如果顺序乱了主机侧解析出来的 LOTID 和 WAFERID 就会互相调换轻则数据错位重则 MES 报警。4.2 Host Command 的权限与格式主机远程命令通过 S2F41 下发设备回答 S2F42。典型命令有 START、STOP、ABORT、RECIPE_DOWNLOAD。命令不是自由文本必须在设备能力表里提前注册否则设备只能回拒绝。代码里做白名单校验gem.on_message((2, 41)) def on_host_command(msg): cp_name msg[CPNAME] # 例如 START cp_val msg.get(CPVAL, []) if cp_name not in allowed_commands: return 1 # 1 不允许的 command do_something(cp_name, cp_val) return 0 # 0 已接收S2F42 的 ACKC 返回 0 表示“已接收”不表示“已执行完”。长命令要先回已接受再通过事件异步上报最终执行结果。这是踩坑最多的地方把 S2F42 当成执行完成标志MES 以为设备已经跑起来其实设备还在排队。4.3 变量一多怎么办Report 与 Data Item 的层级关系SECS-II 的数据体不是 JSON而是嵌套 List 加标量类型类型用字母表示。常见类型如下类型代码含义字节数BBoolean1U1/U2/U4/U8无符号整数1/2/4/8I1/I2/I4有符号整数1/2/4F4浮点数4AASCII 字符串按长度LList嵌套容器动态解析报文最容易翻车的是忘记 L 的个数。S6F11 第一层是 L第二个元素是 CEID第三层是 L 嵌套的 report 列表。如果用 JSON 模板直接映射需要保留层次不能拍平。我会让设备厂商先把 Data Item 清单按这个表维护好再写脚本生成报文模板而不是手拼 SECS 字节。集成阶段把设备日志打开导出一份 CSV逐项核对变量 ID、类型和层级比联调时靠肉眼看十六进制快得多。5. 排错与最后 10% 的打磨System Bytes、重试和日志5.1 五分钟定位连不上链路层到应用层用 nc 检查 TCP 通不通再用 tcpdump 看有没有 Select 和 S1F13。记住TCP 通不等于 SECS 层通。nc -zv 192.168.1.20 5000 tcpdump -i any tcp port 5000 -n端口通但没有 Select重点检查设备端 SECS/GEM 服务是否启动、Device ID 和主机配置是否一致。看到 Select.req 但没有 Select.rsp几乎可以断定是设备号或协议版本不匹配。5.2 一个屡见不鲜的坑System Bytes 不唯一每条 Primary 都带一个 System Bytes用来把 Secondary 配对回去。很多协议栈使用随机数或进程启动时的计数器但进程重启后计数器清零而主机侧还留着旧的 pending就会串包。自己实现时要保证重启后不立即复用或者用时间戳加序号拼接。import time import itertools seq itertools.count(int(time.time()) 0xFFFF) def next_system_bytes(): hi int(time.time()) 0xFFFF lo next(seq) 0xFFFF return ((hi 16) | lo).to_bytes(4, byteorderbig)这样 System Bytes 在时间和序号两个维度都不容易重复。发送后把它保存到 pending 字典收到响应时再取出来配对超时未响应的记录清理掉。5.3 日志落地技巧日志要能还原现场记录时间、方向、SxFy、System Bytes、耗时和结果。我会用类似这样的一行式格式logger.info(TX S1F1 sysab12c3d4 elapse0.04 okTrue) logger.info(RX S1F2 sysab12c3d4 len320 okTrue)避免在日志里打印整包配方内容既占空间又容易泄密记录变量数量就够了。上线前把设备所有可用 CEID 和 Command 拉出来做一次对比测试确确实实能触发 S6F11 和 S2F42再和 MES 联调能省掉一整个星期的现场排查时间。本文还有配套的精品资源点击获取
返回列表