跳转到内容

设备通讯协议(v1.0-ws)

文档版本: v1.0-ws
最后更新: 2026-06-24
适用对象: 设备固件开发者、第三方硬件集成商

日期更新内容
2026-06-241. 【下发-新增】文件打印 params.resources[] 新增 sourceType 字段,用于标识任务来源:printtext_to_imagetext_to_label,取值与 Pull 请求 params.type 保持一致 → 打印任务下发
2026-06-111. 【状态-补充】设备状态上报补充 Wi-Fi RSSI 与 4G LTE RSRP 的 dBm 口径、RSRP 索引换算和 4 格信号转换公式 → 设备状态上报
2. 【控制-新增】设备控制指令新增 report_state,平台可要求设备立即通过 /up/state 上报一次设备状态 → 设备控制指令
2026-06-051. 【协议-新增】发布单 WebSocket 通道设备协议,设备通过 protocolVersion=1.0-ws 接入,状态、Pull、打印、语音生成、固件升级、控制与心跳均复用同一 WebSocket 连接 → 协议范围
2. 【固件-补充】固件升级下发说明补齐 compression 最新处理要求,明确设备按实际下发的 url/hash/size/compression 处理文件 → 固件升级任务下发

本文档定义设备通过单个 WebSocket 长连接接入云打印平台时使用的消息格式、连接流程、任务处理时序和回执规则。

设备接入后,以下业务均通过同一个设备 WebSocket 通道传输:

业务上行消息下行消息关联章节
心跳保活/up/heartbeat/down/heartbeat心跳协议
状态上报/up/state-设备状态上报
任务拉取/up/pull/down/pull/ack/down/print/down/upgrade任务拉取请求
打印任务/up/print/ack/down/print打印任务下发
语音生成/up/voice_generate + Binary/down/print/down/voice_text语音生成任务
固件升级/up/upgrade/ack/down/upgrade固件升级任务下发
设备控制/up/control/ack/down/control设备控制指令
设备事件/up/event-设备事件上报

ASR 不需要设备单独连接 ASR 网关。设备在本协议的 WebSocket 通道内发送 /up/voice_generate 文本帧和音频 Binary 帧,云端完成识别后按 generateType 返回文本或打印任务。

链路协议帧类型使用时机
设备 -> Bootstrap APIHTTPS / HTTP/1.1JSON设备开机后、Token 过期前重新获取接入参数
设备 <-> 云端设备网关WebSocket (ws/wss)Text JSON发送通用信封消息,例如心跳、状态、任务、回执
设备 -> 云端设备网关WebSocketBinary/up/voice_generate 会话开始后发送音频字节
云端设备网关 -> 设备WebSocketBinary/down/printdeliverType=stream 时下发打印数据

设备侧实现至少需要保存以下 Bootstrap 返回值:

参数来源字段使用位置
WebSocket 地址data.websocket.url建立设备 WebSocket 连接
连接鉴权data.websocket.authorizationWebSocket 握手请求头 Authorization
Token 有效期data.websocket.tokenTtlSec到期前重新 Bootstrap 并重连
心跳周期data.websocket.keepalive/up/heartbeat 发送周期
消息类型映射data.messageTypes.*组装 messageType
ASR 首帧参数data.asr/up/voice_generatefunasrStart 默认值
状态上报周期data.stateReportInterval定时发送 /up/state
服务端时间data.serverTime校准设备时间或计算时间偏移

设备每次开机、网络恢复或 Token 失效后,按以下顺序接入:

  1. 初始化网络、读取设备 SN、固件版本、硬件型号、耗材和错误状态。
  2. 调用 Bootstrap,提交 snprotocolVersiontssign
  3. 使用 Bootstrap 返回的 data.websocket.url 建立 WebSocket 连接。
  4. WebSocket 握手时在请求头加入 Authorization: {data.websocket.authorization}
  5. 连接成功后立即发送 /up/state,上报当前 errCodewarnCodefirmware
  6. 发送 /up/pullparams.type=firmware,检查固件升级任务。
  7. 发送 /up/pullparams.type=print,拉取待打印任务。
  8. data.websocket.keepalive 周期发送 /up/heartbeat
  9. data.stateReportInterval 周期发送 /up/state;状态变化时立即补发 /up/state
  10. 持续监听 /down/print/down/upgrade/down/control/down/heartbeat/down/voice_text
sequenceDiagram
  autonumber
  participant Dev as 设备
  participant API as Bootstrap API
  participant Srv as 云端设备网关

  Dev->>Dev: 初始化网络、读取 SN、固件和设备状态
  Dev->>API: POST /api/v1/bootstrap
  API-->>Dev: WebSocket 地址、Authorization、消息类型、心跳、ASR 参数
  Dev->>Srv: WebSocket Connect + Authorization
  Srv-->>Dev: 连接建立
  Dev->>Srv: /up/state
  Dev->>Srv: /up/pull type=firmware
  Srv-->>Dev: /down/upgrade 或 /down/pull/ack
  Dev->>Srv: /up/pull type=print
  Srv-->>Dev: /down/print 或 /down/pull/ack
  loop keepalive 周期
    Dev->>Srv: /up/heartbeat
    Srv-->>Dev: /down/heartbeat
  end

连接断开后,设备按以下顺序恢复:

  1. 关闭本地旧 WebSocket 连接和未完成的 Binary 发送状态。
  2. 判断 authorization 是否仍在有效期内。
  3. 未过期时,使用原 WebSocket 参数重连。
  4. 已过期或连续重连失败时,重新调用 Bootstrap。
  5. 重连成功后发送 /up/state
  6. 如断开前存在未完成任务,根据任务类型发送最终回执或重新拉取任务。
POST https://cprint-api-stg.iprtapp.com/api/v1/bootstrap
{
"sn": "SN-XYZ-001",
"protocolVersion": "1.0-ws",
"ts": 1724040000000,
"sign": "abc123def456..."
}
字段类型必填说明
snstring设备序列号
protocolVersionstringWebSocket 协议版本,固定使用 1.0-ws
tsint6413 位毫秒时间戳
signstringHMAC-SHA256 签名,明文为 sn + ts
{
"code": 0,
"message": "OK",
"data": {
"device": {
"sn": "SN-TEST-001",
"model": "A40w-4G"
},
"websocket": {
"url": "wss://iot.byteone.com/ws/device",
"authorization": "Bearer eyJhbGciOiJIUzI1NiIs...",
"tokenTtlSec": 3600,
"keepalive": 60
},
"messageTypes": {
"upPull": "/up/pull",
"upVoiceGenerate": "/up/voice_generate",
"upPrintAck": "/up/print/ack",
"upUpgradeAck": "/up/upgrade/ack",
"upControlAck": "/up/control/ack",
"upState": "/up/state",
"upEvent": "/up/event",
"upHeartbeat": "/up/heartbeat",
"downPullAck": "/down/pull/ack",
"downPrint": "/down/print",
"downUpgrade": "/down/upgrade",
"downControl": "/down/control",
"downHeartbeat": "/down/heartbeat",
"downVoiceText": "/down/voice_text"
},
"asr": {
"model": "SenseVoiceSmall",
"language": "zh-CN",
"hotwordCacheId": "hotword_label_daily_v1",
"mode": "2pass",
"wav_format": "pcm",
"audio_fs": 16000,
"chunk_size": [5, 10, 5],
"chunk_interval": 10,
"itn": true
},
"stateReportInterval": 1800,
"serverTime": 1759991021000
}
}
字段路径类型必填使用位置
codeint0 表示获取成功
messagestring接口返回描述
data.device.snstring设备本次接入的 SN
data.device.modelstring固件升级拉取和状态上报中的设备型号
data.websocket.urlstringWebSocket 连接地址
data.websocket.authorizationstringWebSocket 握手请求头 Authorization
data.websocket.tokenTtlSecintToken 有效期,单位秒
data.websocket.keepaliveint/up/heartbeat 发送周期,单位秒
data.messageTypes.*string设备组装 messageType 时使用
data.asrobject/up/voice_generate 开始帧默认参数
data.stateReportIntervalint/up/state 定时上报周期,单位秒
data.serverTimeint64服务端 13 位毫秒时间

除 Binary 帧外,所有 WebSocket Text 消息均使用以下 JSON 信封:

{
"msgId": "32字符唯一ID",
"messageType": "/up/pull",
"ts": 1724044088000,
"params": {}
}
字段类型必填说明
msgIdstring消息唯一标识,使用 UUID v4 去连字符或等价唯一 ID;回执通过 ackOriginalMsgId 关联
messageTypestring消息类型路径,优先使用 Bootstrap 返回的 data.messageTypes
tsint6413 位毫秒时间戳
paramsobject业务参数对象
方向前置消息Binary 内容结束消息
设备 -> 云端/up/voice_generatestreamStage=start音频字节/up/voice_generatestreamStage=end
云端 -> 设备/down/printdeliverType=streamstreamStage=start打印数据字节/down/printstreamStage=end

设备收到或发送 Binary 帧时,需要根据当前会话状态区分音频数据和打印数据。不存在已开始的语音或流式打印会话时,忽略该 Binary 帧并上报设备事件或错误状态。

WebSocket 协议复用 MQTT 协议的业务字段名,业务载荷统一放入 WebSocket params 内:

MQTT 字段/语义WebSocket 字段路径说明
msgIdmsgId字段名一致
tsts字段名一致
MQTT 主题路径messageType例如 MQTT up/pull 对应 WebSocket /up/pull
MQTT 业务顶层字段params.*例如 MQTT resources 对应 WebSocket params.resources
Pull typeparams.type例如 printtext_to_labelfirmware
Pull paramsparams.paramsPull 的业务参数对象保留 params 字段名
Control paramsparams.params控制指令参数对象保留 params 字段名
Event eventType/eventParamsparams.eventType / params.eventParams事件字段名保持一致

messageType: /up/pull

设备在以下时机发送 Pull:

时机params.typeparams.params
开机上线后检查固件firmware当前硬件型号和固件版本
开机上线后拉取打印任务print{}
设备空闲时主动取任务print{}
文本生成图片text_to_imagewidthheightprompt 等生成参数
文本生成标签text_to_labelprompt、标签尺寸、语言、时区等生成参数
获取能力列表feature_list{}null
获取设备参数device_params{}null

普通打印任务拉取:

{
"msgId": "k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
"messageType": "/up/pull",
"ts": 1724044088000,
"params": {
"type": "print",
"params": {}
}
}

固件更新拉取:

{
"msgId": "k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z7",
"messageType": "/up/pull",
"ts": 1724044088000,
"params": {
"type": "firmware",
"params": {
"hardware": {
"deviceModel": "P5802"
},
"firmware": [
{
"firmwareType": "cloud",
"firmwareVersion": "1.2.3",
"nn": "NN-001"
},
{
"firmwareType": "printer",
"firmwareVersion": "3.4.5"
}
]
}
}
}
字段路径类型必填使用位置
params.typestring任务类型;为空时按 print 处理
params.paramsobject当前任务类型的业务参数
params.params.hardwareobjecttype=firmware 时上报硬件信息
params.params.hardware.deviceModelstringtype=firmware 时填写设备型号
params.params.firmwareobject[]type=firmware 时填写当前固件列表
params.params.firmware[].firmwareTypestringcloud/printer/bluetooth
params.params.firmware[].firmwareVersionstring当前固件版本
params.params.firmware[].nnstring对应固件类型的 NN 号
params.params.bizIdstringtype=text_to_imagetext_to_label 时填写业务 ID
params.params.widthint条件必填type=text_to_image 时为图片宽度(像素);type=text_to_label 时为标签宽度(mm)
params.params.heightint条件必填type=text_to_image 时为图片高度(像素);type=text_to_label 时为标签高度(mm)
params.params.promptstring条件必填type=text_to_imagetext_to_label 时填写用户输入文本
params.params.timezonestringtype=text_to_label 时填写设备时区
params.params.languagestringtype=text_to_label 时填写设备语言
params.params.fileTypestringimageprn
params.params.prnProtocolstring条件必填fileType=prn 时填写,当前支持 esc

云端响应:

  • 有普通打印任务时,下发 /down/print
  • 有固件升级任务时,下发 /down/upgrade
  • 无可用任务或返回功能/参数结果时,下发 /down/pull/ack

messageType: /up/voice_generate

设备通过 /up/voice_generate 发起语音生成会话。会话由一个开始帧、若干 Binary 音频帧和一个停止帧组成。

sequenceDiagram
  autonumber
  participant Dev as 设备
  participant Srv as 云端设备网关

  Dev->>Srv: /up/voice_generate streamStage=start
  loop 录音过程中
    Dev->>Srv: Binary 音频 chunk
  end
  Dev->>Srv: /up/voice_generate streamStage=end
  alt generateType=text
    Srv-->>Dev: /down/voice_text
  else generateType=label 或 image
    Srv-->>Dev: /down/print
    Dev->>Srv: /up/print/ack status=confirm
    Dev->>Srv: /up/print/ack status=printing
    Dev->>Srv: /up/print/ack status=success 或 failed
  end

语音会话处理步骤:

  1. 从 Bootstrap data.asr 读取 ASR 默认参数。
  2. 用户触发录音后发送开始帧,params.streamStage=start
  3. 将录音数据按 Binary frame 发送到同一个 WebSocket 通道。
  4. 录音结束后发送停止帧,params.streamStage=endparams.is_speaking=false
  5. 停止帧中携带本次音频的 crc32audioBytes
  6. generateType=text 时,等待 /down/voice_text
  7. generateType=labelimage 时,等待 /down/print 并按打印任务流程回执。

开始帧:

{
"msgId": "v-start-0001",
"messageType": "/up/voice_generate",
"ts": 1724045000000,
"params": {
"streamStage": "start",
"generateType": "label",
"bizId": "voice_print_label",
"deliverType": "file",
"fileType": "image",
"model": "SenseVoiceSmall",
"language": "zh-CN",
"hotwordCacheId": "hotword_label_daily_v1",
"funasrStart": {
"mode": "2pass",
"wav_name": "SN-TEST-001-1724045000000",
"wav_format": "pcm",
"audio_fs": 16000,
"chunk_size": [5, 10, 5],
"chunk_interval": 10,
"is_speaking": true,
"itn": true,
"hotwords": "",
"language": "zh-CN",
"retain_asr_record": false
}
}
}

生成 PRN 文件时,开始帧使用:

{
"params": {
"streamStage": "start",
"generateType": "label",
"deliverType": "file",
"fileType": "prn",
"prnProtocol": "esc"
}
}

Binary 音频帧:

funasrStart.wav_formatBinary 内容
pcm裸 PCM 字节,不带文件头
wavWAV 文件字节
mp3MP3 文件字节
mp4MP4 文件字节
flacFLAC 文件字节

停止帧:

{
"msgId": "v-end-0001",
"messageType": "/up/voice_generate",
"ts": 1724045003000,
"params": {
"streamStage": "end",
"is_speaking": false,
"crc32": "1a2b3c4d",
"audioBytes": 128000,
"errCode": [],
"msg": ""
}
}

设备本地录音异常时,在停止帧携带 errCodemsg

{
"msgId": "v-end-0002",
"messageType": "/up/voice_generate",
"ts": 1724045003000,
"params": {
"streamStage": "end",
"is_speaking": false,
"crc32": "1a2b3c4d",
"audioBytes": 124000,
"errCode": [2012],
"msg": "device memory pressure, dropped 4000 bytes before upload"
}
}
字段路径类型必填使用位置
params.streamStagestringstartend
params.generateTypestringstart 时必填label 生成标签并下发打印任务;image 生成图片并下发打印任务;text 返回识别文本
params.bizIdstringstart 时可选语音生成业务 ID
params.deliverTypestringstart 时可选filestream,默认 file
params.fileTypestringstart 时可选imageprngenerateType=label/image 时生效
params.prnProtocolstring条件必填fileType=prn 时填写,当前支持 esc
params.modelstringASR 模型,当前内置 CPU 部署支持 Fun-ASR-MLT-Nano-GGUFSenseVoiceSmall;配置 Azure 上游后也可使用 MicrosoftAzureSpeech
params.languagestring语言偏好,例如 zh-CN;支持语言见 ASR 服务 API 文档
params.hotwordCacheIdstring热词缓存 ID
params.funasrStart.modestringstart 时填写必须匹配所选 ASR 模型支持的模式;Fun-ASR-MLT-Nano-GGUF 仅支持 offlineSenseVoiceSmallMicrosoftAzureSpeech 支持 offlineonline2pass
params.funasrStart.wav_namestringstart 时填写音频会话名
params.funasrStart.wav_formatstringstart 时填写pcmwavmp3mp4flac
params.funasrStart.audio_fsintstart 时填写采样率,常用 16000
params.funasrStart.chunk_sizeint[]start 时填写分块参数,默认 [5,10,5]
params.funasrStart.chunk_intervalintstart 时填写分块间隔,默认 10
params.funasrStart.is_speakingboolstart 时填写开始帧填写 true
params.funasrStart.itnbool文本归一化,默认 true
params.funasrStart.hotwordsstring热词 JSON 字符串;未传时可使用 hotwordCacheId
params.funasrStart.languagestring标准语言码;未传时使用 params.language
params.funasrStart.retain_asr_recordbool是否保留本次识别记录
params.is_speakingboolend 时必填停止帧填写 false
params.crc32string本次会话全部原始音频字节 CRC32 十六进制字符串;兼容 crccrcCheckCodeaudioCrc32crs
params.audioBytesint本次会话全部原始音频字节长度;兼容 audioLengthrawAudioLengthrawAudioBytes
params.errCodeint/int[]设备上报的 ASR 错误码
params.msgstring设备上报的 ASR 错误描述

ASR 校验规则:

  1. 停止帧存在 crc32 时,云端用已收到的音频字节计算 CRC32;不一致时记录错误码 2010
  2. 停止帧存在 audioBytes 时,云端用已收到的音频字节长度比对;不一致时记录错误码 2011
  3. 设备出现本地内存不足并丢弃录音字节时,停止帧上报 errCode:[2012],后续 /up/state 上报 warnCode:[2012]
  4. 语音会话未发送停止帧即异常结束时,后续 /up/state 上报 warnCode:[2013]

messageType: /up/print/ack

收到 /down/print 后,设备按任务阶段发送回执:

阶段params.status发送时机
接收确认confirm收到 /down/print 并完成任务幂等检查后
打印开始printing文件下载、校验、解压完成并开始打印时
打印成功success设备完成打印并确认出纸状态后
打印失败failed下载、校验、解压、打印或设备状态不满足时
{
"msgId": "b2c3d4e5f67890a1b2c3d4e5f67890a1",
"messageType": "/up/print/ack",
"ts": 1724040088000,
"params": {
"jobIds": ["92ef08872ff906876071478274eec57b"],
"ackOriginalMsgId": "e5f6789012a3b4c5d6e7f89012a3b4c5",
"status": "confirm",
"queueStatus": "good",
"errCode": [],
"msg": "ok"
}
}
字段路径类型必填使用位置
params.jobIdsstring[]打印任务单 ID 数组;文件打印取 resources[].jobId,流式打印取 jobId
params.ackOriginalMsgIdstring对应 /down/printmsgId
params.statusstringconfirmprintingsuccessfailed
params.queueStatusstringconfirm 时填写队列状态:goodcongestedfull
params.errCodeint[]错误码数组,[] 表示成功
params.msgstring结果描述

messageType: /up/upgrade/ack

收到 /down/upgrade 后,设备按升级阶段发送回执:

阶段params.status发送时机
接收确认confirm收到升级任务并完成 deviceUpgradeId 幂等检查后
下载中downloading开始下载固件文件后,可按进度间隔上报
升级中upgrading固件文件校验完成并进入升级流程前
升级成功success升级完成并重启上线后
升级失败failed下载、校验、解压、写入或重启校验失败时
{
"msgId": "d4e5f6789012a3b4c5d6e7f89012a3b4",
"messageType": "/up/upgrade/ack",
"ts": 1724041088000,
"params": {
"deviceUpgradeId": "92ef08872ff906876071478274eec57b",
"ackOriginalMsgId": "f6789012a3b4c5d6e7f89012a3b4c5d6",
"status": "upgrading",
"errCode": [],
"msg": "ok"
}
}
字段路径类型必填使用位置
params.deviceUpgradeIdstring对应 /down/upgradedeviceUpgradeId
params.ackOriginalMsgIdstring对应 /down/upgrademsgId
params.statusstringconfirmdownloadingupgradingsuccessfailed
params.errCodeint[]错误码数组,[] 表示成功
params.msgstring结果描述

messageType: /up/control/ack

收到 /down/control 后,设备按以下顺序处理:

  1. 使用 controlId 做幂等检查。
  2. 发送 status=confirm 回执。
  3. 执行 command
  4. 执行成功后发送 status=success
  5. 执行失败或参数不支持时发送 status=failed,并携带 errCodemsg
{
"msgId": "g5h6i7j890k1l2m3n4o5p6q789r0s1t2",
"messageType": "/up/control/ack",
"ts": 1724042088000,
"params": {
"controlId": "a351eff1b614d0c1f64227d0c4b28c99",
"ackOriginalMsgId": "h6i7j890k1l2m3n4o5p6q789r0s1t2u3",
"status": "confirm",
"errCode": [],
"msg": "ok"
}
}
字段路径类型必填使用位置
params.controlIdstring对应 /down/controlcontrolId
params.ackOriginalMsgIdstring对应 /down/controlmsgId
params.statusstringconfirmsuccessfailed
params.errCodeint[]错误码数组,[] 表示成功
params.msgstring结果描述

messageType: /up/state

设备在以下时机发送状态:

时机上报内容
WebSocket 连接成功后当前设备状态、固件版本、错误码、警告码
stateReportInterval 周期到达当前设备状态
设备错误或警告变化最新 errCodewarnCode
打印任务完成后耗材、错误码、计数等变化字段
固件升级重启上线后新固件版本
ASR 异常后warnCode:[2012]warnCode:[2013]
{
"msgId": "a1b2c3d4e5f6789012345678901234ab",
"messageType": "/up/state",
"ts": 1724040060000,
"params": {
"rssi": -58,
"battery": 90,
"paper": 1,
"paperType": "roll",
"errCode": [],
"warnCode": [2013],
"temperature": 35.2,
"humidity": 45,
"ipAddress": "192.168.1.25",
"bluetoothMac": "00:1A:7D:DA:71:13",
"imei": "865123456789012",
"iccid": "89860123456789012345",
"signalStrength": -75,
"networkType": "4G",
"printCount": 12345,
"avgLatency": 150,
"packetLossRate": 2,
"charging": false,
"sleepTime": 10,
"firmware": [
{
"firmwareType": "cloud",
"firmwareVersion": "1.2.3",
"nn": "NN-001"
},
{
"firmwareType": "printer",
"firmwareVersion": "3.4.5",
"nn": "NN-002"
}
]
}
}
字段路径类型必填说明
params.rssiintWi-Fi RSSI,单位 dBm,通常为负数,数值越接近 0 信号越强
params.signalStrengthint4G LTE RSRP,单位 dBm,通常为负数;不要上报 RSRP 原始索引值
params.networkTypestring网络类型:WiFi4G5G
params.errCodeint[]阻塞性错误码,[] 表示无错误
params.warnCodeint[]非阻塞警告码,[] 表示无警告
params.firmwareobject[]当前固件列表
params.firmware[].firmwareTypestringcloudprinterbluetooth
params.firmware[].firmwareVersionstring当前固件版本
params.firmware[].nnstring对应固件类型的 NN 号

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

params.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无效值,不上报 params.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 格。

messageType: /up/event

设备在发生用户操作、任务中断、设备本地事件时发送事件。

{
"msgId": "h7i8j9k012l3m4n5o6p7q8r901s2t3u4",
"messageType": "/up/event",
"ts": 1724043088000,
"params": {
"eventType": "stop_print",
"eventParams": {
"reason": "user_button"
}
}
}
字段路径类型必填说明
params.eventTypestring事件类型,例如 stop_print
params.eventParamsobject事件参数

messageType: /down/pull/ack

云端在 Pull 请求无直接任务下发、返回功能列表或返回设备参数时发送该消息。

{
"msgId": "pull-ack-0001",
"messageType": "/down/pull/ack",
"ts": 1724044089000,
"params": {
"ackOriginalMsgId": "k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
"type": "print",
"errCode": [],
"msg": "no task",
"dateTime": 1724044089000
}
}
字段路径类型必填使用位置
params.ackOriginalMsgIdstring对应 /up/pullmsgId
params.typestring对应 /up/pullparams.type
params.errCodeint[]错误码数组,[] 表示请求成功
params.msgstring响应描述
params.paramsobject功能列表或设备参数等响应数据
params.dateTimeint64服务端时间

messageType: /down/print

设备收到 /down/print 后,先发送 /up/print/ack status=confirm,再按 deliverType 处理打印数据。

文件打印处理步骤:

  1. 读取 resources
  2. 使用每个 resources[].jobId 做幂等检查。
  3. 发送 /up/print/ackstatus=confirm
  4. 下载 resources[].url
  5. 校验下载文件大小和 hash
  6. compression=gzip 时先解压。
  7. 根据 fileType 处理文件;prn 直接进入打印协议,image 进入设备图像打印流程。
  8. 开始打印时发送 status=printing
  9. 打印成功发送 status=success;失败发送 status=failed
{
"msgId": "e5f6789012a3b4c5d6e7f89012a3b4c5",
"messageType": "/down/print",
"ts": 1724846400000,
"params": {
"deliverType": "file",
"resources": [
{
"jobId": "j-202408-0001",
"url": "https://obj.example.com/prints/j-202408-0001.data",
"hash": "sha256:ab12cd34ef56...",
"size": 102400,
"fileType": "prn",
"prnProtocol": "esc",
"sourceType": "print",
"compression": "gzip"
}
],
"dateTime": 1724846400000
}
}

流式打印处理步骤:

  1. 收到 deliverType=streamstreamStage=start/down/print
  2. 使用 jobId 做幂等检查。
  3. 发送 /up/print/ackstatus=confirm
  4. 接收后续 WebSocket Binary frame,并写入打印缓冲。
  5. 开始输出时发送 /up/print/ackstatus=printing
  6. 收到 streamStage=end 后校验 crc32dataBytes
  7. 打印成功发送 status=success;校验或打印失败发送 status=failed

开始帧:

{
"msgId": "p-start-0001",
"messageType": "/down/print",
"ts": 1724045010000,
"params": {
"deliverType": "stream",
"streamStage": "start",
"ackOriginalMsgId": "v-end-0001",
"jobId": "j-voice-0001",
"fileType": "prn",
"prnProtocol": "esc",
"dateTime": 1724045010000
}
}

结束帧:

{
"msgId": "p-end-0001",
"messageType": "/down/print",
"ts": 1724045015000,
"params": {
"deliverType": "stream",
"streamStage": "end",
"jobId": "j-voice-0001",
"crc32": "0f1e2d3c",
"dataBytes": 204800,
"errCode": [],
"msg": "ok",
"dateTime": 1724045015000
}
}
字段路径类型必填使用位置
params.deliverTypestringfilestream
params.resourcesobject[]条件必填deliverType=file 时填写打印资源列表
params.resources[].jobIdstring打印任务单 ID,用于 /up/print/ack.params.jobIds
params.resources[].urlstring文件下载 URL
params.resources[].hashstringSHA256 哈希,格式 sha256:十六进制字符串
params.resources[].sizeint文件大小,单位字节
params.resources[].fileTypestringprnimage
params.resources[].prnProtocolstringfileType=prn 时返回,当前支持 esc
params.resources[].sourceTypestring任务来源类型,取值与 Pull 请求 params.type 保持一致:printtext_to_imagetext_to_label
params.resources[].compressionstringnonegzip
params.streamStagestring条件必填deliverType=stream 时填写 startend
params.ackOriginalMsgIdstring流式打印关联的原始上行消息 ID,例如语音停止帧 msgId
params.jobIdstring条件必填deliverType=stream 时的打印任务单 ID
params.crc32stringend 时必填流式打印全部 Binary 字节 CRC32 十六进制字符串
params.dataBytesintend 时必填流式打印全部 Binary 字节长度;设备可兼容读取 bytes
params.errCodeint[]流结束状态错误码,[] 表示成功
params.msgstring流结束状态描述
params.dateTimeint64服务端时间

messageType: /down/voice_text

仅当 /up/voice_generate 开始帧中 params.generateType=text 时使用。设备收到后使用 ackOriginalMsgId 关联语音会话。

{
"msgId": "voice-text-0001",
"messageType": "/down/voice_text",
"ts": 1724045010000,
"params": {
"ackOriginalMsgId": "v-end-0001",
"generateType": "text",
"text": "打印一张开封特产标签",
"errCode": [],
"msg": "",
"dateTime": 1724045010000
}
}
字段路径类型必填使用位置
params.ackOriginalMsgIdstring对应 /up/voice_generate 停止帧 msgId
params.generateTypestring固定为 text
params.textstring最终语音识别文本
params.errCodeint[]错误码数组,[] 表示成功
params.msgstring结果描述
params.dateTimeint64服务端时间

messageType: /down/upgrade

设备收到 /down/upgrade 后,按 deviceUpgradeId 做幂等处理。已处理成功的升级任务不重复执行;正在处理的任务可继续上报当前阶段。

sequenceDiagram
  autonumber
  participant Srv as 云端设备网关
  participant Dev as 设备

  Srv-->>Dev: /down/upgrade
  Dev->>Srv: /up/upgrade/ack status=confirm
  Dev->>Dev: 下载固件文件
  Dev->>Srv: /up/upgrade/ack status=downloading
  Dev->>Dev: 校验 hash 和 size
  Dev->>Dev: 按 compression 解压
  Dev->>Srv: /up/upgrade/ack status=upgrading
  Dev->>Dev: 写入固件并重启
  Dev->>Srv: /up/upgrade/ack status=success 或 failed
  Dev->>Srv: /up/state firmware=新版本
{
"msgId": "f6789012a3b4c5d6e7f89012a3b4c5d6",
"messageType": "/down/upgrade",
"ts": 1724846400000,
"params": {
"deviceUpgradeId": "u-202408-0001",
"firmwareType": "cloud",
"firmwareVersion": "1.2.4",
"url": "https://obj.example.com/fw/p5802-1.2.4.bin.gz",
"hash": "sha256:cd34ef56ab78...",
"size": 5242880,
"compression": "gzip",
"dateTime": 1724846400000
}
}
字段路径类型必填使用位置
params.deviceUpgradeIdstring升级任务唯一标识,用于幂等去重和 /up/upgrade/ack
params.firmwareTypestringcloudprinterbluetooth
params.firmwareVersionstring目标固件版本
params.urlstring固件下载 URL
params.hashstring下发文件 SHA256,格式 sha256:十六进制字符串
params.sizeint下发文件大小,单位字节
params.compressionstringnonegzipgzip 表示下载文件校验后需要解压
params.dateTimeint64服务端时间

固件升级处理步骤:

  1. 收到任务后发送 /up/upgrade/ackstatus=confirm
  2. 下载固件文件;下载过程中可发送 status=downloading
  3. sizehash 校验下载文件。
  4. compression=gzip 时解压下载文件。
  5. 进入升级写入前发送 status=upgrading
  6. 升级完成并重启上线后发送 status=success
  7. 发送 /up/state,在 firmware 中上报新版本。
  8. 任一步骤失败时发送 status=failed,携带 errCodemsg

messageType: /down/control

{
"msgId": "h6i7j890k1l2m3n4o5p6q789r0s1t2u3",
"messageType": "/down/control",
"ts": 1724846400000,
"params": {
"controlId": "a351eff1b614d0c1f64227d0c4b28c99",
"command": "reboot",
"params": {},
"dateTime": 1724846400000
}
}
字段路径类型必填使用位置
params.controlIdstring控制指令 ID,用于幂等去重和 /up/control/ack
params.commandstring控制命令
params.paramsobject控制命令参数
params.dateTimeint64服务端时间

支持的 command

命令设备动作
shutdown关机
reboot重启
beep蜂鸣
reset_wifi重置 Wi-Fi
reset_bluetooth重置蓝牙
factory_reset恢复出厂设置
clear_cache清理缓存
set_params设置设备参数,参数从 params.params 读取
report_state立即上报当前设备状态;设备确认收到后发送 /up/state,完成后回 success

report_state 用于平台主动刷新设备状态。该控制指令不携带超时参数;设备收到后立即上报当前状态即可。管理端 HTTP 刷新接口默认等待 10 秒;等待期间设备通过 /up/state 上报状态后,平台会立即把最新状态返回给 HTTP 客户端,超时则返回当前缓存状态并标记超时。

设备按 Bootstrap 返回的 data.websocket.keepalive 周期发送心跳。云端返回 /down/heartbeat 时,设备用 ackOriginalMsgId 关联本次心跳。

连续多个周期未收到 /down/heartbeat 或 WebSocket 连接异常时,设备进入重连流程。

上行心跳:

{
"msgId": "hb-up-0001",
"messageType": "/up/heartbeat",
"ts": 1724040005000
}

下行心跳:

{
"msgId": "hb-down-0001",
"messageType": "/down/heartbeat",
"ts": 1724040005001,
"params": {
"ackOriginalMsgId": "hb-up-0001"
}
}
字段路径类型必填使用位置
params.ackOriginalMsgIdstring对应 /up/heartbeatmsgId
sequenceDiagram
  autonumber
  participant Srv as 云端设备网关
  participant Dev as 设备

  Srv-->>Dev: /down/print deliverType=file
  Dev->>Srv: /up/print/ack status=confirm
  Dev->>Dev: 下载、校验、解压资源
  Dev->>Srv: /up/print/ack status=printing
  Dev->>Dev: 打印
  Dev->>Srv: /up/print/ack status=success 或 failed
  Dev->>Srv: /up/state
sequenceDiagram
  autonumber
  participant Dev as 设备
  participant Srv as 云端设备网关

  Dev->>Srv: /up/voice_generate streamStage=start
  Dev->>Srv: Binary 音频
  Dev->>Srv: /up/voice_generate streamStage=end
  Srv-->>Dev: /down/print deliverType=file 或 stream
  Dev->>Srv: /up/print/ack status=confirm
  Dev->>Srv: /up/print/ack status=printing
  Dev->>Srv: /up/print/ack status=success 或 failed
sequenceDiagram
  autonumber
  participant Srv as 云端设备网关
  participant Dev as 设备

  Srv-->>Dev: /down/control
  Dev->>Srv: /up/control/ack status=confirm
  Dev->>Dev: 执行 command
  opt command=report_state
    Dev->>Srv: /up/state
  end
  Dev->>Srv: /up/control/ack status=success 或 failed
错误码含义上报位置
2010ASR 录音 CRC 校验不一致云端记录;设备检查停止帧 crc32
2011ASR 录音长度不一致云端记录;设备检查停止帧 audioBytes
2012ASR 本地内存不足丢弃录音字节/up/voice_generate 停止帧 errCode/up/state.warnCode
2013ASR 会话异常结束/up/state.warnCode
4001固件下载失败/up/upgrade/ack.errCode
4002升级失败或回滚/up/upgrade/ack.errCode
4003固件校验失败/up/upgrade/ack.errCode
4004固件版本不兼容/up/upgrade/ack.errCode

设备固件接入完成前,按以下项目核对:

  1. 开机后先调用 Bootstrap,再建立 WebSocket。
  2. WebSocket 握手请求头携带 Bootstrap 返回的 Authorization
  3. 所有 Text 消息包含 msgIdmessageTypets
  4. 回执消息通过 ackOriginalMsgId 关联下行 msgId
  5. 连接成功后立即上报 /up/state
  6. 上线后先拉取 firmware,再拉取 print
  7. 心跳周期使用 Bootstrap 返回的 keepalive
  8. 语音生成按 start、Binary、end 顺序发送。
  9. 语音停止帧携带 is_speaking=false,并可携带 crc32audioBytes
  10. 收到 /down/print 后先回 confirm,再处理下载或流式数据。
  11. 收到 /down/upgrade 后按 confirmdownloadingupgradingsuccess/failed 回执。
  12. 收到 /down/control 后按 confirmsuccess/failed 回执;其中 report_state 需要在成功回执前立即补发 /up/state
  13. 固件升级成功重启后发送 /up/state 上报新版本。
  14. Token 到期前重新 Bootstrap 并重连。

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