易点绘展厅触摸一体机 串口通信协议
| 项目 | 内容 |
|---|---|
| 协议名称 | 易点绘展厅串口通信协议 |
| 协议版本 | V1.0 |
| 发布日期 | 2026-08-30 |
| 适用产品 | 易点绘展厅触摸一体机(QBTTouch) |
| 通信方式 | RS232 / RS485(串口) |
| 适用范围 | 中控系统、第三方设备与本一体机之间的指令交互 |
1. 通信基础
1.1 物理参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| 串口号 | COM1(可配置) | 在"设置 → 中控设置"中配置,支持 COM1~COM256 |
| 波特率 | 115200 | 可配置:4800 / 9600 / 19200 / 38400 / 57600 / 115200 / 230400 / 460800 |
| 数据位 | 8 | 固定 |
| 校验位 | None | 固定 |
| 停止位 | 1 | 固定 |
双方波特率必须完全一致,否则通信失败或乱码。若一体机未配置串口,启动时不会自动打开串口,需先在设置页配置串口号并重启。
1.2 编码约定
- JSON 帧:UTF-8 编码的文本,以换行符
\n(0x0A)结尾,一条指令一行。 - HEX 帧:二进制字节流,按"帧头 + 长度"定位,不受
\n影响。
1.3 两种格式如何区分
一体机接收串口数据时按首字节判断:
| 首字节 | 判定 | 分帧方式 |
|---|---|---|
0xAA |
HEX 二进制帧 | 按帧结构(见第 3 章)切分 |
其它(如 { / [) |
JSON 文本帧 | 按 \n 切分,一行一帧 |
注意:HEX 帧不能用文本方式发送(如
"AA 01 10 02 00 64 21"这一串 ASCII 字符),必须是真实的二进制字节AA 01 10 02 00 64 21。
2. 指令总览
| 类别 | 指令 | HEX CMD | JSON cmd |
当前支持 |
|---|---|---|---|---|
| 系统 | 心跳 | 0x01 |
— | ⏳ 仅识别记录 |
| 系统 | 获取设备信息 | 0x02 |
— | ⏳ 仅识别记录 |
| 页面 | 页面跳转 | 0x10 |
Page.Open |
✅ 支持 |
| 页面 | 返回上一页 | 0x11 |
Page.Back |
✅ 支持 |
| 页面 | 返回首页 | 0x12 |
Page.Home |
✅ 支持 |
| 音频 | 设置音量 | 0x40 |
Audio.Volume |
✅ 支持 |
| 音频 | 静音 | 0x41 |
Audio.Mute |
✅ 支持 |
| 控件 | 控件单击 | 0x50 |
Control.Click |
✅ 支持 |
| 弹窗 | 打开弹窗 | 0x20 |
Popup.Open |
⏳ 预留 |
| 弹窗 | 关闭弹窗 | 0x21 |
Popup.Close |
⏳ 预留 |
| 视频 | 播放/暂停/停止/跳转 | 0x30~`0x33` |
Video.* |
⏳ 预留 |
| 场景 | 场景联动 | — | Scene.Run |
⏳ 预留 |
| 自定义 | 扩展指令 | 0x80~`0xFF` |
Light.* / Robot.* 等 |
⏳ 预留 |
✅ = 已实现动作;⏳ = 当前版本可正确识别并记录日志,但尚未触发业务动作(预留扩展)。
3. HEX 帧格式
3.1 帧结构
| 帧头 HEAD | 地址 ADDR | 命令 CMD | 长度 LEN | 数据 DATA | 校验 CRC |
| 1 字节 | 1 字节 | 1 字节 | 1 字节 | N 字节 | 1 字节 |
| 字段 | 长度 | 取值 | 说明 |
|---|---|---|---|
| HEAD | 1 Byte | 固定 0xAA |
帧头,用于识别 HEX 帧 |
| ADDR | 1 Byte | 0x00~`0xFF` |
设备地址(一体机目前不校验地址,按 0x01 使用) |
| CMD | 1 Byte | 0x01~`0xFF` |
命令码(见第 2 章) |
| LEN | 1 Byte | 0x00~`0xFA` |
数据区长度 N(0~250 字节) |
| DATA | N Byte | 具体指令参数 | 按指令定义 |
| CRC | 1 Byte | 校验值 | 见 3.2 |
3.2 CRC 校验算法
CRC = 帧头到数据区末尾所有字节的累加和,取低 8 位(不包含 CRC 自身)。
CRC = (HEAD + ADDR + CMD + LEN + DATA[0] + ... + DATA[N-1]) & 0xFF
示例:页面跳转指令 AA 01 10 02 00 64(跳转页面 100)
0xAA + 0x01 + 0x10 + 0x02 + 0x00 + 0x64
= 170 + 1 + 16 + 2 + 0 + 100
= 289 = 0x121
CRC = 0x121 & 0xFF = 0x21
完整帧:AA 01 10 02 00 64 21
若你的设备使用异或(XOR)等其它校验,可在一体机代码
PreviewWindow.CheckCrc中调整(一处即可)。
3.3 HEX 指令示例
心跳(CMD 0x01,预留)
AA 01 01 00 AC
CRC = 0xAA + 0x01 + 0x01 + 0x00 = 0xAC
页面跳转(CMD 0x10)— 跳转到指定页面
DATA 区为页面 ID 的 ASCII 文本(与 JSON 的 pageId 一致),支持两种写法:
- 完整 ID:
PAGE_639199874094277296(推荐,项目页面 ID 形如PAGE_+ 随机数字串) - 纯数字:
639199874094277296(一体机自动补PAGE_前缀)
示例:跳转到页面 PAGE_1(DATA = PAGE_1 的 ASCII 字节,共 6 字节)
AA 01 10 06 50 41 47 45 5F 31 6E
- LEN = 0x06,DATA =
PAGE_1→ ASCII:50 41 47 45 5F 31 - CRC = (0xAA+0x01+0x10+0x06+0x50+0x41+0x47+0x45+0x5F+0x31) & 0xFF = 0x6E
返回上一页(CMD 0x11)
AA 01 11 00 BC
返回首页(CMD 0x12)
AA 01 12 00 BD
设置音量(CMD 0x40)— 音量 50%
AA 01 40 01 32 1E
- LEN = 1,DATA[0] =
0x32= 50(范围 0~100,超出按 100 处理) - 作用于一体机的背景音乐音量
静音(CMD 0x41)— 静音
AA 01 41 01 01 EE
- LEN = 1,DATA[0] =
0x01(非 0 表示静音,0x00表示恢复)
控件单击(CMD 0x50)— 触发控件鼠标单击事件
DATA 区为控件 ID 的 ASCII 文本(控件 ID 在项目编辑器中定义,如 btn001)。
示例:触发控件 btn001 的单击事件(DATA = btn001 的 ASCII 字节,共 6 字节)
AA 01 50 06 62 74 6E 30 30 31 D6
- LEN = 0x06,DATA =
btn001→ ASCII:62 74 6E 30 30 31 - CRC = (0xAA+0x01+0x50+0x06+0x62+0x74+0x6E+0x30+0x30+0x31) & 0xFF = 0xD6
- 说明:控件必须存在且配置了行为事件(如页面跳转/打开弹窗等)才会触发,效果与用户鼠标单击一致;否则返回失败状态(1005 控件不存在或未配置事件)
4. JSON 指令格式
4.1 协议标准格式(cmd 字段)
JSON 指令以 { 开头,一行一条,末尾必须带 \n,UTF-8 编码。
{"cmd":"Page.Open","pageId":"PAGE_639199874094277296"}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cmd | string | ✅ | 指令名,见下表 |
| pageId | string(推荐)/ number | 页面指令 | 目标页面 ID(项目页面 ID 形如 PAGE_639199874094277296;传纯数字时自动补 PAGE_ 前缀) |
| id | number / string | 弹窗/视频指令 | 资源 ID |
| time | number | 视频指令 | 跳转时间(秒) |
| value | number / bool | 音频指令 | 音量 0~100,或静音 true/false |
| sceneId | string | 场景指令 | 场景 ID |
| channel | number | 自定义指令 | 通道号 |
| action | string | 自定义指令 | 动作名 |
4.2 标准指令示例
| 指令 | 示例(发送内容,含结尾 \n) |
|---|---|
| 页面跳转 | {"cmd":"Page.Open","pageId":"PAGE_639199874094277296"}(pageId 也可传纯数字 639199874094277296) |
| 返回上一页 | {"cmd":"Page.Back"} |
| 返回首页 | {"cmd":"Page.Home"} |
| 设置音量 50% | {"cmd":"Audio.Volume","value":50} |
| 静音 | {"cmd":"Audio.Mute","value":true} |
| 恢复音量 | {"cmd":"Audio.Mute","value":false} |
| 控件单击 | {"cmd":"Control.Click","id":"btn001"}(id 为目标控件 ID) |
| 打开弹窗(预留) | {"cmd":"Popup.Open","id":200} |
| 播放视频(预留) | {"cmd":"Video.Play","id":"001"} |
| 场景联动(预留) | {"cmd":"Scene.Run","sceneId":"Hall001"} |
4.3 兼容旧格式(项目内部 MessageCommand)
若 JSON 不含 cmd 字段,一体机会按项目原有指令格式解析,第三方也可使用:
| 指令 | 示例(发送内容,含结尾 \n) |
说明 |
|---|---|---|
| 页面跳转 | {"Command_Type":1,"PageID":"100"} |
Command_Type: 1 = PAGE_SKIP |
| 控件事件 | {"Command_Type":2,"ControlID":"btn001"} |
Command_Type: 2 = CONTROL_EVENT,触发指定控件的点击事件(控件行为在其内部按配置执行) |
可选字段:ProjectID、Content、ConnectType(飞屏形式)。
两种 JSON 格式可混用,推荐优先使用 4.2 的标准
cmd格式。
5. 指令行为说明
| 指令 | 一体机执行的动作 |
|---|---|
| 页面跳转(Page.Open / 0x10) | 主屏跳转到指定页面。目标为项目页面 ID(形如 PAGE_639199874094277296)。HEX 的 DATA 与 JSON 的 pageId 均传该 ID 文本;支持纯数字(自动补 PAGE_ 前缀)与数字后缀容错匹配;未找到对应页面则记录日志 |
| 返回上一页(Page.Back / 0x11) | 跳转到上一页(依据页面导航记录) |
| 返回首页(Page.Home / 0x12) | 跳转到当前项目的首页(Pages[0]) |
| 设置音量(Audio.Volume / 0x40) | 设置背景音乐音量,value/DATA 范围 0 |
| 静音(Audio.Mute / 0x41) | 静音(音量 0)或恢复(音量 1) |
| 控件单击(Control.Click / 0x50) | 触发当前页面指定控件的鼠标单击事件(控件需存在且配置了行为事件),效果与用户鼠标单击一致;事件逻辑在控件内部按行为类型执行。控件不存在或未配置事件时返回失败(1005) |
6. 返回状态指令
一体机收到任意指令后,无论执行成功与否,都会向发送方返回一条状态指令(串口为单设备连接,返回走同一串口)。
6.1 JSON 指令的返回(JSON 状态指令)
成功:
{"result":true,"echoCmd":"Page.Open","message":"页面跳转:PAGE_639199874094277296"}
失败:
{"result":false,"errorCode":1005,"echoCmd":"Page.Open","message":"页面不存在"}
| 字段 | 类型 | 说明 |
|---|---|---|
| result | bool | true 成功 / false 失败 |
| echoCmd | string | 回显请求的指令名(失败时也回显,便于定位) |
| message | string | 描述信息 |
| errorCode | number | 仅失败时出现,取值见 6.3 |
回执识别与防循环:
result与errorCode字段是一体机识别"响应回执"的标识。一体机收到含这两个字段(任一)的 JSON 时,会判定为回执并直接忽略、不再回发,以避免双向回执形成无限循环。因此对接方约定:① 业务指令中请勿使用result/errorCode字段名;② 对接方若也会对收到的指令返回回执,建议对带result字段的消息做同样的忽略处理。特殊说明:串口
0x02 获取设备信息指令的返回为设备信息报文,其字段名为cmd({"result":true,"cmd":"GetDeviceInfo",...}),与本节通用回执的echoCmd字段不同,请勿混淆。
编码说明:响应 JSON 中的中文(message 等)以
\uXXXX转义形式传输(如"页面不存在"→"\u9875\u9762\u4e0d\u5b58\u5728"),保证任意解码环境(GBK/ANSI/UTF-8)都不会乱码。\uXXXX是标准 JSON 转义,发送方用任意 JSON 解析器(JSON.parse / Newtonsoft / python json 等)解析后会自动还原为中文。
6.2 HEX 指令的返回(HEX 响应帧)
响应帧格式与请求帧相同,命令码为 请求 CMD | 0x80:
AA + 地址 + (CMD|0x80) + 长度 + 数据 + CRC
- 成功:LEN=1,DATA=
01 - 失败:LEN=2,DATA=
00 错误码(低字节)
示例(CRC 算法同请求帧,累加和取低 8 位):
| 请求 | 成功响应 | 失败响应 |
|---|---|---|
心跳 AA 01 01 00 AC |
AA 01 81 01 01 2E |
— |
页面跳转 AA 01 10 06 50 41 47 45 5F 31 6E |
AA 01 90 01 01 3D |
AA 01 90 02 00 E9 26(0xE9 = 1005 资源不存在) |
心跳成功响应
AA 01 81 01 01 2E与协议规范示例一致(0x81 = 0x01 | 0x80,DATA=01表示在线)。
6.3 错误码
| 编号 | 说明 |
|---|---|
| 0000 | 成功 |
| 1001 | 未知指令 |
| 1002 | 参数错误 |
| 1003 | 设备不存在 |
| 1004 | 执行失败 |
| 1005 | 资源不存在(如页面不存在) |
7. 对接示例
6.1 使用串口调试工具(SSCOM 等)
- 打开一体机"设置 → 中控设置",配置串口号(如 COM3)与波特率(115200),保存并重启。
- 用虚拟串口对或串口线连接第三方设备。
- SSCOM 连接对应 COM 口,波特率 115200。
- 发 JSON:切到文本模式,输入
{"cmd":"Page.Open","pageId":"PAGE_639199874094277296"},勾选"发送新行"(自动追加\n)。 - 发 HEX:切到 HEX 模式,输入
AA 01 10 06 50 41 47 45 5F 31 6E,以十六进制字节发送。
- 发 JSON:切到文本模式,输入
6.2 Python 示例(pyserial)
import serial
ser = serial.Serial("COM3", 115200, bytesize=8, parity="N", stopbits=1, timeout=1)
# 方式一:发送 JSON 指令(必须带 \n,UTF-8 编码;pageId 传完整页面 ID 字符串)
json_cmd = '{"cmd":"Page.Open","pageId":"PAGE_639199874094277296"}\n'
ser.write(json_cmd.encode("utf-8"))
# 方式二:发送 HEX 帧(DATA 为页面 ID 的 ASCII 文本,这里用 "PAGE_1" 作示例)
# 完整 ID 同理:data = b"PAGE_639199874094277296"
data = b"PAGE_1"
body = bytes([0xAA, 0x01, 0x10, len(data)]) + data
crc = sum(body) & 0xFF
hex_frame = body + bytes([crc]) # AA 01 10 06 50 41 47 45 5F 31 6E
ser.write(hex_frame)
ser.close()
6.3 C# 示例(System.IO.Ports)
using System.IO.Ports;
using (var sp = new SerialPort("COM3", 115200, Parity.None, 8, StopBits.One))
{
sp.Open();
// 发送 JSON 指令(带 \n,pageId 传完整页面 ID 字符串)
string json = "{\"cmd\":\"Page.Open\",\"pageId\":\"PAGE_639199874094277296\"}\n";
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
sp.Write(jsonBytes, 0, jsonBytes.Length);
// 发送 HEX 帧(DATA 为页面 ID 的 ASCII 文本,这里用 "PAGE_1" 作示例)
// 完整 ID 同理:Encoding.ASCII.GetBytes("PAGE_639199874094277296")
byte[] data = Encoding.ASCII.GetBytes("PAGE_1");
var body = new byte[] { 0xAA, 0x01, 0x10, (byte)data.Length }.Concat(data).ToArray();
byte crc = (byte)(body.Sum(b => b) & 0xFF);
var hexFrame = body.Concat(new byte[] { crc }).ToArray();
sp.Write(hexFrame, 0, hexFrame.Length);
sp.Close();
}
6.4 CRC 计算参考(Python)
def calc_crc(frame_head_to_data: bytes) -> int:
"""累加和取低 8 位(不含 CRC 自身)"""
return sum(frame_head_to_data) & 0xFF
# 页面跳转示例(DATA 为页面 ID 的 ASCII 文本)
page_id = "PAGE_1"
body = bytes([0xAA, 0x01, 0x10, len(page_id)]) + page_id.encode("ascii")
crc = calc_crc(body) # 0x6E
frame = body + bytes([crc]) # AA 01 10 06 50 41 47 45 5F 31 6E
8. 错误处理与注意事项
| 编号 | 说明 |
|---|---|
| 1 | 编码:JSON 必须 UTF-8;含中文内容时尤其注意,不要用 GBK/ASCII 发送 |
| 2 | 分帧:JSON 每条必须以 \n 结尾;HEX 帧长度必须等于 5 + LEN,LEN 超出 250 会被丢弃 |
| 3 | 波特率:必须与一体机配置一致,否则乱码或收不到 |
| 4 | 页面 ID:页面跳转的目标 ID 是一体机项目中的页面 ID(形如 PAGE_639199874094277296)。HEX 的 DATA 与 JSON 的 pageId 均传该 ID 文本(推荐),也可传纯数字(自动补 PAGE_ 前缀);传不存在的 ID 只会记录日志,不会跳转 |
| 5 | 预留指令:心跳 / 设备信息 / 弹窗 / 视频 / 场景 / 自定义指令当前仅识别并记录日志,不会触发动作,请勿依赖 |
| 6 | 音量范围:0~100,超出会被钳制 |
| 7 | 地址校验:一体机当前不校验 ADDR 字段,任何地址都会处理(建议按 0x01 使用,为将来多设备区分预留) |
9. 版本记录
| 版本 | 日期 | 说明 |
|---|---|---|
| V1.0 | 2026-08-30 | 发布初版:定义 JSON 与 HEX 两种帧格式;支持页面跳转 / 返回上一页 / 返回首页 / 设置音量 / 静音 / 控件单击;指令无论成败均返回状态(JSON 回执回显字段 echoCmd,HEX 指令返回 CMD|0x80 响应帧);补充错误码表 |
