ZeroOne AI
← 返回文章列表

MES + 工业打印机:让每一件产品“自动生成身份证”,从生产到追溯真正闭环

👁 6
分类:MES

在传统注塑工厂,MES记录生产、打印机打印标签,两套系统各自独立运行,人工重复录入容易出错。本文以实际工业场景为例,介绍如何构建 MES + 工业打印机自动打印网关:MES作为生产数据唯一来源,通过MQTT触发打印,打印网关自动拉取设备与生产数据并转换为打印协议,经TCP下发工业打印机完成产品标识,并把打印结果纳入追溯体系,真正实现“生产—打印—追溯”闭环。

在传统注塑工厂里,MES负责记录生产,打印机负责打印标签,两套系统往往各自独立运行。

生产人员需要先在MES中查询生产信息,再手动输入打印软件;设备编号、产品规格、颜色、重量、生产批次等信息也可能需要人工录入。

这种方式看似简单,但一旦产线数量增加,就容易出现:

真正的智能制造,并不是简单地"给MES增加一个打印按钮",而是让MES成为生产数据唯一来源,让打印机成为MES数据的最终执行终端。

本文以实际工业场景为例,介绍如何构建一套 MES + 工业打印机自动打印网关。

一、MES与打印机为什么需要打通?

在注塑、滴灌带、包装、食品、电子装配等生产行业中,产品通常需要打印:

设备编号 + 产品规格 + 产品颜色 + 重量 + 生产编号 + 操作员 + 检验员 + 班次

这些信息实际上都已经存在于MES中。

例如生产现场有一台设备:

LA#ST-02

MES中可以维护:

设备名称:LA生产线2号设备
设备编号:LA#ST-02
产品规格:φ16-30cm
产品颜色:黑色
产品重量:10Kg
生产编号:XXXXXX
操作员:冉阳
检验员:XXXX

如果打印机还需要操作员重新输入这些信息,就产生了一个非常明显的问题:

MES已经有数据,为什么还要人工再输入一次?

因此,更合理的架构应该是:

生产设备
 ↓
MES生产数据
 ↓
打印网关
 ↓
工业打印机
 ↓
产品标签

打印机不再负责"产生生产数据",而只负责:

执行MES下发的打印任务。

二、整体系统架构

整个系统可以设计成四层。

┌──────────────────────────────────────────┐
│ ERP / MES                               │
│                                          │
│ 设备管理 生产订单 产品规格 人员管理       │
│ 生产批次 检验信息 产品颜色 重量信息       │
└───────────────────┬──────────────────────┘
                    │ HTTP API
                    ▼
┌──────────────────────────────────────────┐
│ MES Printer Gateway                      │
│                                          │
│ MQTT监听                                 │
│ ↓                                        │
│ 获取设备数据                             │
│ ↓                                        │
│ 生成打印数据                             │
│ ↓                                        │
│ TCP发送                                  │
└───────────────┬──────────────────────────┘
                │ TCP/IP
                ▼
┌──────────────────────────────────────────┐
│ Industrial Printer                       │
│                                          │
│ TCP : 9100                               │
│                                          │
│ 接收打印指令                             │
│ ↓                                        │
│ 自动打印                                 │
└──────────────────────────────────────────┘

这套架构最大的特点是:

打印机不需要直接连接MES数据库。

打印网关负责中间转换。

三、为什么采用 MQTT + HTTP + TCP?

这套方案实际上采用了三种通信方式,每一种负责不同的事情。

  1. MQTT:负责"通知打印"

MQTT不负责传输完整生产数据。

它只发送:

{
 "device_no": "LA#ST-02"
}

意思就是:

LA#ST-02设备发生打印请求。

例如MES生产完成后:

MES
 ↓
MQTT
 ↓
/mes/Lines/Print
 ↓
{"device_no":"LA#ST-02"}

打印网关收到消息后,再去MES查询完整数据。

这样做有一个非常重要的好处:

MQTT消息非常小。

即使未来增加到几十台、几百台设备,也非常容易管理。

四、ERPNext作为MES数据中心

当前项目采用ERPNext作为MES基础平台。

打印网关通过ERPNext REST API查询:

Machine Equipment

例如:

GET
/api/resource/Machine%20Equipment/LA%23ST-02

这里有一个非常容易忽略的问题。

设备编号:

LA#ST-02

里面包含:

#

而#属于URL特殊字符,因此不能直接拼接URL。

需要进行URL编码:

from urllib.parse import quote

encoded_dev = quote(device_no, safe="")

url = f"{ERP_URL}/api/resource/{encoded_doctype}/{encoded_dev}"

最终:

LA#ST-02

会转换成:

LA%23ST-02

这也是工业MES开发中非常典型的细节。

五、ERPNext API Key + API Secret

打印网关不需要模拟网页登录ERPNext。

而是使用:

API Key
+
API Secret

通过Token方式访问。

HTTP Header:

headers = {
 "Authorization": f"token {API_KEY}:{API_SECRET}",
 "Content-Type": "application/json",
 "Accept": "application/json"
}

然后:

response = requests.get(
 url,
 headers=headers,
 timeout=10
)

这样打印网关就可以独立运行。

例如:

MES服务器
192.168.20.200
    ↑
    │ HTTP API
    │
    ↓
Printer Gateway
    │
    │ TCP
    ↓
打印机
192.168.17.45:9100

需要注意的是,API Secret 属于敏感凭据,实际部署时应放入配置文件或环境变量,并避免写入Git仓库。

六、设备编号自动转换

工业现场经常存在多个设备之间的关联。

例如:

LA#ST-02

代表生产线设备。

而实际对应的注塑机可能是:

LA#IM-02

视觉检测设备可能是:

LA#IV-02

因此打印网关可以根据设备编号自动转换。

例如:

def convert_device_number(device_no, target_type):

    if not device_no:
        return ""

    parts = device_no.split("#")

    if len(parts) != 2:
        return device_no

    line = parts[0]
    machine = parts[1]

    if "-" not in machine:
        return device_no

    number = machine.split("-", 1)[1]

    return f"{line}#{target_type}-{number}"

调用:

convert_device_number(
    "LA#ST-02",
    "IM"
)

得到:

LA#IM-02

调用:

convert_device_number(
    "LA#ST-02",
    "IV"
)

得到:

LA#IV-02

这样MES只需要维护一个生产设备编号,系统即可自动关联生产设备和检测设备。

七、班次信息也可以自动生成

打印标签经常需要区分:

白班
夜班

如果依靠人工选择,就容易出现错误。

可以直接根据系统时间判断。

例如项目要求:

09:00~21:00 = 白班
21:00~次日09:00 = 夜班

代码:

from datetime import datetime

def get_shift_text():

    now = datetime.now()

    current_minutes = now.hour * 60 + now.minute

    day_start = 9 * 60
    night_start = 21 * 60

    if day_start <= current_minutes < night_start:
        return "✔", ""

    return "", "✔"

这样打印机接收到的就是已经处理好的结果。

例如:

09:30
↓
白班
↓
✔

或者:

23:20
↓
夜班
↓
✔

生产人员无需再选择。

八、打印数据最终如何组成?

当前打印协议采用:

Header
+
字段
+
Tail

其中字段使用:

;

分隔。

例如:

dtbzbq.zpl;
9;
LA#ST-02;
产品规格;
10Kg;
✔;
;
生产编号;
检验员;
操作工;
黑色

最终转换为TCP数据:

1B 1C 74 70 6C
...
0D 0A

其中:

1B 1C 74 70 6C

是打印协议头。

0D 0A

是结束符。

因此打印网关本质上就是一个:

MES数据 → 打印协议

转换器。

九、打印网关的核心工作流程

完整流程可以设计成:

     MES
     │
     │ 生产完成
     ▼
 发布MQTT打印消息
     │
     ▼
 /mes/Lines/Print
     │
     ▼
 Printer Gateway
     │
     │ 获取device_no
     ▼
 查询Machine Equipment
     │
     ▼
 获取生产数据
     │
     ┌──────┴──────┐
     │             │
     ▼             ▼
 设备信息       产品信息
     │             │
     └──────┬──────┘
            ▼
    生成打印字段
            │
            ▼
    生成TCP数据包
            │
            ▼
    连接打印机9100
            │
            ▼
    发送 0D 0A
            │
           100ms
            │
            ▼
    发送主打印数据
            │
            ▼
    等待打印机响应
            │
           最长3秒
            │
            ▼
    记录返回数据
            │
            ▼
    关闭TCP连接

这个流程比简单的:

MQTT → 打印机

可靠得多。

十、为什么发送打印前还要发送 0D 0A?

当前项目的打印机通信流程不是直接发送主数据。

而是:

TCP连接
 ↓
发送 0D 0A
 ↓
等待100ms
 ↓
发送主打印数据
 ↓
等待返回
 ↓
关闭TCP

也就是说:

prepare_data = bytes([0x0D, 0x0A])

sock.sendall(prepare_data)

time.sleep(0.1)

sock.sendall(packet)

这个设计相当于在正式打印之前给打印机发送一个初始化/分隔数据。

对于工业设备通信来说,这种"小协议细节"非常重要。

不要认为TCP连接成功就代表打印机一定已经准备好。

十一、打印机返回数据必须记录

很多工业项目只做:

sock.sendall(packet)

然后:

sock.close()

这实际上是不完整的。

因为打印机可能会返回:

ACK
状态码
错误码
设备信息
异常信息

因此当前方案增加了:

sock.settimeout(3)

然后:

response_data = b""

while True:

    try:

        chunk = sock.recv(4096)

        if not chunk:
            break

        response_data += chunk

        logger.info(
            "收到HEX:%s",
            chunk.hex(" ")
        )

    except socket.timeout:

        logger.warning(
            "等待打印机返回超时"
        )

        break

最终日志可以看到:

打印机TCP连接成功
发送初始化数据:0D 0A
等待0.100秒后发送主打印数据
发送主打印数据,长度:xxx bytes
主数据HEX:
1b 1c 74 70 6c ...
等待打印机返回,超时:3秒
收到打印机数据:
...
收到HEX:
...
打印机TCP连接已关闭

这对于现场调试尤其重要。

十二、3秒没有响应,是不是打印失败?

这里需要特别注意。

TCP发送成功

和:

打印机返回成功

是两个不同概念。

例如:

发送成功
 ↓
打印机已经收到
 ↓
打印机开始处理
 ↓
打印机没有返回数据
 ↓
3秒超时

这时候不能简单判断:

打印失败

更合理的是把状态拆成:

SEND_SUCCESS
RESPONSE_RECEIVED
RESPONSE_TIMEOUT
SEND_FAILED
CONNECT_FAILED

以后MES可以进一步实现:

打印任务
 ↓
发送
 ↓
等待
 ↓
打印机响应
 ↓
成功 / 超时 / 失败

这样才能真正形成打印任务闭环。

十三、打印网关为什么不直接写进MES?

这是系统架构中非常重要的一点。

如果直接把打印机TCP代码写进MES后台:

MES
 ├── ERP
 ├── 生产
 ├── 设备
 ├── 质量
 └── 打印机

随着打印机数量增加,后台会越来越复杂。

而采用独立打印网关:

MES
 │
 ├── MQTT
 │
 ▼
Printer Gateway
 │
 ├── Printer 01
 ├── Printer 02
 ├── Printer 03
 ├── Printer 04
 └── ...

可以实现打印机层独立扩展。

以后增加:

ZPL打印机
热转印打印机
喷码机
激光打标机
标签打印机

只需要增加对应驱动。

MES本身不需要修改核心业务逻辑。

十四、从一台打印机扩展到整座工厂

单台设备:

MES
 │
 ▼
Printer Gateway
 │
 ▼
Printer

扩展到一条产线:

      MES
      │
      MQTT
      │
 ┌────┴────┐
 │         │
Printer  Printer
Gateway  Gateway
 │         │
 ┌────┼────┐  ┌────┼────┐
 ▼    ▼    ▼  ▼    ▼    ▼
P01  P02  P03 P04  P05  P06

进一步扩展到整个工厂:

        MES
        │
  MQTT / HTTP API
        │
 ┌──────┼──────┐
 │      │      │
 LA     LB     LC
 │      │      │
打印网关 打印网关 打印网关
 │      │      │
多台打印机 多台打印机 多台打印机

最终形成:

MES统一管理,打印网关统一执行,打印机分布式部署。

十五、最终形成"生产—打印—追溯"闭环

真正有价值的不是"自动打印"本身。

而是打印完成后,这个标签可以成为产品的数字身份。

例如:

产品
 ↓
生产设备
 ↓
生产批次
 ↓
生产时间
 ↓
操作员
 ↓
检验员
 ↓
产品规格
 ↓
产品颜色
 ↓
重量
 ↓
打印标签
 ↓
二维码
 ↓
MES追溯

客户拿到产品以后,通过二维码扫描:

产品二维码
 ↓
MES
 ↓
查询生产记录
 ↓
生产设备
 ↓
生产时间
 ↓
操作员
 ↓
检验记录
 ↓
质量数据

这时候打印机就不再只是一个"打印设备"。

而成为:

MES数字化追溯体系中的最后一个执行节点。

十六、未来可以继续升级哪些功能?

这套架构还可以继续扩展。

① 打印任务队列

MES
 ↓
MQTT
 ↓
打印任务队列
 ↓
Printer

防止瞬间大量任务造成打印机压力。

② 打印任务ID

例如:

PRINT-20260902-000001

MES可以完整记录:

任务ID
设备
打印时间
打印内容
发送状态
响应状态
异常信息

③ 自动重试

例如:

第一次失败
 ↓
等待1秒
 ↓
第二次
 ↓
仍失败
 ↓
第三次
 ↓
报警

④ 打印机心跳

持续监控:

在线
离线
忙碌
缺纸
故障

⑤ 打印内容防错

打印前自动检查:

设备编号 ✓
产品规格 ✓
生产批次 ✓
操作员 ✓
检验员 ✓

任何关键字段为空:

禁止打印

⑥ 打印结果回写MES

最终形成:

MES
 ↓
打印请求
 ↓
Printer Gateway
 ↓
打印机
 ↓
打印结果
 ↓
MES

这才是真正意义上的:

MES + 打印设备闭环控制

十七、总结

传统生产模式是:

MES记录数据
+
人工操作打印机

智能制造模式则是:

MES产生生产数据
 ↓
MQTT触发打印
 ↓
打印网关读取MES
 ↓
自动生成打印协议
 ↓
TCP发送工业打印机
 ↓
等待打印机响应
 ↓
记录打印结果
 ↓
回写MES

最终实现:

生产数据从MES产生,经过打印网关自动转换,最终驱动工业打印机完成产品标识,并将打印过程纳入MES追溯体系。

这不是简单的"MES连接打印机",而是把生产数据、设备数据、人员数据、质量数据和产品标签真正连接起来。

对于注塑工厂而言,下一步还可以把它扩展成:

注塑机
 ↓
MES
 ↓
生产订单
 ↓
产品参数
 ↓
视觉检测
 ↓
称重
 ↓
自动打印
 ↓
二维码
 ↓
包装
 ↓
入库
 ↓
全流程追溯

最终形成一套真正面向智能工厂的**"生产—检测—打印—包装—入库—追溯"数字化闭环系统**。

评论(0