
简介《MES 接口设计说明书》面向SAP R/3与MES系统集成项目的实施顾问、接口开发人员及制造业信息化设计者围绕MELEBUS-BMAS模板下的R/3-MES协作提供制造指图数据抽取、实绩数据计上、系统间排他控制及文件接口的规格说明。压缩包共1个doc文件约178KB内容以日文文档形式组织涵盖系统目的与适用前提、制造指图抽取与实绩计上接口、R/3与MES两侧处理分工、接口文件一览与字段规格以及ZMAF001、ZMAF005程序规格和参数设定等章节。文档还给出想定业务流程图与处理注意事项便于读者理解接口边界、确认数据流与字段对应关系并作为原型搭建、接口评审或二次开发时的参考基线。已有2668人学习下载适合需要梳理SAP R/3与MES集成方案、查阅接口设计与程序规格的技术人员按章节检索使用。1. MES 接口设计说明书怎么写才有人敢照着做从两张接口文字文件倒推MES 接口设计说明书最容易出问题的地方是把它写成一张字段对照表左边 ERP 字段右边 MES 字段中间点一个逗号然后再配三张截图。真到了联调现场现场提问的都是另外几件事——指单什么时候算真正发出去、发出去以后哪一侧还能改、实绩重复回传一次会不会翻倍。这些答案不在字段表里而在抽取条件、状态标记和排他规则里。这篇按一份能直接交付的说明书结构走先划适用边界再写制造指单抽出、实绩计上两个处理的接口规格最后落到排他制御与验收。适合正在做 MES 集成毕设、或者要给工厂交付一版接口雏形的读者结构和参数照着改就能用。2. 系统规格与适用前提三层边界、两个处理与一套排他骨架接口文档的第一章不该是功能列表而应该是「这套东西在什么条件下成立」。这一点最容易忽略也最容易在验收会上被追问。我的习惯是把系统规格拆成三层写适用范围业务边界、系统化对象范围功能边界、运行前提环境边界。三层写完读者才明白后面那些参数为什么要那样给。2.1 适用范围的三条硬性限制第一条是单工厂内连携。ERP 与 MES 的接口只在一个工厂范围内成立跨工厂、跨法人的指单不在本接口的处理范围内。这条不写清楚实施时一定有人拿另一个工厂的指单来试然后回来说你的抽取条件写错了。第二条是生产方式限定。对象只覆盖「会发行制造指单」的生产方式。流程型、无指单的连续生产不在范围内——它们的实绩是按班次、按罐批回收的跟指单级别的作业确认是两套逻辑。说明书里把这条摆在前面比在附录里加十页免责声明管用。第三条是批处理节奏。指单抽出与实绩计上都按批处理方式运行处理周期按 12 次/日设计。这个数字决定了后面所有的排他设计如果一天只跑一两次用「管理文件存在与否」做互斥就够如果要做到准实时那就得换成消息队列或者数据库行锁整个方案的结构都要重写。所以它不是一句性能描述而是设计前提。提示批处理周期一旦确定就要在文档里同时写明「允许的最大延迟」。现场排产时MES 拿到指单的时间点直接决定开工时间这个值写不清楚后面所有关于时效的争议都没有依据。2.2 系统化对象范围两个处理一条不交付的边界整套接口由两个处理构成。制造指单数据抽出处理从 ERP 侧把制造指单的头信息、构成品目数据取出来写入指单接口文件。实绩数据计上处理把 MES 输出的投入实绩、完成实绩文件读回来作为作业实绩计上到 ERP 侧的制造指单上。必须同时写明的是MES 侧接口功能不在本交付范围内。这句话看着像甩锅实际上是验收的基础。它明确了本方只对「文件被正确生成、被正确消费」负责MES 内部的取入逻辑、现品票打印、指单分割属于另一侧的交付物。接口文件的格式是双方约定但两侧的实现各自验收。写方案的时候把这条列成独立小标题比藏在注意事项里有效得多。2.3 想定业务流六个节点两个交接面业务流我一般画成六个节点、两个交接面。节点依次是计划立案与计划手配作成 → 工程割付 → 制造指单发行 → 指单抽出并写入接口文件 → MES 侧取入、再发行、分割、现品票输出 → 实绩回传并计上。两个交接面就是两个方向的接口文件。这里有几条约定必须在业务流里说死制造指单与计划手配是1 对 1指单的作成单位是 ERP 侧做工程计划的单位通常是日 / 品目级别。一张指单可以由多个作业构成但不支持副作业。这一条是数据模型的限制不是实现偷懒必须显式声明。指单发行在 ERP 完成发行之后的再发行、再印刷、变更、移动单位分割、现品票输出全部由 MES 侧管理。指单抽出之后ERP 侧基本不再变更该指单。这一条决定了实绩回传时的数据基准也决定了「实绩修正只能在 ERP 侧做」的后续规则。ERP 侧作业与 MES 侧作业按1 对 1对应。因为制造上的原因要分割或合并时在 MES 侧完成回传时按一张指单汇总不在分割单位上计上实绩。这几条串起来其实是一句话指单发行之后主数据的权威在 ERP执行数据的权威在 MES。谁改什么、在哪一侧改都从这句话推出来。2.4 排他制御骨架两个管理文件定生死接口文件放在共享网络上ERP 侧和 MES 侧两边进程访问同一个文件。这种架构下没有数据库事务可用互斥只能靠约定。方案里用的是最朴素也最可靠的一招管理文件。管理文件分两个指单处理管理文件和实绩处理管理文件。规则只有三条处理开始时创建管理文件只有管理文件不存在时才允许执行处理处理结束后删除管理文件。写侧永远以追加模式往接口文件里写记录删记录的权力只在读侧——读侧处理完成之后才删。注意管理文件方案依赖「文件系统原子创建」这个假设。共享目录如果跨了不同操作系统的挂载方式创建语义可能不一致实施前必须在真实共享路径上验证一次别只在开发机上测。2.5 运行环境把差异挪进参数变体这套方案里有一个设计我很认同动作环境设定变体化。换行码、文件逻辑路径、日志保留期限全部不进代码进参数。理由很直接——同一套程序要同时跑在 Windows 和 Unix 上硬编码一个CRLF或者一个绝对路径换一个现场就要改一次代码、重新走一次发布流程。[ENV] newline CRLF ; MES 侧为 Windows 时用 CRLFUnix 侧改 LF不改代码 logical_path /if/mes/ ; 逻辑路径ERP 与 MES 必须指向同一共享目录 log_keep_days 30 ; 日志保留期限对账时要往回翻历史 [EXTRACT] mode SEND_FLAG ; LOG_CHECK 日志比对 / SEND_FLAG 用户状态二选一 date_from_offset 0 ; 着手日窗口起点相对当天 date_to_offset 7 ; 窗口终点负值表示只抽历史指单 [POST] actual_type DAILY ; DAILY 日别实绩 / CUMULATIVE 累计实绩newline决定写文件时的换行码logical_path决定接口文件落在哪log_keep_days决定历史日志留多久——对账和事故追溯全靠它。mode是抽出管理方式的开关下一章细说。actual_type决定实绩的计量口径第四章细说。这四个参数一改程序的运行形态就变了代码一行不用动这就是变体化真正的价值。还有一条容易被忽略的前提接口文件按透过数据传递不做代码转换。这意味着如果两侧的字符编码不一致问题会一直漂到业务层才爆出来。文档里必须写明这一条并约定双方在联调前各自确认编码。2.6 接口文件一览四张业务表加三类辅助文件接口文件清单我建议单独成表放在系统规格章末尾。它的作用是让读到这一章的人立刻知道「交接物一共几个」。文件方向内容唯一键指单头文件ERP → MES指单号、指单类型、品目、数量、着手日、工厂指单号指单构成品目文件ERP → MES指单号、品目、必要数量、行号指单号 品目 行号投入实绩文件MES → ERP指单号、投入品目、数量、作业日指单号 品目 作业日 连番完成实绩文件MES → ERP指单号、出来高、不良数、预测终了日、确认区分指单号 作业日 连番指单处理管理文件共用存在即表示指单接口处理中无存在性即语义实绩处理管理文件共用存在即表示实绩接口处理中无存在性即语义日志文件共用开始/终了结果 记录级明细按批次号注意「确认区分」这一列它是完成实绩里唯一一个带业务语义的标记部分确认还是最终确认。MES 侧能不能判断一张指单做完了全靠这个字段。文档里必须写明它的取值和判定责任方。3. 制造指单抽出接口四层过滤、追加写与 SEND 置位的闭环抽出接口是这套方案里逻辑最密的一段。它要回答的是哪些指单该发出去、发出去之后怎么保证不重复发、发失败了怎么知道。三个问题对应三块设计——抽取条件、写文件方式、抽出后处理。3.1 抽取条件的四层过滤条件分四层从宽到窄。最外层是着手日窗口由参数文件给出一个日期范围第二层是系统状态必须是已发行、且没有完了或部分完了第三层是有效性取消掉的指单不抽第四层是抽出管理方式二选一——要么「送信日志文件中不存在」的未送信指单要么「用户状态 SEND 未 ON」的指单。-- 制造指单抽出四层过滤少一层就会有无效指单流到现场 SELECT h.ORDER_NO, h.ORDER_TYPE, h.MAT_NO, h.PLANT, h.START_DATE, h.QTY FROM MFG_ORDER_H h WHERE h.PLANT :P_PLANT -- 单工厂跨厂不在本接口范围 AND h.START_DATE :P_DATE_FROM -- 着手日窗口参数文件给 AND h.START_DATE :P_DATE_TO AND h.SYS_STATUS REL -- 已发行 AND h.SYS_STATUS NOT IN (TECO, PREL) -- 未技术完了、未部分完了 AND h.DEL_FLAG N -- 未被取消 AND h.USER_STATUS_SEND N -- 方式二SEND 未置位才抽 ORDER BY h.ORDER_NO;参数说明:P_PLANT是工厂代码一般由运行变体绑定不给运行时手填的机会:P_DATE_FROM/:P_DATE_TO来自参数文件的date_from_offset/date_to_offset换算成绝对日期最后一行是管理方式开关若选日志比对方式这一行换成「指单号不在此前批次的送信日志中」的关联子查询。窗口的设定有个经验值起点取当天终点给 7 天左右。窗口太窄周末不跑批就会漏窗口太宽一次抽几千张指单MES 侧取入压不住还会拖长排他时间。3.2 两种抽出管理方式的取舍方案给了两个选项实际选型看现场对「可追溯」的要求。日志文件重复检查把每次抽出的指单号写进送信日志下次抽出时排除日志里已有的指单号。优点是追溯性极好——日志本身就是一本发出去的指单记录出了争议直接翻。缺点是日志只增不减跑上一年之后比对会变慢需要定期归档。用户状态 SEND 标记抽出正常完成后把指单的用户状态 SEND 置 ON下次抽出只取未置位的。优点是快状态就在指单上不需要额外比对。缺点是它在业务数据上留了痕而且一旦置位了但文件写失败就会出现「状态说发了、文件里没有」的不一致。我一般的做法是默认用 SEND 标记同时保留批次日志。日志不参与抽取判断只做追溯用。这样既保住了速度又留了后悔药。3.3 抽出主流程追加写、双日志与抽出后置位def extract_orders(cfg, mode): # 1) 抢管理文件创建失败说明 MES 侧正在处理直接退出 if not acquire_mgmt_file(cfg.order_mgmt_file): log.write(MES 侧处理中本次不执行抽出, levelWARN) return 1 try: rows query_orders(cfg) # 见上一节 SQL if not rows: log.write(无符合条件指单, levelINFO) return 0 # 2) 始终追加写文件不存在则新建写侧永远不删文件 append_records(cfg.if_order, to_header_rows(rows), newlinecfg.newline) append_records(cfg.if_bom, to_bom_rows(rows), newlinecfg.newline) # 3) 只有两个文件都写成功才置位 SEND if mode SEND_FLAG: set_user_status([r.order_no for r in rows], SEND, Y) log.write(f抽出完成指单 {len(rows)} 张, levelINFO) finally: release_mgmt_file(cfg.order_mgmt_file) # 异常路径也要删否则接口假死 return 0三个关键点。第一acquire_mgmt_file必须是原子性的「不存在则创建」用O_CREAT | O_EXCL之类的语义不要用「先判断存在、再创建」这种两步操作那中间有窗口。第二写侧只追加不删除。删除权归读侧这是同步规约的核心。理由是写侧不知道读侧处理到哪一条了一旦写侧删了文件读侧的数据就丢了而读侧在自己处理完成之后删语义是明确的。第三set_user_status放在两个文件都写成功之后。顺序反了就会出现状态置了、构成品目文件没写成的半截数据MES 侧取入时找不到 BOM报一堆莫名其妙的错。日志分两种开始/终了文件处理开始和结束时各写一条结果给运维看记录级日志逐条记录处理内容给对账看。两个都保留log_keep_days控制保留期限。3.4 MES 侧取入处理完成检查与删除时机MES 侧的逻辑要对称地写进说明书哪怕本方不交付这部分实现。取入时先做处理完成检查只处理未处理的数据处理完成后删除指单接口文件和构成品目接口文件处理过程中用同一个指单处理管理文件做互斥。这里有个细节值得在文档里点明MES 侧删除的是整个接口文件不是文件里的某些行。这意味着取入必须是一次性全量、要么全成功要么全失败。如果 MES 侧要支持部分成功那就得改成读侧标记完成行、定期清理接口文件的结构也要跟着改。这个设计取舍要在文档里写出来别让下游自己发挥。4. 实绩计上接口两种计量口径与二重计上的防护层实绩回传是整条链路上最容易翻车的一段。抽出发错了大不了多送几张指单现场还能手工处理实绩计上错了就是账实不符事后修正要人工一笔一笔冲。所以这一章的重点不是「怎么把数据写进去」而是「怎么保证只写一次、写错了怎么办」。4.1 计上实绩种别累计实绩与日别实绩怎么选MES 侧回传的实绩有两种口径。作业累计实绩针对某个作业回传从开工到当前的累计数量作业日别实绩回传某一天该作业发生的数量。两种口径都能用但混用会出大事——同一张指单前一批按累计回、后一批按日别回ERP 侧算出来的出来高会翻倍。方案里把它做成了运行时变体批处理启动时选择计上实绩数据的种别整个批次统一。这比在每条记录上带一个类型字段更安全因为类型字段一旦被 MES 侧写错ERP 侧没有能力判断该信谁。选型上的建议MES 侧如果是按班次采集、按日汇总的用日别实绩语义最自然如果 MES 只维护一个当前进度、不做日切用累计实绩避免为了凑日别数据去做人为分摊。选定一种之后文档里要写死「本接口不做双口径兼容」这句话能省掉后面无数扯皮。4.2 四类必定报错的实绩数据有四类数据在计上时按错误处理写进日志但不影响整批——这一点很重要单条错误不能把整批打回否则一张指单的数据问题会卡住全厂的实绩。第一类是后冲销品目的投入实绩。后冲销品目的消耗是在 ERP 侧随着完成确认自动冲减的MES 再回传一次投入实绩就重复了。这种情况作为错误记日志如果确实需要修改后冲销品目的投入数量从 ERP 侧的作业确认界面手工输入。第二类是BOM 里不存在的构成品目。投入实绩数据里的构成品目必须在该指单发行时点就已经登记在 BOM 中。因为制造上的原因用了 BOM 外的品目MES 侧回传上来会报错得走 ERP 侧的补登流程。第三类是同一唯一键重复回传。读侧按唯一键判断是否为此前已处理的再送数据是则跳过不重复计上。第四类是已完成指单的变更数据。本接口不设想从 MES 侧对特定指单的实绩做变更或取消计上之后的实绩修正一律在 ERP 侧做MES 侧不提供反向接口。这条限制必须写在业务注意事项里因为它是使用者的操作约定不是程序能自动兜住的。4.3 登录顺序WORK 表暂存与二重计上防护def post_actuals(cfg): if not acquire_mgmt_file(cfg.actual_mgmt_file): log.write(MES 侧处理中本次不计上, levelWARN) return 1 try: for rec in read_if_file(cfg.if_confirm, newlinecfg.newline): if is_duplicated(rec.key): # 唯一键判再送重复的直接跳过 log.write(f再送数据跳过 {rec.key}, levelWARN) continue stage_to_work_table(rec) # 先落 WORK 表异常后可从这儿续跑 for rec in load_work_table(): # 事务内统一确认 if rec.kind ISSUE: post_issue(rec) # 投入投入品目代码 数量 else: post_completion(rec) # 完成出来高 / 不良 / 预测终了日 commit() delete_if_file(cfg.if_confirm) # 全部成功后才删接口文件 finally: release_mgmt_file(cfg.actual_mgmt_file) return 0这段的重点在stage_to_work_table和delete_if_file的先后关系。先把数据落到 WORK 表再在数据库事务里做业务计上最后才删接口文件。这三个动作的顺序不能乱如果直接读文件边读边计上中途异常退出文件还在、数据计了一半重跑就翻倍。如果计上成功但删文件失败重跑时靠唯一键判重能挡住这就是唯一键存在的意义。如果先删文件再计上那是最危险的做法一次异常整批数据就没了。WORK 表在这里的角色是黑匣子出了事可以查「这批数据到底读到哪一条了」。4.4 完成实绩的确认区分与汇总规则MES 侧回传的完成数据要带部分确认 / 最终确认的区分。ERP 侧靠这个判断指单是否做完了——没有这个字段指单会一直挂在未完了的状态里后续工序排不进来。汇总规则要在文档里写死两条一是 MES 侧按制造指单单位、日次集计二是在 MES 内部发生批次汇总或分割时由 MES 侧在一张指单的单位上做汇总接口不传递分割明细。第二条约定的含义是ERP 侧收到的实绩永远对得上指单不需要在 ERP 侧做分割关系的还原。4.5 MES 侧输出规格与排他对称地写 MES 侧按制造指单单位把投入实绩、完成实绩写入接口文件因制造需要分割的制造指示书每份的实绩汇总后在同一时机输出完成数据要带部分/最终确认区分输出过程用实绩处理管理文件做互斥与管理文件互斥规则一致。5. 常见问题排查五条最容易翻车的接口事故5.1 整批文件被读成一行字段全乱现象ERP 侧读 MES 回传文件时记录条数明显不对或者每条记录的末尾挂了下一行的开头。原因换行码不一致。这套接口按透过数据传递不做代码转换Windows 侧写 CRLF、Unix 侧按 LF 读或者反过来行边界就消失了。解决把换行码做成参数变体第 2 章的newline两侧联调的第一步就是互相确认这个值。另外在读取逻辑里加一条防御如果单条记录长度超过字段定义总和的两倍直接判为格式异常并整批打回别让它继续往下走。5.2 管理文件残留接口看起来像卡住了现象某天开始抽出和计上都不执行了日志里只有「处理中本次不执行」一行连续几天如此。原因上一次处理异常终止finally没跑到管理文件留在共享目录里。之后的每一次执行都认为「对方在处理中」永远进不去。解决三件事一起做。一是创建管理文件时把进程号、开始时间、主机名写进文件内容而不是只建一个空文件二是清理逻辑里加超时判定管理文件存在超过设定时长比如批处理周期的两倍就告警人工确认后清理三是把「管理文件残留」列入日常巡检项运维每天看一眼。5.3 抽出成功但没有置位第二天重复送同一批指单现象MES 侧反馈同一批指单连续两天收到现场按重复指单开了工。原因抽出程序在写第二个文件时抛了异常SEND 置位没有执行但第一个文件已经追加写了一部分。第二天重跑条件仍然满足整批再发一次。解决把「写文件」和「置状态」放在同一个错误处理域里任一文件写失败就把本批次已写入的记录做逻辑标记批次号 状态置位动作只在两个文件都成功后执行。读侧则依赖唯一键去重即使重复收到也只处理一次。5.4 异常重启之后实绩翻倍现象某张指单的完成数量在 ERP 侧变成了实际值的两倍。原因计上程序直接读文件、边读边计上中途数据库连接断开重跑时文件还在前一半数据被计了第二次。解决严格执行「WORK 表暂存 → 事务内计上 → 成功后删除接口文件」三段式并且唯一键的生成规则要包含指单号、作业日、连番保证同一笔数据重跑时能被识别成再送。这条改动量不大但它是唯一可靠的后悔药。5.5 后冲销品目和 BOM 外品目MES 侧正常ERP 侧全量报错现象MES 侧显示实绩回传成功ERP 侧日志里刷出一片错误两边的处理结果对不上。原因这两类数据在 MES 侧看是正常的投入实绩但 ERP 侧的计上规则不允许——后冲销品目由完成确认自动冲减BOM 外品目根本找不到对应的指单构成品目。解决这不是程序 bug是业务约定没有提前对齐。做法有两个一是在接口规格里把这两类明确列为「必定报错」并写进使用手引让 MES 侧在输出前就拦掉二是在联调阶段专门造这两类测试数据把错误日志的样子跑出来给双方看一遍。6. 验收与答辩用一张对账表证明接口真能上线接口类项目的验收最怕变成「跑一遍看看有没有报错」。跑通了不代表对尤其是在文件型接口里两侧各自打日志、各自说成功实际上数量对不上这种情况太常见了。我一般会准备一张对账表把 ERP 侧、接口文件、MES 侧三个点的数据放在一起比。验收项比对口径通过标准指单抽出完整性ERP 合格指单数 vs 指单头文件行数完全相等差异为 0构成品目完整性抽出指单对应的 BOM 行数 vs 构成品目文件行数完全相等抽出幂等性连续跑两次抽出第二次文件行数增量增量为 0SEND 模式实绩计上准确性投入实绩文件数量合计 vs ERP 作业确认数量合计差异为 0实绩幂等性同一批文件重跑一次ERP 实绩数量变化变化为 0排他有效性两侧同时启动观察是否只有一侧进入只有一侧产生处理日志异常恢复计上中途 kill 进程后重跑无重复计上无数据丢失对账脚本不需要复杂一个能跑的版本几十行就够# 三方对账ERP 侧 / 接口文件 / MES 侧任意一处不等就打印差异 def reconcile(work_date, cfg): erp query_scalar( SELECT COUNT(*) FROM MFG_ORDER_H WHERE START_DATE %s AND USER_STATUS_SEND Y, work_date) ifile count_lines(cfg.if_order, newlinecfg.newline) back query_scalar( SELECT COUNT(*) FROM ACTUAL_IF WHERE WORK_DATE %s, work_date) print(fERP{erp} IF{ifile} MES回传{back}) assert erp ifile, 抽出行数与 ERP 合格指单数不一致先查抽取条件 assert ifile back, 回传数超过发送数优先怀疑唯一键重复work_date是要对账的作业日cfg里带的是接口文件的逻辑路径和换行码——注意对账脚本本身也要用同一个newline去数行数否则数出来的永远是 1。三个 assert 的顺序是有讲究的先对发送侧再对回传侧最后才查业务值。因为链路是串行的前面的对不上后面的比对没有意义。答辩或交付评审的时候我通常只讲三个问题哪些指单会被抽出来、抽出来之后重复跑会不会多、实绩重复回传一次会不会翻倍。这三个问题答得干净说明设计是闭环的答不干净字段表做得再漂亮也没用。剩下的时间用来演示异常场景——手工删掉一半接口文件、故意留一个管理文件、往实绩文件里塞一条 BOM 外品目。看系统怎么反应比看它正常运行一次有说服力得多。从那以后我每次做接口类方案都会在对账表里强制加两行「幂等性」的验收项不管对方催得多急。这两行不加后面补数据的时间一定比省下来的时间多。希望帮到你。本文还有配套的精品资源点击获取