打码设备对接 · 测试环境

蛋壳溯源码的签发、打印与用量回报

每一枚溯源码由平台签发并归属于具体农场。农场电脑预先下载码集,逐条交给打码设备打印,并通过 WebSocket 回报已打印与已作废的序号;平台据此核对签发量与用量,也可以随时查询每台设备当前的打印位置。

本页面供打码设备厂家联调使用:申请测试账号后,下载示例程序即可在本地模拟一台打码机,并在联调控制台核对每一条回报。

下载示例程序
F07A 8K9Q
8 位字码喷墨打印 · 两行各 4 位
二维码底色上激光打印 · 扫码直达查询页

系统结构

打码设备 喷墨机:8 位字码 激光机:二维码 农场电脑 厂家程序(参照示例程序) 本地保存码集与打印记录 断网照常打印,恢复后补报 溯源平台 签发码 · 核对用量 消费者扫码查询 逐条下发 厂家自有协议 HTTPS 下载码集 WebSocket 回报用量 · 应答进度查询

三步完成联调: 从申请账号到看到第一条回报

1

申请测试账号

填写公司名称即可获得测试用的 farm_id 与 api_key。测试账号与正式农场隔离,每批最多 1000 个码。

2

运行示例程序

示例程序模拟一台打码机:下载码、逐条打印、回报用量、应答进度查询。一条命令即可运行,无需真机。

3

在控制台核对

联调控制台实时显示设备在线状态、签发与打印数量、每一条回报的处理结果,并可主动查询设备的打印位置。

码的规格: 两种载体

8 位字码 · 喷墨打印

字符集:0-9 与 A-Z,共 36 个字符,全部大写
版式:两行,每行 4 位;下载接口中的 text_lines 已按行拆好
码空间:约 2.8 万亿;由平台以算法生成,不可推算
参数:示例程序使用 --print-as text

二维码 · 激光打印

内容:下载接口中的 qr_content,即查询页地址加 8 位码,原样编码
容错等级:H
用途:消费者扫码后直接进入本平台的查询页,无需手工输入
参数:示例程序使用 --print-as qr
接入指南

五个步骤接入打码设备

以下命令中的服务器地址、farm_id 与 api_key 已按当前账号填好,可直接复制运行。尚未申请账号时显示为占位符。

1

申请测试账号

测试账号编号以 SANDBOX 开头,api_key 只在申请时显示一次,本浏览器会保存一份以便下次打开控制台。

2

准备运行环境

示例程序使用 Python 3.9 或更高版本,依赖两个常用库。

pip install websockets requests
3

下载并运行示例程序

下载 trace_code_client_sample.zip,解压后在该目录运行下面的命令。程序会模拟一台编号为 P1 的喷墨机,每秒打印 20 个码。


      

模拟激光机打二维码,把设备编号换成 L1,码型换成 qr:


      

运行中命令行底部一行每秒刷新:当前批次与序号、本次已打与作废、速度、本地剩余、待回报、是否在线。输入以下字母后回车:

p  暂停        r  继续        s  打印完整状态        q  打完当前一个、发完回报后退出

演示喷头故障与自动暂停:加上 --fault-after 100,打 100 个之后模拟喷头堵塞,连续 3 个检查不合格即在本地暂停并上传照片,输入 r 继续。生成照片需要 pip install pillow qrcode。

4

在联调控制台核对

打开 联调控制台,可以看到设备 P1 已连接、平台签发的批次、每隔几秒到达的打印回报。点「查询打印进度」,平台会通过 WebSocket 实时询问设备当前打到哪一条。

5

接入真机

示例程序中需要替换的是两个类:PrinterAdapter.print_code() 换成打码设备的驱动调用;CameraInspector 换成相机取图与贵方的检查方法。示例中的检查是模拟的,并不分析照片,只用于演示上传与自动暂停。实际检查建议:二维码用 OpenCV 的 cv2.QRCodeDetector 解码,与 qr_content 比对;8 位字码做 OCV(光学字符校验),核对打出的是否就是应打的 8 个字符,比通用 OCR 更稳也更快;喷头堵塞可由字迹区域的墨点覆盖率与横向断线提前发现。若贵方已有带 OCV 的视觉检测相机,直接接入其结果即可。本地记账、断线重连、回报补发、自动暂停等逻辑可以照搬,也可以按下方报文说明用其他语言实现。

class PrinterAdapter:
    def print_code(self, item) -> bool:
        # item["print_as"] == "text":打印 item["text_lines"],两行各 4 位
        # item["print_as"] == "qr"  :把 item["qr_content"] 打成二维码
        # 打印成功返回 True;打废返回 False,程序会按作废回报
        ok = my_printer.send(item)   # 替换为贵方驱动调用
        return ok
报文说明

WebSocket 报文

下载完整接口文档

地址 ,消息均为 JSON 文本。上行 为农场电脑发往平台,下行 为平台发往农场电脑。

上行hello · 连接后 10 秒内先发
{"type": "hello", "farm_id": "SANDBOX-XXXX", "api_key": "...", "device_id": "P1",
 "software": "贵方软件/1.0", "printer_model": "型号"}

平台回复 welcome,其中 open_batches 列出本机未打完的批次及 next_seq,可用于与本地记录核对。

上行printed · 打印回报,按连续序号区间
{"type": "printed", "request_id": "唯一编号", "batch_id": "SANDBOX-XXXX-260919-7K2Q",
 "from_seq": 0, "to_seq": 199, "ts": 1790000000.0}

区间也可以写成 "seqs": [...] 或 "codes": [...]。同一 request_id 重发不会重复计数。

上行void · 打废或剔除的码
{"type": "void", "request_id": "唯一编号", "batch_id": "...", "seqs": [37, 88], "reason": "print_failed"}
下行ack · 每条回报的处理结果
{"type": "ack", "request_id": "同上", "ok": true, "accepted": 200, "duplicate": 0,
 "already_void": 0, "batch_printed": 200, "batch_void": 0, "batch_remaining": 800}

duplicate 大于 0 表示有码被重复打印,需要排查。

下行status_request · 平台查询打印进度
{"type": "status_request", "request_id": "..."}

收到后立即回复:

{"type": "status", "reply_to": "status_request 中的 request_id", "state": "printing",
 "current_batch": "...", "current_seq": 1234, "local_todo": 766, "ink_pct": 82}
下行batch_ready · 有新批次可下载
{"type": "batch_ready", "batch_id": "...", "count": 1000, "print_as": "text"}
下行control · 平台要求暂停或继续
{"type": "control", "request_id": "...", "action": "pause", "reason": "联调控制台暂停"}

action 为 pause 或 resume。执行后立即回复:

{"type": "control_ack", "reply_to": "control 中的 request_id", "ok": true, "state": "paused",
 "pause_by": "server", "pause_reason": "联调控制台暂停", "current_batch": "...", "current_seq": 1234}
上行state · 设备自己改变状态时主动报告
{"type": "state", "state": "paused", "by": "local", "reason": "连续 3 个检查不合格:字迹缺损,疑似喷头堵塞"}

by 为 local(本地判断)、operator(现场操作)或 server(平台指令);state 为 printing、paused、stopped。

HTTP上传打码照片
POST /api/images?device_id=P1&batch_id=...&seq=37&ok=0&reason=字迹缺损
X-Farm-Id / X-Api-Key,Content-Type: image/jpeg 或 image/png,请求体为图像字节,单张不超过 2 MB

不合格的全部上传,合格的抽样上传。平台按批次和序号关联到具体的码。

HTTP售出核销
POST /api/sale        X-Farm-Id / X-Api-Key
{"code": "F07A8K9Q", "by": "某门店 1 号收银台"}

返回 result:sold(核销成功)、already_sold(已售出过,疑似回收再用或仿冒)、not_printed、void、not_found。一个码只能核销一次;消费者查询时显示售出时间。

上行heartbeat · 每 30 秒一次
{"type": "heartbeat", "state": "printing", "ink_pct": 82}

必须遵守的四条

  1. 一个码只打印一次。断电重启后从本地记录继续,不得从批次开头重来;上次正在打印、无法确认结果的那一条按已打印处理。同一码出现在两枚蛋上会被判定为克隆。
  2. 未收到 ack 的回报必须保留。重连后以原 request_id 重发,平台按编号去重。
  3. 断网期间照常打印。码集已预先下载,回报保存在本地,网络恢复后补报。
  4. 打废与剔除的码回报 void。作废的码不再使用。
下载

示例程序与接口文档

压缩包内含示例程序、接口文档与已填好服务器地址的 README。

trace_code_client_sample.zip

示例程序 + 接口文档 + README,解压即可运行。

下载压缩包

3_client_farm_printer_sample.py

农场端示例程序(Python)。替换 PrinterAdapter.print_code() 即可接入真机。

单独下载

4_protocol_trace_code_ws.md

HTTP 与 WebSocket 接口说明、报文样例、必须遵守的规则。

单独下载

运行环境

Windows、Linux 或 macOS 均可;Python 3.9 或更高版本;依赖 websockets 与 requests。农场电脑需能访问 。本地记录文件 client_state_<farm>_<device>.db 保存打印进度,请勿删除。

联调控制台

联调控制台

溯源查询

查询一枚蛋的溯源码

输入蛋壳上的 8 位码,两行连续输入即可,大小写不限;扫描蛋壳上的二维码会直接打开本页。