跳转到内容

设备通讯协议(v0.1)

本文为历史版本协议文档,对应 ProtocolVersion = 0.1。新设备或新接入项目请优先参考 设备通讯协议(v1.0);仅在维护仍运行 v0.1 固件的设备时查阅本文。

文档版本: v0.1
最后更新: 2026-03-16
适用对象: 设备固件开发者、第三方硬件集成商


日期更新内容
2026-03-161. 设备状态上报新增 sleepTime 字段,用于上报设备休眠时间(单位:分钟) → 设备状态上报
2026-03-121. 上报 NN 号调整为在 firmware 固件列表中上报(由 firmware[].nn 承载) → 设备状态上报
2. 设备状态上报新增 charging 字段,用于标识设备是否处于充电状态 → 设备状态上报
2026-02-261. 打印任务资源列表新增 compression 字段,支持指示资源文件是否启用压缩(nonegzip) → 打印任务下发
2. 固件升级任务新增 compression 字段,支持指示固件文件是否启用压缩(nonegzip) → 固件升级任务
2026-02-061. 新增独立的 Pull 主题 devices/{sn}/up/pull,设备主动拉取打印任务或固件升级任务 → 任务拉取请求
2. 新增 Pull Ack 主题 devices/{sn}/down/pull/ack,用于回复无可用任务情况 → Pull响应
3. 移除打印任务回执中的 pull 状态,拉取任务改用独立 Pull 主题 → 打印任务回执
4. 移除设备状态上报中的 firmwareId 字段 → 设备状态上报
5. 移除固件升级任务下发中的 firmwareId 字段 → 固件升级任务
6. 设备不再在首次状态上报时获取任务,改为主动 Pull 拉取 → 主动拉取任务
7. 设备端负责判断本地错误是否应该 Pull,云端不再在 Pull 时判断错误 → 云端响应逻辑
8. 去除掉定时pull的需求,保留根据资源情况自行pull,其余情况由云端来保证任务的稳定性 → 任务拉取请求
9. 打印任务回执中 seq 字段改为 seqs 数组,支持批量确认多个资源 → seqs字段说明
2026-02-031. 设备状态上报新增 avgLatency(平均延时)和 packetLossRate(丢包率)字段 → 设备状态上报
2. 新增设备事件上行主题 devices/{sn}/up/event,用于设备上报事件通知 → 设备事件上报
3. 新增停止打印事件类型(stop_print),云端收到后会清除该设备的打印队列 → 停止打印事件说明
2026-01-271. 新增设备状态错误码 6013 纸张类型错误,用于标识纸张类型与任务要求不匹配的情况 → 设备状态错误码
2026-01-261. Bootstrap API 响应新增 keepalivecleanSessionstateReportInterval 字段,支持服务端配置MQTT心跳时间、会话清洁策略和设备状态上报周期 → 响应字段说明
2. 设备引导时间戳校验简化,仅校验13位长度,移除±5分钟时间窗口限制,避免设备初次启动时时间不准导致引导失败 → 请求字段说明
3. 设备状态上报新增 paperType 字段(纸张类型) → 设备状态上报
4. 设备状态上报错误码字段由 errorCode 调整为 errCode,并改为 int 数组类型(支持多个错误码) → 设备状态上报
5. 移除下行控制指令 test_print(测试页改为由云端自行拼接并触发打印) → 设备控制指令
2025-11-20初始版本发布,定义基础通信协议


  • 设备已向平台注册,获得 SN(序列号)和 Secret(密钥)
  • 设备支持 HTTPS 和 MQTT 协议
  • 设备具备基本的文件下载和哈希校验能力
  • 建议设备时间与 NTP 服务器同步,误差不超过 5 分钟
  1. 设备上电 → 调用 Bootstrap API 获取连接参数
  2. 使用返回的参数连接 MQTT Broker
  3. 订阅下行主题(接收平台命令和 Pull 响应)
  4. 上报设备状态
  5. 主动拉取任务(通过 Pull 主题请求打印或固件升级任务)
  6. 处理平台下发的打印/升级/控制任务
sequenceDiagram
  autonumber
  participant Dev as 设备
  participant API as Bootstrap API
  participant MQTT as EMQX Broker
  
  Note over Dev,MQTT: 1. 设备引导
  Dev->>API: POST /api/v1/bootstrap {sn, ts, sign}
  API->>API: 验证签名和时间戳
  API-->>Dev: 返回 MQTT 参数和主题配置
  
  Note over Dev,MQTT: 2. MQTT 连接
  Dev->>MQTT: CONNECT (clientId, username, password)
  MQTT->>MQTT: 验证 JWT Token
  MQTT-->>Dev: CONNACK (连接成功)
  
  Note over Dev,MQTT: 3. 订阅主题
  Dev->>MQTT: SUBSCRIBE devices/{sn}/down/print (QoS 2)
  Dev->>MQTT: SUBSCRIBE devices/{sn}/down/upgrade (QoS 2)
  Dev->>MQTT: SUBSCRIBE devices/{sn}/down/control (QoS 2)
  Dev->>MQTT: SUBSCRIBE devices/{sn}/down/pull/ack (QoS 1)
  MQTT-->>Dev: SUBACK
  
  Note over Dev,MQTT: 4. 上报状态
  Dev->>MQTT: PUBLISH devices/{sn}/up/state {状态数据}
  MQTT-->>Dev: PUBACK
  
  Note over Dev,MQTT: 5. 主动拉取任务
  Dev->>MQTT: PUBLISH devices/{sn}/up/pull {拉取请求}
  MQTT-->>Dev: PUBACK
sequenceDiagram
  autonumber
  participant Platform as 平台
  participant MQTT as EMQX Broker
  participant Dev as 设备
  
  Note over Dev,Platform: 1. 设备主动拉取任务
  Dev->>MQTT: PUBLISH up/pull {jobId:"", seq:0, firmware:[...]}
  MQTT->>Platform: 转发拉取请求
  
  alt 有固件升级任务
    Platform->>MQTT: PUBLISH down/upgrade {固件升级任务}
    MQTT->>Dev: 转发固件升级任务
    Note over Dev: 执行固件升级流程
  else 有打印任务
    Platform->>MQTT: PUBLISH down/print {打印任务}
    MQTT->>Dev: 转发打印任务
    
    Note over Dev: 2. 立即确认收到的资源
    Dev->>MQTT: PUBLISH up/print/ack {status:confirm, seqs:[1,2,3...]}
    Note right of Dev: 必须在10秒内发送,seqs包含已收到的资源序号
    MQTT->>Platform: 转发确认回执
    
    Note over Dev: 3. 下载资源
    Dev->>Dev: 下载 resources[i]
    Dev->>Dev: 校验 hash
    
    Note over Dev: 4. 打印进度
    Dev->>MQTT: PUBLISH up/print/ack {status:printing, seqs:[1]}
    MQTT->>Platform: 转发进度回执
    
    Note over Dev: 5. 判断是否需要拉取更多资源
    Dev->>Dev: 检查 seq == totalFileNumber?
    
    alt seq < totalFileNumber
      Note over Dev: 6. 拉取更多资源
      Dev->>MQTT: PUBLISH up/pull {jobId:"xxx", seq:5}
      MQTT->>Platform: 请求更多资源
      Platform->>MQTT: PUBLISH down/print {新资源列表}
      MQTT->>Dev: 转发新资源
      Note over Dev: 循环回到步骤5继续下载
    else seq >= totalFileNumber
      Note over Dev: 7. 完成当前任务
      Dev->>MQTT: PUBLISH up/print/ack {status:success, seqs:[1-10]}
      MQTT->>Platform: 转发完成回执
      
      Note over Dev: 8. 拉取下一单打印任务
      Dev->>MQTT: PUBLISH up/pull {jobId:"", seq:0, firmware:[...]}
      MQTT->>Platform: 请求下一单任务
      
      alt 队列中有待打印任务
        Platform->>MQTT: PUBLISH down/print {下一单打印任务}
        MQTT->>Dev: 转发新任务
      else 队列为空
        Platform->>MQTT: PUBLISH down/pull/ack {message:"no_task"}
        MQTT->>Dev: 回复无可用任务
      end
    end
  else 无可用任务
    Platform->>MQTT: PUBLISH down/pull/ack {message:"no_task"}
    MQTT->>Dev: 回复无可用任务
  end
sequenceDiagram
  autonumber
  participant Platform as 平台
  participant MQTT as EMQX Broker
  participant Dev as 设备
  
  Note over Dev,Platform: 1. 设备主动拉取任务
  Dev->>MQTT: PUBLISH up/pull {jobId:"", seq:0, firmware:[...]}
  MQTT->>Platform: 转发拉取请求
  Platform->>Platform: 检查固件版本,发现有升级任务
  
  Note over Platform,Dev: 2. 升级任务下发
  Platform->>MQTT: PUBLISH devices/{sn}/down/upgrade {升级任务}
  MQTT->>Dev: 转发升级任务
  
  Note over Dev: 3. 立即确认
  Dev->>MQTT: PUBLISH up/upgrade/ack {status:confirm}
  MQTT->>Platform: 转发确认回执
  
  Note over Dev: 4. 下载固件
  Dev->>Dev: 下载固件文件
  Dev->>MQTT: PUBLISH up/upgrade/ack {status:downloading}
  MQTT->>Platform: 转发下载进度
  
  Note over Dev: 5. 校验哈希
  Dev->>Dev: 验证 SHA256 hash
  
  Note over Dev: 6. 执行升级
  Dev->>MQTT: PUBLISH up/upgrade/ack {status:upgrading}
  MQTT->>Platform: 转发升级状态
  Dev->>Dev: 应用新固件
  Dev->>Dev: 重启设备
  
  Note over Dev: 7. 重启后上报
  Dev->>MQTT: PUBLISH up/upgrade/ack {status:success}
  MQTT->>Platform: 转发成功回执
  Dev->>MQTT: PUBLISH up/state {新固件版本}
  MQTT->>Platform: 同步设备状态
  
  Note over Dev: 8. 拉取打印任务
  Dev->>MQTT: PUBLISH up/pull {jobId:"", seq:0, firmware:[新版本]}
  MQTT->>Platform: 请求打印任务
sequenceDiagram
  autonumber
  participant Platform as 平台
  participant MQTT as EMQX Broker
  participant Dev as 设备
  
  Note over Platform,Dev: 1. 控制指令下发
  Platform->>MQTT: PUBLISH devices/{sn}/down/control {控制指令}
  MQTT->>Dev: 转发控制指令
  
  Note over Dev: 2. 立即确认
  Dev->>MQTT: PUBLISH up/control/ack {status:confirm}
  MQTT->>Platform: 转发确认回执
  
  Note over Dev: 3. 完成操作
  Dev->>MQTT: PUBLISH up/control/ack {status:success}
  MQTT->>Platform: 转发完成回执
  
  alt 需要重启的操作
    Note over Dev: 4. 设备重启
    Dev->>Dev: 执行重启
    Note over Dev: 5. 重启后上报
    Dev->>MQTT: PUBLISH up/state {设备状态}
    MQTT->>Platform: 同步设备状态
  end

设备 <--HTTPS--> Bootstrap API (获取连接参数)
设备 <--MQTT--> EMQX Broker <--Core MQTT Bridge--> Kafka <--> 平台应用
  • 双向通信: 设备可上报状态,平台可下发任务
  • QoS 保证: 上行 QoS1,下行 QoS2(可协商降级到 QoS1)
  • 消息幂等: 基于 msgIdjobId 实现幂等去重
  • TLS 加密: 生产环境强制使用 TLS 1.2+

术语说明示例/备注
Device(设备)物联网打印机或相关硬件设备-
SN(序列号)设备的全局唯一标识符SN-XYZ-001,禁止包含 | . 等特殊字符
Secret(密钥)平台为设备分配的密钥,用于签名验证32-64字节随机字符串,设备端需安全存储
msgId(消息ID)消息的唯一标识符,32字符长度建议使用 UUID v4 去掉连字符,如 a1b2c3d4e5f6789012345678901234ab
ProtocolVersion协议版本号当前为 0.1
术语说明
MQTT消息队列遥测传输协议,轻量级发布/订阅模式
Topic(主题)MQTT 消息的分类路径,格式如 devices/{sn}/up/state
Upstream(上行)设备 → 平台的消息流
Downstream(下行)平台 → 设备的消息流
QoS消息传输质量等级:QoS0(最多一次)、QoS1(至少一次)、QoS2(恰好一次)
ACL访问控制列表,限制设备只能访问自己的主题
术语说明
jobId打印任务的唯一标识符
deviceUpgradeId设备升级任务的唯一标识符
firmwareType固件类型:cloud(云端)、printer(打印机)、bluetooth(蓝牙)
seq资源序号,从 1 开始递增
字段单位说明
ts毫秒Unix 时间戳(13位毫秒级),设备上报的当前时间,如 1724040060000
dateTime毫秒Unix 时间戳(13位毫秒级),服务器时间,如 1724846400000

提示: Bootstrap API 仅校验时间戳长度为13位,不校验时间窗口,设备可在引导成功后根据响应中的 serverTime 进行时间校准。


状态码说明处理建议
200成功-
401签名无效或已过期检查签名算法和时间戳
404设备未注册联系平台管理员注册设备
423设备已被禁用设备被停用,无法继续使用
429请求频率超限实施指数退避策略
500服务器内部错误重试或联系技术支持

约定:凡字段名为 errCode(数组)时,空数组 [] 表示无错误/正常;当存在错误时,数组内元素为一个或多个错误码,取值参考本章节错误码定义。

错误码说明
0操作成功
错误码说明处理建议
1001签名非法检查签名算法,确认 Secret 正确
1002令牌过期或无效重新调用 Bootstrap API 获取新令牌
1003设备未授权检查设备是否已注册并启用
错误码说明处理建议
2001主题访问被拒绝(ACL)检查主题路径是否正确
2002消息格式错误检查 JSON 格式和必填字段
2003消息体过大单条消息不得超过 256KB
错误码说明处理建议
3001打印失败(设备硬件故障)检查打印机状态,上报详细错误信息
3002打印超时检查网络和设备性能
3003打印内容下载失败检查网络连接,支持断点续传
3004打印内容校验失败重新下载文件,检查 hash 算法
3005存储空间不足重启机器或者联系工程师排查情况处理
错误码说明处理建议
4001升级包校验失败检查 SHA256 哈希值
4002升级失败/回滚保留旧固件,支持回滚机制
4003升级包下载失败检查网络,支持断点续传
4004固件版本不兼容检查设备型号和固件版本匹配
4005存储空间不足清理临时文件或提示用户
4006升级超时设备升级超时且达到最大重试次数,平台标记失败
错误码说明处理建议
5001不支持的控制指令检查指令是否在支持列表中
5002控制指令参数错误检查参数格式和取值范围
5003控制指令执行失败检查设备状态和硬件功能
5004控制指令超时检查设备响应能力
错误码说明处理建议
6001打印机缺纸提示用户添加纸张
6002打印机卡纸提示用户清除卡纸
6003打印机过热暂停打印,等待降温
6004电池电量低提示用户充电
6005存储空间不足清理缓存文件
6006盖子未关重新把盖子关上
6007盖子未关且卡纸重新打开盖子整理下纸张再关好盖子
6008盖子未关且过热通风散热后再重新关盖打印
6009卡纸且过热通风散热后打开盖子调整纸张后再重新关盖打印
6010盖子未关且卡纸且过热通风散热后打开盖子调整纸张后再重新关盖打印
6011硬件错误联系工程师处理
6012设备忙等待设备正常后再执行后续打印操作
6013纸张类型错误检查纸张类型是否与任务要求匹配

Step 1: Bootstrap API - 获取连接参数

Section titled “Step 1: Bootstrap API - 获取连接参数”

设备上电后,首先通过 HTTPS 调用 Bootstrap API 获取 MQTT 连接参数和主题配置。

接口地址

POST https://byteone-core-stg.iprtapp.com/api/v1/bootstrap

请求头

请求体结构

{
"sn": "SN-XYZ-001", // 必填:设备序列号
"protocolVersion": "0.1", // 必填:协议版本
"ts": 1724040000000, // 必填:当前时间戳(13位毫秒),误差不超过±5分钟
"sign": "abc123def456..." // 必填:签名,见下方算法说明
}
字段类型必填说明
snstring设备序列号,全局唯一标识符
protocolVersionstring协议版本号,当前为 0.1
tsint64当前时间戳(13位毫秒),仅需确保为13位长度即可
signstringHMAC-SHA256签名,计算方式见下方算法说明

算法: HMAC-SHA256

步骤:

  1. 拼接明文字符串:plaintext = sn + ts
    • 示例:"SN-XYZ-001" + "1724040000000""SN-XYZ-0011724040000000"
  2. 使用 Secret 作为密钥,对明文进行 HMAC-SHA256 计算,例如明文SN-XYZ-0011724040000000使用密钥password进行HMAC-SHA256加密后的结果为5776e385eb1e6a652e71dd3cb37b98a7f459d186ec630a3da5274fa97f429743
  3. 将计算结果转换为十六进制小写字符串

成功响应(HTTP 200)

{
"code": 0,
"message": "OK",
"data": {
"device": {
"sn": "SN-TEST-001",
"model": "A40w-4G"
},
"mqtt": {
"host": "mqtt.byteone.com",
"port": 8883, // TLS端口,测试环境可能为1883
"clientId": "SN-TEST-001|0.1", // 格式:{sn}|{protocolVersion}
"username": "SN-TEST-001",
"password": "eyJhbGciOiJIUzI1NiIs...", // JWT短期令牌
"qosUp": 1, // 上行消息QoS等级
"qosDown": 2, // 下行消息QoS等级
"tokenTtlSec": 3600, // 令牌有效期(秒)
"keepalive": 60, // MQTT心跳时间(秒),设备应按此间隔发送心跳包
"cleanSession": false, // 是否清洁会话,false表示保持会话以恢复离线消息
"tls": {
"enabled": true, // 生产环境必须为true
"caCertPem": "-----BEGIN CERTIFICATE-----\n..." // TLS根证书
}
},
"topics": {
"upState": "devices/SN-TEST-001/up/state",
"upPrintAck": "devices/SN-TEST-001/up/print/ack",
"upUpgradeAck": "devices/SN-TEST-001/up/upgrade/ack",
"upControlAck": "devices/SN-TEST-001/up/control/ack",
"upEvent": "devices/SN-TEST-001/up/event",
"upPull": "devices/SN-TEST-001/up/pull",
"downPrint": "devices/SN-TEST-001/down/print",
"downUpgrade": "devices/SN-TEST-001/down/upgrade",
"downControl": "devices/SN-TEST-001/down/control",
"downPullAck": "devices/SN-TEST-001/down/pull/ack"
},
"stateReportInterval": 1800, // 设备状态上报周期(秒),默认1800秒(30分钟)
"serverTime": 1759991021 // 服务器当前时间戳,用于时间校准
}
}

失败响应示例

{
"code": 1001,
"message": "签名验证失败",
"data": null
}
字段路径类型说明
codeint业务错误码,0表示成功
messagestring响应消息描述
data.device.snstring设备序列号
data.device.modelstring设备型号
data.mqtt.hoststringMQTT服务器地址
data.mqtt.portintMQTT服务器端口,8883(TLS)或1883(非TLS)
data.mqtt.clientIdstringMQTT客户端ID,格式固定为 {sn}|{protocolVersion}
data.mqtt.usernamestringMQTT连接用户名,通常为设备SN
data.mqtt.passwordstringJWT短期令牌,有效期由 tokenTtlSec 指定
data.mqtt.qosUpint上行消息QoS等级(通常为1)
data.mqtt.qosDownint下行消息QoS等级(通常为2)
data.mqtt.tokenTtlSecintJWT令牌有效期(秒),默认为3600秒(1小时)
data.mqtt.keepaliveintMQTT心跳时间(秒),设备应按此间隔发送心跳包保持连接,默认60秒
data.mqtt.cleanSessionbool是否清洁会话,true表示不保留离线消息,false表示保持会话以便恢复离线消息
data.mqtt.tls.enabledbool是否启用TLS,生产环境必须为true
data.mqtt.tls.caCertPemstringTLS根证书(PEM格式),用于验证服务器身份,目前使用验证过的公钥,所以当前字段默认为空,由设备端自行通过证书库认证
data.topics.upStatestring设备状态上行主题
data.topics.upPrintAckstring打印任务回执上行主题
data.topics.upUpgradeAckstring固件升级回执上行主题
data.topics.upControlAckstring控制指令回执上行主题
data.topics.upEventstring设备事件上行主题,用于设备上报事件通知
data.topics.upPullstring任务拉取上行主题,设备主动拉取打印或固件升级任务
data.topics.downPrintstring打印任务下行主题
data.topics.downUpgradestring设备固件升级下行主题
data.topics.downControlstring控制指令下行主题,接收平台控制命令
data.topics.downPullAckstringPull响应下行主题,用于回复无可用任务的情况
data.stateReportIntervalint设备状态上报周期(秒),设备应按此间隔定期上报设备状态,默认1800秒(30分钟)
data.serverTimeint64服务器当前时间戳(秒级,13位),设备可用于时间校准
  1. 参数有效期: Bootstrap 返回的 MQTT 连接参数长期有效,除非平台更新配置
  2. 令牌续期: JWT 令牌有效期为 tokenTtlSec 秒(通常为3600秒),令牌接近过期(剩余5分钟)时,应重新调用 Bootstrap API 获取新令牌
  3. 时间同步: 如果设备时间与 serverTime 差异过大,应使用 serverTime 进行校准
  4. TLS证书: 生产环境必须启用 TLS

使用 Bootstrap API 返回的参数连接 MQTT Broker。


连接成功后,立即订阅平台下发命令的主题。需订阅以下主题:

  • devices/{sn}/down/print - 打印任务下发
  • devices/{sn}/down/upgrade - 固件升级任务下发
  • devices/{sn}/down/control - 控制指令下发
  • devices/{sn}/down/pull/ack - Pull 响应(无可用任务时的回复)

订阅成功后,立即上报一次设备状态。


上报状态后,设备应主动通过 Pull 主题拉取可用的打印任务或固件升级任务:

// 发送到 devices/{sn}/up/pull
{
"msgId": "xxx",
"jobId": "", // 为空表示请求新任务
"seq": 0,
"firmware": [
{"firmwareType": "cloud", "firmwareVersion": "1.0.0", "nn": "NN-001"},
{"firmwareType": "printer", "firmwareVersion": "2.0.0"}
],
"ts": 1724044088000
}

云端根据设备上报的固件版本判断是否需要下发固件升级任务,优先下发固件升级。

注意: 设备端需自行判断本地是否存在阻塞性错误(如缺纸、卡纸),存在错误时不应发送 Pull 请求。云端在收到 Pull 时不再判断设备错误状态。


监听消息事件,处理打印和升级任务。


方向主题模式说明
上行devices/{sn}/up/{message_type}设备上报消息到平台
下行devices/{sn}/down/{command_type}平台下发命令到设备

命名约束:

  • 主题路径仅允许字符:[a-z0-9-_/]
  • SN 建议使用 A-Z0-9- 字符组合
  • 主题路径最大长度:256 字符

所有 MQTT 消息载荷均为 JSON UTF-8 编码格式。

通用字段:

{
"msgId": "32字符唯一ID", // 必填:消息唯一标识符,用于去重
"ts": 1724040060000, // 必填:消息时间戳(13位毫秒)
// ... 其他业务字段
}

msgId 生成规范:

  • 长度:32 字符
  • 格式:建议使用 UUID v4 去掉连字符(例:a1b2c3d4e5f6789012345678901234ab
  • 唯一性:全局唯一,用于消息去重和链路追踪
  • 生成示例:

主题: devices/{sn}/up/state
QoS: 1
用途: 上报设备实时状态,包括网络、电量、固件版本等信息

{
"msgId": "a1b2c3d4e5f6789012345678901234ab",
"ts": 1724040060000,
"rssi": -58, // WiFi 信号强度(dBm)
"battery": 90, // 电池电量百分比(0~100)
"paper": 1, // 纸张状态:0=无纸,1=有纸
"paperType": "roll", // 纸张类型:fold/roll/gap/hole/tattoo
"errCode": [], // 错误码数组:空数组表示正常,可同时上报多个错误码
"temperature": 35.2, // 可选:设备温度(摄氏度)
"humidity": 45, // 可选:设备湿度(0~100)
"ipAddress": "192.168.1.25", // 可选:设备IP地址
"bluetoothMac": "00:1A:7D:DA:71:13", // 可选:蓝牙MAC地址
"imei": "865123456789012", // 可选:4G模块IMEI号(15位数字)
"iccid": "89860123456789012345", // 可选:SIM卡ICCID号(18-22位数字)
"signalStrength": -75, // 可选:4G信号强度(dBm)
"networkType": "4G", // 可选:网络类型(2G/3G/4G/5G)
"printCount": 12345, // 可选:累计打印张数
"avgLatency": 150, // 可选:平均延时(毫秒)
"packetLossRate": 2, // 可选:丢包率(0~100,如2表示2%)
"charging": false, // 可选:是否正在充电
"sleepTime": 10, // 可选:休眠时间(分钟)
"firmware": [
{
"firmwareType": "cloud", // 固件类型
"firmwareVersion": "1.2.3", // 固件版本号
"nn": "NN-001" // 模组NN号
},
{
"firmwareType": "printer",
"firmwareVersion": "3.4.5",
"nn": "NN-002" // 打印机NN号
},
{
"firmwareType": "bluetooth",
"firmwareVersion": "0.9.8"
}
]
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
tsint64消息时间戳(13位毫秒)
rssiintWi-Fi RSSI,单位 dBm,通常为负数,数值越接近 0 信号越强
batteryfloat电量百分比,范围0~1
paperint纸张状态,0=缺纸,1=正常
paperTypestring纸张类型:fold(折叠纸)/roll(卷纸)/gap(标签纸)/hole(孔型纸)/tattoo(纹身纸)
errCodeint[]设备错误码数组,[] 表示正常,其他见错误码表,可同时上报多个错误码
temperaturefloat设备温度(摄氏度)
humidityfloat设备湿度(0~1)
ipAddressstring设备当前IP地址
bluetoothMacstring蓝牙MAC地址
imeistring4G模块IMEI号(15位数字),用于识别4G模块
iccidstringSIM卡ICCID号(18-22位数字),用于识别SIM卡
signalStrengthint4G LTE RSRP,单位 dBm,通常为负数;不要上报 RSRP 原始索引值
networkTypestring网络类型:2G/3G/4G/5G
printCountint累计打印张数
avgLatencyint平均延时(毫秒),用于监控设备网络质量
packetLossRateint丢包率(0~100),如2表示2%丢包率
chargingbool是否正在充电,true 表示充电中
sleepTimeint休眠时间(分钟)
firmwarearray固件版本列表
firmware[].firmwareTypestring固件类型:cloud/printer/bluetooth
firmware[].firmwareVersionstring固件版本号
firmware[].nnstring设备当前 NN 号,建议在 firmwareType=cloud 的固件项中上报;非空时云端将更新设备记录中的 NN 号

rssisignalStrength 都使用 dBm。Wi-Fi 信号上报 ESP32/ESP-IDF 的 RSSI dBm 值,参考 Espressif ESP-IDF Wi-Fi API 中 RSSI threshold 的 rssi 参数说明:阈值单位为 dBm,常见范围约为 -10010,极强信号可能出现轻微正值。

signalStrength 上报 4G LTE RSRP dBm 值。若模组只提供 LTE RSRP 报告值,应先按 3GPP TS 36.133 v14.5.0 Table 9.1.4-1 的 RSRP measurement report mapping 转成 dBm 后再上报:

RSRP 报告值RSRP dBm 区间
value <= -17rsrp < -156 dBm
-16 <= value <= -1(value - 140) dBm <= rsrp < (value - 139) dBm
value = 0rsrp < -140 dBm
1 <= value <= 96(value - 141) dBm <= rsrp < (value - 140) dBm
97 <= value <= 126-44 dBm <= rsrp
value = 127无效值,不上报 signalStrength 或按未知处理

4 格信号展示可按以下公式从 dBm 转换。缺失或无效值应显示为未知,不参与公式计算。

wifiBars = min(4, max(0, floor((rssiDbm + 95) / 10)))
lteBars = min(4, max(0, floor((rsrpDbm + 125) / 10)))

对应阈值为:Wi-Fi < -85 为 0 格,[-85,-76] 为 1 格,[-75,-66] 为 2 格,[-65,-56] 为 3 格,>= -55 为 4 格;4G RSRP < -115 为 0 格,[-115,-106] 为 1 格,[-105,-96] 为 2 格,[-95,-86] 为 3 格,>= -85 为 4 格。

场景上报时机
开机上报设备启动完成,各状态正常,MQTT 连接成功后立即上报
周期上报可选,建议每 30 分钟上报一次
变化上报重要状态变更时立即上报(缺纸、电量低、过热等)
频率限制每分钟不超过 100 条(突发异常除外)

主题: devices/{sn}/up/print/ack
QoS: 1
用途: 向平台回复打印任务的执行状态和进度

{
"msgId": "b2c3d4e5f67890a1b2c3d4e5f67890a1",
"jobId": "92ef08872ff906876071478274eec57b", // 打印任务ID
"ackOriginalMsgId": "a1b2c3d4e5f6789012345678901234ab", // 原始下发消息的msgId
"status": "confirm", // 任务状态
"seqs": [1, 2, 3, 4, 5], // 确认的资源序号数组
"errCode": [], // 错误码数组,空数组表示成功
"msg": "ok", // 错误描述信息
"ts": 1724040088000
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
jobIdstring打印任务唯一标识,与下发任务的jobId对应
ackOriginalMsgIdstring原始下发消息的msgId,用于消息关联
statusstring任务状态:confirm/printing/success/failed
seqsint[]资源序号数组,支持批量确认多个资源,每个元素取值 1~totalFileNumber,详情见seqs字段说明
errCodeint[]错误码数组,[] 表示成功,其他见错误码表,可同时返回多个错误码
msgstring错误描述信息或状态说明
tsint64消息时间戳(13位毫秒)
status 值含义是否必传说明
confirm收到任务确认✅ 必传设备收到任务后立即回复,10秒内必须发送,seqs 包含已确认收到的资源序号
printing打印中✅ 建议打印进度上报,携带 seqs 字段
success打印成功✅ 必传所有资源打印完成,seqs 包含所有成功打印的资源序号
failed打印失败✅ 必传打印过程中出现错误,seqs 包含失败的资源序号

注意: 拉取新的打印任务或固件升级任务请使用独立的 Pull 主题(devices/{sn}/up/pull)。

  • 用途:用于确认每个打印任务单和文件的实际打印情况,也可用与设备掉电后能云端能确定具体打到哪个文件了
  • 类型: 整数数组,支持批量确认多个资源
  • 取值范围: 每个元素范围 1 ~ totalFileNumber(打印任务文件总数)
  • 语义:
    • confirm 状态:已成功接收并确认的资源序号列表,如 [1, 2, 3, 4, 5] 表示确认收到seq 1-5的资源
    • printing 状态:当前正在打印的资源序号,通常只包含当前值,如 [3]
    • success 状态:当前打印完成的资源序号,通常只只包含当前值,如[3]
    • failed 状态:当前打印失败的资源序号,通常只只包含当前值,如[3]

示例:

// 确认收到seq 1-5的资源
{"status": "confirm", "seqs": [1, 2, 3, 4, 5], ...}
// 正在打印seq 3的资源
{"status": "printing", "seqs": [3], ...}
// 打印完成
{"status": "success", "seqs": [3], ...}
  1. 设备打印中突然断电
  2. 设备重启: 设备重启后完成自检、MQTT 连接,上报设备状态
  3. 主动拉取任务: 设备通过 Pull 主题(devices/{sn}/up/pull)携带本地缓存的任务ID和seq主动拉取任务,如果本地没有缓存则直接传空由云端判断
  4. 续打任务下发: 平台根据设备上报的进度,下发续打任务
  5. 恢复打印: 设备继续打印

主题: devices/{sn}/up/upgrade/ack
QoS: 1
用途: 向平台回复固件升级任务的执行状态

{
"msgId": "d4e5f6789012a3b4c5d6e7f89012a3b4",
"deviceUpgradeId": "92ef08872ff906876071478274eec57b", // 设备升级任务ID
"ackOriginalMsgId": "原始下发消息的msgId",
"status": "upgrading", // 升级状态
"errCode": [], // 错误码数组,空数组表示成功
"msg": "ok", // 错误描述
"ts": 1724041088000
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
deviceUpgradeIdstring设备升级任务ID,与下发任务的deviceUpgradeId对应
ackOriginalMsgIdstring原始下发消息的msgId,用于消息关联
statusstring升级状态:confirm/downloading/upgrading/success/failed
errCodeint[]错误码数组,[] 表示成功,其他见错误码表,可同时返回多个错误码
msgstring错误描述信息或状态说明
tsint64消息时间戳(13位毫秒)
status 值含义是否必传说明
confirm收到任务确认✅ 必传设备收到升级任务后立即回复
downloading下载中❌ 可选固件下载进度上报
upgrading升级中❌ 可选正在执行升级
success升级成功✅ 必传升级完成并重启后发送
failed升级失败✅ 必传升级过程中出现错误

主题: devices/{sn}/up/control/ack
QoS: 1
用途: 向平台回复设备控制指令的执行状态

{
"msgId": "g5h6i7j890k1l2m3n4o5p6q789r0s1t2",
"controlId": "a351eff1b614d0c1f64227d0c4b28c99", // 控制指令ID
"ackOriginalMsgId": "原始下发消息的msgId",
"status": "confirm", // 执行状态
"errCode": [], // 错误码数组,空数组表示成功
"msg": "ok", // 错误描述
"ts": 1724042088000
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
controlIdstring控制指令ID,与下发指令的controlId对应
ackOriginalMsgIdstring原始下发消息的msgId,用于消息关联
statusstring执行状态:confirm/success/failed
errCodeint[]错误码数组,[] 表示成功,其他见错误码表,可同时返回多个错误码
msgstring错误描述信息或状态说明
tsint64消息时间戳(13位毫秒)
status 值含义是否必传说明
confirm收到指令确认✅ 必传设备收到控制指令后立即回复
success执行成功✅ 必传控制操作完成
failed执行失败✅ 必传控制操作失败

主题: devices/{sn}/up/event
QoS: 1
用途: 设备向平台上报事件通知,用于触发云端特定业务逻辑

{
"msgId": "h7i8j9k012l3m4n5o6p7q8r901s2t3u4",
"eventType": "stop_print", // 事件类型
"eventParams": { // 事件参数(可选)
"reason": "user_action" // 事件原因或其他参数
},
"ts": 1724043088000
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
eventTypestring事件类型,见下方事件类型表
eventParamsobject事件参数,JSON对象,不同事件类型有不同参数
tsint64消息时间戳(13位毫秒)
eventType 值含义eventParams 参数云端处理逻辑
stop_print停止打印事件reason: 停止原因(可选)云端收到后会清除该设备的打印队列中所有待打印任务

当设备需要停止打印时(如用户按下停止按钮),设备应发送此事件通知云端。

消息示例:

{
"msgId": "i8j9k012l3m4n5o6p7q8r901s2t3u4v5",
"eventType": "stop_print",
"eventParams": {
"reason": "user_button"
},
"ts": 1724043188000
}

云端响应:

  • 收到 stop_print 事件后,云端会立即清除该设备打印队列中所有可被打印的任务

上行消息:任务拉取请求(Pull)

Section titled “上行消息:任务拉取请求(Pull)”

主题: devices/{sn}/up/pull
QoS: 1
用途: 设备主动拉取新的打印任务或固件升级任务

{
"msgId": "k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
"jobId": "", // 可选:当前打印任务ID,为空表示请求新任务
"seq": 0, // 本地缓存的最大资源序号
"firmware": [ // 当前固件版本列表
{
"firmwareType": "cloud",
"firmwareVersion": "1.2.3",
"nn": "NN-001"
},
{
"firmwareType": "printer",
"firmwareVersion": "3.4.5",
"nn": "NN-002"
},
{
"firmwareType": "bluetooth",
"firmwareVersion": "0.9.8"
}
],
"ts": 1724044088000
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
jobIdstring当前打印任务ID。为空表示请求新任务,不为空表示请求该任务的后续资源
seqint本地缓存的最大资源序号。为0表示请求新任务,大于0表示请求seq+1及后续资源
firmwarearray当前固件版本列表,用于云端判断是否需要推送固件升级
firmware[].firmwareTypestring固件类型:cloud/printer/bluetooth
firmware[].firmwareVersionstring固件版本号
firmware[].nnstring模组或者打印机的NN 号
tsint64消息时间戳(13位毫秒)
  1. 优先检查固件升级:根据设备上报的固件版本,判断是否有待执行的固件升级任务

    • 如有固件升级任务:通过 devices/{sn}/down/upgrade 主题下发固件升级任务,不下发打印任务
    • 设备完成升级后再次 Pull 获取打印任务
  2. 打印任务处理(无固件升级时):

    • jobId 为空或 seq >= totalFileNumber:获取队列中最早的有效任务单下发
    • jobId 不为空且 seq < totalFileNumber:下发该任务的 seq+1 及后续资源
  3. 任务筛选条件

    • 任务在有效期内
    • 任务状态不为”取消”或”完成”
    • 失败状态的任务如果在设备设置的有效期内,也允许重新下发
  4. 无可用任务:通过 devices/{sn}/down/pull/ack 主题回复无可用任务

  • 设备端职责:设备在发送 Pull 请求前应自行判断本地是否存在阻塞性错误(如缺纸、卡纸等)。存在阻塞性错误时不应发送 Pull 请求
  • 云端职责:云端在收到 Pull 请求时不再判断设备错误状态,直接按上述逻辑响应。云端仅在以下场景判断设备错误:
    • 用户创建新任务时
    • 有队列任务需要由云端主动触发下发时

下行消息:Pull 响应(无可用任务)

Section titled “下行消息:Pull 响应(无可用任务)”

主题: devices/{sn}/down/pull/ack
QoS: 1
用途: 当 Pull 请求没有可用的打印任务或固件升级任务时,云端回复此消息

{
"msgId": "m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8",
"ackOriginalMsgId": "k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
"code": 0, // 响应码:0表示成功(但无可用任务)
"message": "no_task", // 响应消息
"dateTime": 1724044188000 // 服务器时间
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
ackOriginalMsgIdstring原始 Pull 请求的 msgId
codeint响应码:0表示成功
messagestring响应消息:no_task 表示无可用任务
dateTimeint64服务器时间(13位毫秒时间戳)
  • 当有可用的打印任务时,云端通过 devices/{sn}/down/print 主题下发,不使用此主题
  • 当有可用的固件升级任务时,云端通过 devices/{sn}/down/upgrade 主题下发,不使用此主题
  • 此主题仅用于回复”无可用任务”的情况

主题: devices/{sn}/down/print
QoS: 2(可协商降级到 QoS 1)
用途: 平台向设备下发打印任务

{
"msgId": "e5f6789012a3b4c5d6e7f89012a3b4c5",
"jobId": "j-202408-0001", // 打印任务唯一ID
"totalFileNumber": 100, // 任务文件总数
"resources": [
{
"seq": 1, // 资源序号,从1开始
"url": "https://obj.example.com/prints/j-202408-0001-part1.data",
"hash": "sha256:ab12cd34ef56...", // SHA256哈希值
"size": 102400, // 文件大小(字节)
"compression": "gzip" // 压缩方式:none-不压缩,gzip-gzip压缩
},
{
"seq": 2,
"url": "https://obj.example.com/prints/j-202408-0001-part2.data",
"hash": "sha256:cd34ef56ab78...",
"size": 102400,
"compression": "none"
}
],
"dateTime": 1724846400000 // 服务器时间(13位毫秒时间戳)
}
字段类型必填说明
msgIdstring消息唯一ID
jobIdstring打印任务唯一标识,用于幂等去重
totalFileNumberint任务文件总数
resourcesarray打印资源列表,单次下发最多100个
resources[].seqint资源序号,从1开始递增
resources[].urlstring文件下载URL
resources[].hashstringSHA256哈希值,格式:sha256:十六进制字符串
resources[].sizeint文件大小(字节)
resources[].compressionstring压缩方式:none(不压缩)、gzip(gzip压缩)。设备下载后需根据此字段决定是否解压
dateTimeint64服务器时间(13位毫秒时间戳)
  1. 接收任务: 收到消息后立即发送 status=confirm 回执(10秒内)
  2. 幂等检查: 根据 jobId 判断是否为重复任务,重复任务直接返回上次结果
  3. 下载资源: 按 seq 顺序下载文件,支持断点续传
  4. 校验哈希: 下载完成后验证 SHA256 哈希值
  5. 解压资源: 检查 compression 字段,若为 gzip 则进行 gzip 解压,若为 none 则跳过解压
  6. 执行打印:
    • 按顺序打印资源
    • 开始打印时发送 status=printing 进度回执
  7. 完成回执: 打印完成后发送 status=successstatus=failed

主题: devices/{sn}/down/upgrade QoS: 2(可协商降级到 QoS 1)
用途: 平台向设备下发固件升级任务

{
"msgId": "f6789012a3b4c5d6e7f89012a3b4c5d6",
"deviceUpgradeId": "u-202408-0001", // 设备升级任务ID
"firmwareType": "cloud", // 固件类型
"firmwareVersion": "1.2.4", // 固件版本号
"url": "https://obj.example.com/fw/p5802-1.2.4.bin",
"hash": "sha256:cd34ef56ab78...", // SHA256哈希值
"size": 5242880, // 文件大小(字节)
"compression": "gzip", // 压缩方式:none-不压缩,gzip-gzip压缩
"dateTime": 1724846400000 // 服务器时间(13位毫秒时间戳)
}
字段类型必填说明
msgIdstring消息唯一ID,32字符
deviceUpgradeIdstring设备升级任务唯一标识,用于幂等去重
firmwareTypestring固件类型:cloud(云端固件)、printer(打印机固件)、bluetooth(蓝牙固件)
firmwareVersionstring固件版本号
urlstring固件下载URL
hashstringSHA256哈希值,格式:sha256:十六进制字符串
sizeint文件大小(字节)
compressionstring压缩方式:none(不压缩)、gzip(gzip压缩)。设备下载后需根据此字段决定是否解压
dateTimeint64服务器时间(13位毫秒时间戳)
  1. 接收任务: 收到消息后立即发送 status=confirm 回执
  2. 下载固件:
    • 支持断点续传
    • 定期发送 status=downloading 进度(可选)
  3. 校验哈希: 下载完成后验证 SHA256 哈希值,失败则立即报错
  4. 解压固件: 检查 compression 字段,若为 gzip 则进行 gzip 解压,若为 none 则跳过解压
  5. 执行升级:
    • 发送 status=upgrading 状态
    • 应用新固件
  6. 重启设备: 升级完成后重启
  7. 上报结果:
    • 重启后发送 status=success 回执
    • 上报新的固件版本(通过设备状态消息)

主题: devices/{sn}/down/control
QoS: 2(可协商降级到 QoS 1)
用途: 平台向设备下发控制指令,用于远程控制设备行为

{
"msgId": "h6i7j890k1l2m3n4o5p6q789r0s1t2u3",
"controlId": "a351eff1b614d0c1f64227d0c4b28c99", // 控制指令唯一ID
"command": "reboot", // 控制指令类型
"params": {}, // 可选:指令参数 预留字段
"dateTime": 1724846400000 // 服务器时间(13位毫秒时间戳)
}
指令 (command)说明参数 (params)预期行为
shutdown关机设备执行安全关机,保存状态后关闭电源
reboot重启设备执行安全重启,保存状态后重启系统
beep发声/蜂鸣发出蜂鸣声
reset_wifi重置WiFi清除WiFi配置,恢复到待配网状态
reset_bluetooth重置蓝牙清除蓝牙配对记录,恢复到待配对状态
factory_reset恢复出厂设置清除所有配置,恢复出厂状态。keep_network为true时保留网络配置
clear_cache清理缓存清理临时文件和打印缓存
set_params设置设备参数-设置设备运行参数;设备收到后更新本地配置并回执

说明:测试页打印不再通过控制指令下发。平台如需打印测试页,应由云端自行拼接测试页内容并按普通打印任务流程下发。

字段类型必填说明
msgIdstring消息唯一ID
controlIdstring控制指令唯一标识,用于幂等去重
commandstring控制指令类型,见上表
paramsobject指令参数,不同指令参数不同
dateTimeint64服务器时间(13位毫秒时间戳)
  1. 接收指令: 收到消息后立即发送 status=confirm 回执
  2. 幂等检查: 根据 controlId 判断是否为重复指令
  3. 参数验证: 检查 command 是否支持,params 是否合法
  4. 完成回执:
    • 成功:发送 status=success
    • 失败:发送 status=failed,携带错误信息
  5. 重启类操作: 重启后上报设备状态

示例 : 重启设备

{
"msgId": "a1b2c3d4e5f6789012345678901234ab",
"controlId": "a351eff1b614d0c1f64227d0c4b28c99",
"command": "reboot",
"dateTime": 1724846400000
}

设备应针对不同错误场景返回相应错误码:

错误场景errCodemsg 示例
不支持的指令[5001]“不支持的控制指令: xxx”
参数错误[5002]“参数错误: duration必须为正整数”
设备忙碌[6012]“设备正在打印,无法执行控制操作”
执行失败[5003]“WiFi重置失败: 网络模块错误”
  1. 危险操作确认: factory_reset 等危险操作建议设备端二次确认(如通过指示灯闪烁或按键确认)
  2. 幂等性: 基于 controlId 实现幂等,避免重复执行

环境TLS端口说明
生产环境✅ 必须8883强制使用 TLS 1.2+
测试环境❌ 可选1883 / 8883建议启用 TLS

TLS 配置:

  • 服务器证书验证: 设备必须验证服务器证书的有效性
  • 证书链: 使用 Bootstrap API 返回的 caCertPem 验证整个证书链
  • 证书过期: 设备应定期检查并更新 CA 证书

阶段 1: HTTP Bootstrap 认证

  • 算法: HMAC-SHA256
  • 输入: sn + ts
  • 密钥: 设备 Secret
  • 输出: 十六进制签名字符串
  • 有效期: ±5 分钟时间窗口

阶段 2: MQTT 连接认证

  • 用户名: 设备 SN
  • 密码: JWT 短期令牌(来自 Bootstrap 响应)
  • 令牌有效期: 通常 3600 秒/1小时(由 tokenTtlSec 指定)

设备仅允许访问自己的主题,禁止跨设备访问。

操作允许的主题模式
发布(PUBLISH)devices/{自己的sn}/up/*
订阅(SUBSCRIBE)devices/{自己的sn}/down/*

违规示例:


信息类型存储要求说明
SN(序列号)明文存储设备唯一标识,无需加密
Secret(密钥)加密存储使用设备硬件密钥加密,禁止明文存储
JWT Token内存存储不持久化,重启后重新获取
CA 证书明文存储公开信息,可明文存储

虽然 TLS 已提供传输层加密,但关键业务消息建议额外签名:


错误原因解决方案
Connection refused网络不可达检查网络连接,使用指数退避重试
Authentication failed令牌无效或过期重新调用 Bootstrap API 获取新令牌
Certificate verify failedTLS 证书验证失败检查 CA 证书是否正确
Keep alive timeout网络不稳定降低 keepalive 间隔

A: 设备应该实现以下时间同步机制:

  1. NTP 同步: 定期与 NTP 服务器同步时间
  2. Bootstrap 校准: 使用 Bootstrap API 返回的 serverTime 校准本地时间
  3. 误差检测: 如果时间误差超过 5 分钟,拒绝签名验证并提示用户

Q2: 如何处理网络波动导致的消息丢失?

Section titled “Q2: 如何处理网络波动导致的消息丢失?”

A: 采用以下策略:

  1. 使用 QoS 1 或 QoS 2: 保证消息至少送达一次
  2. 消息缓存: 离线时缓存消息,连接恢复后重发
  3. 幂等设计: 基于 jobIdmsgId 实现幂等去重
  4. 超时重试: 设置合理的超时时间和重试机制

Q3: 打印任务太大,如何优化下载速度?

Section titled “Q3: 打印任务太大,如何优化下载速度?”

A: 建议采用以下优化措施:

  1. 并发下载: 同时下载多个 resources 资源(限制并发数为 3-5)
  2. 断点续传: 使用 HTTP Range 请求支持断点续传
  3. 预加载: 打印前几个资源时,提前拉取后续资源
  4. 压缩传输: 资源文件支持 gzip 压缩,设备根据 resources[].compression 字段判断是否需要解压。当 compressiongzip 时,下载完成并校验哈希后需进行 gzip 解压

A: 设备应该实现以下机制:

  1. 双分区设计: 保留旧固件分区,升级失败时自动切换
  2. 升级标记: 记录升级状态,重启后检查是否成功
  3. 回滚逻辑: 升级失败自动回滚到旧版本
  4. 上报失败: 通过 up/upgrade/ack 上报失败原因

Q5: 如何判断是否需要主动拉取任务?

Section titled “Q5: 如何判断是否需要主动拉取任务?”

可以采用以下策略:

  1. 设备启动后拉取: 设备上电、MQTT连接成功、上报状态后,通过 Pull 主题主动拉取任务
  2. 拉取同一任务的后续资源: 当 seq < totalFileNumber 时,通过 Pull 主题携带 jobIdseq 拉取后续资源
  3. 拉取下一单打印任务: 当前任务完成后(发送 status=success),通过 Pull 主题携带空 jobId 请求下一单任务
  4. 提前拉取策略: 根据当前打印进度和文件大小,提前拉取下一批资源,避免等待
  5. 设备端错误判断: 设备在发送 Pull 请求前应自行判断本地是否存在阻塞性错误(如缺纸、卡纸),存在阻塞性错误时不应发送 Pull

重要: 云端在收到 Pull 请求时不再判断设备错误状态,设备端需自行负责错误状态的判断。


A: 设备侧必须具备 SN 和 Secret(用于 Bootstrap 签名与 MQTT 连接认证),通常来源如下:

  1. 设备注册: 平台侧为设备创建设备记录,生成 SN 与 Secret
  2. 生产烧录: 在生产环节将 SN 与 Secret 烧录到设备(Secret 必须加密存储)
  3. App 侧绑定(不同型号流程不同):
  • WiFi 版本:App 通过连接设备本体蓝牙,与设备握手后可获取 SN/设备秘钥等信息,再完成配网与绑定
  • 4G 版本:App 通过扫描/输入 SN 发起验证码请求;设备在线时打印验证码,App 输入/识别验证码后完成绑定(App 不直接持有 Secret)

注意:以上为“设备入网/绑定”的业务流程说明;协议层仍以设备本地持有 SN/Secret 为前提完成引导与认证。


A: 建议使用以下工具和方法:

  1. MQTT 客户端工具:

  2. 抓包分析:

  3. 日志调试:

    • 启用 MQTT 库的详细日志
    • 记录连接参数、认证信息(脱敏)
  4. 测试环境:

    • 先在测试环境验证(使用 1883 明文端口)
    • 确认无误后切换到生产环境(8883 TLS 端口)

平台由 Core 内置 MQTT Bridge 实现 MQTT 和 Kafka 之间的双向消息转发:

设备 <--MQTT--> EMQX <--Core MQTT Bridge--> Kafka <--> 平台应用

设备到平台 (EMQX → Kafka):

  • devices/{sn}/up/state → Kafka Topic: iot-messages (type: device_state)
  • devices/{sn}/up/print/ack → Kafka Topic: iot-messages (type: print_ack)
  • devices/{sn}/up/upgrade/ack → Kafka Topic: iot-messages (type: upgrade_ack)
  • devices/{sn}/up/control/ack → Kafka Topic: iot-messages (type: control_ack)
  • devices/{sn}/up/event → Kafka Topic: iot-messages (type: device_event)
  • devices/{sn}/up/pull → Kafka Topic: iot-messages (type: pull_request)

平台到设备 (Kafka → EMQX):

  • Kafka Topic: device-commands (type: print_command) → devices/{sn}/down/print
  • Kafka Topic: upgrade-commands (type: upgrade_command) → devices/{sn}/down/upgrade
  • Kafka Topic: control-commands (type: control_command) → devices/{sn}/down/control
  • Kafka Topic: pull-ack-commands (type: pull_ack) → devices/{sn}/down/pull/ack

项目限制说明
单条消息大小256 KB打印内容应通过 URL 下载,不直接放在消息体
resources 数组大小100 个元素单次下发最多 100 个打印资源
状态上报频率10 条/分钟突发异常场景除外
主题路径长度256 字符包含完整路径
msgId 长度32 字符UUID v4 去掉连字符
jobId 长度32 字符UUID v4 去掉连字符
Bootstrap 连接参数有效期长期有效仅 JWT Token 需定期续期
JWT Token 有效期1 小时tokenTtlSec 指定

版本日期变更说明
v0.12025-11-20初始版本,定义基础通信协议

文档维护: 爱印科技-应用技术部-方江琛
最后更新: 2026-03-12