GrabBag/App/BeltTearing/Doc/撕裂TCP通信协议.md

597 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 皮带撕裂检测系统 TCP 通信协议
## 版本
版本: 1.6
日期: 2026-08-10
---
### 版本历史
| 版本 | 日期 | 修改内容 |
|------|------------|------------------|
| 1.6 | 2026-08-10 | 增加激光线点云二进制实时发送,以及可配置的抽线、抽点功能;<br/>算法和成像仍使用完整点云;<br/>DETECT_RESULT 始终广播,REALTIME_RESULT 由 SET_REALTIME 单独开启 |
| 1.5 | 2026-08-05 | 增加协议版本字段、完整报警数据、报警复位、重新检测、配置读写和协议能力查询;保留1.4字段兼容旧客户端 |
| 1.4 | 2026-02-21 | 增加CMD汇总表格(实时消息关系以1.6定义为准) |
| 1.3 | 2026-02-12 | 增加实时传输检测结果功能(SET_REALTIME/REALTIME_RESULT) |
| 1.2 | 2025-11-30 | 增加最大撕裂ID字段(maxId) |
| 1.1 | 2025-11-16 | 修改协议长度的格式 |
| 1.0 | 2025-11-11 | 初始版本 |
---
## 1. 协议概述
本协议用于皮带撕裂检测系统的TCP通信,支持撕裂检测结果上报、激光线点云实时传输、速度设置、启停控制等功能。
### 1.1 连接参数
- **服务器端**:视觉检测器(皮带撕裂检测系统)
- **客户端**:上位机或其他控制系统
- 服务器默认监听端口: **5800** (可配置)
- 客户端主动连接服务器
- 支持多客户端连接
### 1.2 协议特点
- 基于TCP长连接
- 控制和检测结果使用JSON,激光线点云使用二进制负载
- 消息头+消息体结构,解决TCP粘包问题
- 支持命令应答机制
- UTF-8编码
### 1.3 CMD 汇总表
| msgType | 方向 | 说明 | 详细章节 |
|---------|------|------|----------|
| `DETECT_RESULT` | 服务器 → 客户端 | 基础撕裂检测结果上报(历史最大值),始终发送给所有客户端 | 4.1 |
| `REALTIME_RESULT` | 服务器 → 客户端 | 实时检测结果上报(所有撕裂详细数据),<br/>仅发送给**已开启**实时传输的客户端 | 4.2 |
| `SET_SPEED` | 客户端 → 服务器 | 设置皮带速度(mm/s) | 5.1 |
| `SET_CONTROL` | 客户端 → 服务器 | 启动/停止检测 | 5.2 |
| `SET_REALTIME` | 客户端 → 服务器 | 开启/关闭实时传输 | 5.3 |
| `RESET_ALARM` | 客户端 → 服务器 | 清除报警并确认当前仍存在的撕裂,不重连相机 | 10.1 |
| `REST_DETECT` | 客户端 → 服务器 | 重新进行检测,与 App 的重置功能一致 | 10.1 |
| `GET_CONFIG` | 客户端 → 服务器 | 读取当前可调配置 | 10.2 |
| `SET_CONFIG` | 客户端 → 服务器 | 部分更新并持久化配置 | 10.2 |
| `GET_PROTOCOL_INFO` | 客户端 → 服务器 | 查询协议版本和能力 | 10.3 |
| `CONFIG_RESPONSE` | 服务器 → 客户端 | 配置读取或写入成功应答 | 6.2 |
| `PROTOCOL_INFO` | 服务器 → 客户端 | 协议能力应答 | 6.3 |
| `CMD_RESPONSE` | 服务器 → 客户端 | 控制命令的统一应答 | 6.1 |
| `HEARTBEAT` | 客户端 → 服务器 | 心跳消息 | 9.1 |
| `HEARTBEAT_ACK` | 服务器 → 客户端 | 心跳应答 | 9.1 |
---
## 2. 数据帧格式
为解决TCP粘包问题,采用**固定消息头+变长消息体**的帧格式:
```
+----------+------------+----------+----------+
| 帧头(8B) | 长度(8B) | 数据体 | 帧尾(4B) |
+----------+------------+----------+----------+
```
### 2.1 帧结构说明
| 字段 | 字节数 | 类型 | 说明 |
|----------|--------|---------------|----------------------------------------|
| 帧头 | 8 | char[8] | 固定字符串 `##START#` |
| 长度 | 8 | char[8] | 数据体长度(8位字符串),单位:字节 |
| 数据体 | 可变 | JSON字符串 | UTF-8编码的JSON数据 |
| 帧尾 | 4 | char[4] | 固定字符串 `#END` |
### 2.2 帧头帧尾定义
```cpp
#define FRAME_HEADER "##START#" // 8字节帧头
#define FRAME_TAIL "#END" // 4字节帧尾
```
---
## 3. 消息类型
所有消息的JSON数据体都包含以下公共字段:
```json
{
"msgType": "消息类型",
"protocolVersion": "1.6",
"timestamp": 1699776000000
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| msgType | string | 消息类型标识 |
| protocolVersion | string | 协议版本;服务器所有输出固定携带 `1.6` |
| timestamp | int64 | 时间戳(毫秒级Unix时间戳) |
客户端请求建议携带 `protocolVersion`。未携带时按1.4旧客户端兼容;显式版本低于1.4或主版本不一致时,服务器返回错误码1001。
---
## 4. 上报消息(服务器 → 客户端)
### 4.1 撕裂检测结果上报
**消息类型**: `DETECT_RESULT`
服务器始终向所有已连接客户端发送本消息,不受 `SET_REALTIME` 状态影响;无撕裂时 `count` 为0且 `tears` 为空数组。
**JSON格式**:
```json
{
"msgType": "DETECT_RESULT",
"protocolVersion": "1.6",
"timestamp": 1699776000000,
"alarm": true,
"count": 3,
"max": 125,
"maxLength": 125,
"maxWidth": 30,
"maxId": 12345,
"tears": [
{"id":12345,"status":2,"length":125,"width":30,"depth":8}
],
"visimg": "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|------------------------------------------|
| msgType | string | 是 | 固定值 `DETECT_RESULT` |
| timestamp | int64 | 是 | 检测时间戳(毫秒) |
| protocolVersion | string | 是 | 当前协议版本 `1.6` |
| alarm | bool | 是 | 本次消息是否包含未确认报警 |
| count | int | 是 | 撕裂个数 |
| max | int | 是 | 历史最大X方向长度,兼容1.4客户端 |
| maxLength | int | 是 | 历史最大X方向长度(毫米) |
| maxWidth | int | 是 | 历史最大长度对应撕裂的Y方向宽度(毫米) |
| maxId | int | 是 | 最大撕裂对应的撕裂ID(唯一标识符) |
| tears | array | 是 | 当前未确认的完整撕裂列表,字段同4.2 |
| visimg | string | 是 | Base64编码的检测结果图片(JPEG格式) |
**示例**:
```json
{
"msgType": "DETECT_RESULT",
"timestamp": 1699776000000,
"count": 2,
"max": 85,
"maxId": 10086,
"visimg": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
}
```
---
### 4.2 实时检测结果上报
当客户端开启实时传输功能后,服务器在每次检测完成时主动上报检测结果,包含所有撕裂的详细数据。
**消息类型**: `REALTIME_RESULT`
**JSON格式**:
```json
{
"msgType": "REALTIME_RESULT",
"timestamp": 1699776000000,
"count": 3,
"tears": [
{
"id": 10001,
"status": 1,
"length": 125,
"width": 30,
"depth": 8
},
{
"id": 10002,
"status": 0,
"length": 85,
"width": 20,
"depth": 5
}
],
"visimg": "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|------------------------------------------|
| msgType | string | 是 | 固定值 `REALTIME_RESULT` |
| timestamp | int64 | 是 | 检测时间戳(毫秒) |
| count | int | 是 | 撕裂个数 |
| tears | array | 是 | 撕裂详细数据列表,元素个数与 count 一致 |
| visimg | string | 是 | Base64编码的检测结果图片(JPEG格式) |
**tears 数组元素字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|------------------------------------------|
| id | int | 是 | 撕裂ID(唯一标识符) |
| status | int | 是 | 撕裂状态(0-未知,1-新发现,2-正在增长,3-已结束,4-无效) |
| length | int | 是 | 撕裂长度(单位:毫米) |
| width | int | 是 | 撕裂宽度(单位:毫米) |
| depth | int | 是 | 撕裂深度(单位:毫米,-1表示贯穿型撕裂) |
**status 状态值定义**(对应 `ESG_tearStatus`):
| 值 | 枚举名 | 说明 |
|----|------------------------------|----------------|
| 0 | keSG_tearStatus_Uknown | 未知 |
| 1 | keSG_tearStatus_New | 新发现的撕裂 |
| 2 | keSG_tearStatus_Growing | 正在增长的撕裂 |
| 3 | keSG_tearStatus_Ended | 撕裂已结束 |
| 4 | keSG_tearStatus_Invalid | 无效撕裂(可能被合并) |
**说明**:
- 实时传输功能需要客户端通过 `SET_REALTIME` 命令开启
- 开启后,服务器每次完成一帧检测即上报一次结果
- 关闭实时传输后,服务器停止上报 `REALTIME_RESULT` 消息
- `DETECT_RESULT` 始终发送;开启实时传输的客户端会在此基础上额外收到 `REALTIME_RESULT`
- 当 count 为 0 时,tears 为空数组 `[]`
**示例**(无撕裂时):
```json
{
"msgType": "REALTIME_RESULT",
"timestamp": 1699776000000,
"count": 0,
"tears": [],
"visimg": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
}
```
---
## 5. 控制命令(客户端 → 服务器)
### 5.1 设置速度命令
**消息类型**: `SET_SPEED`
**JSON格式**:
```json
{
"msgType": "SET_SPEED",
"timestamp": 1699776000000,
"speed": 1000
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|------------------------------|
| msgType | string | 是 | 固定值 `SET_SPEED` |
| timestamp | int64 | 是 | 命令时间戳(毫秒) |
| speed | int | 是 | 速度值(单位:mm/s,范围:0-5000) |
---
### 5.2 启停控制命令
**消息类型**: `SET_CONTROL`
**JSON格式**:
```json
{
"msgType": "SET_CONTROL",
"timestamp": 1699776000000,
"control": true
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|------------------------------|
| msgType | string | 是 | 固定值 `SET_CONTROL` |
| timestamp | int64 | 是 | 命令时间戳(毫秒) |
| control | bool | 是 | 启停状态(true-启动,false-停止)|
---
### 5.3 实时传输控制命令
**消息类型**: `SET_REALTIME`
**JSON格式**:
```json
{
"msgType": "SET_REALTIME",
"timestamp": 1699776000000,
"enable": true
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|-----------|--------|------|--------------------------------------|
| msgType | string | 是 | 固定值 `SET_REALTIME` |
| timestamp | int64 | 是 | 命令时间戳(毫秒) |
| enable | bool | 是 | 实时传输开关(true-开启,false-关闭) |
**说明**:
- 开启后,服务器每次检测完成即通过 `REALTIME_RESULT` 消息上报结果
- 关闭后,服务器停止实时上报
- 默认状态为关闭
- 服务器通过 `CMD_RESPONSE` 应答该命令
---
## 6. 应答消息(服务器 → 客户端)
所有控制命令都需要应答,应答格式统一。
### 6.1 命令应答格式
**消息类型**: `CMD_RESPONSE`
**JSON格式**:
```json
{
"msgType": "CMD_RESPONSE",
"timestamp": 1699776000000,
"cmdType": "SET_SPEED",
"result": true,
"errorCode": 0,
"errorMsg": ""
}
```
**字段说明**:
| 字段 | 类型 | 必填 | 说明 |
|------------|--------|------|------------------------------------|
| msgType | string | 是 | 固定值 `CMD_RESPONSE` |
| timestamp | int64 | 是 | 应答时间戳(毫秒) |
| cmdType | string | 是 | 原始命令类型(如 `SET_SPEED`) |
| result | bool | 是 | 执行结果(true-成功,false-失败) |
| errorCode | int | 是 | 错误码(成功时为0) |
| errorMsg | string | 是 | 错误描述(成功时为空字符串) |
---
## 7. 通信流程
### 7.1 速度设置流程
```
客户端 服务器
| |
|-------- SET_SPEED ------------>|
| { |
| "msgType": "SET_SPEED", |
| "speed": 1000 |
| } |
| |
|<------ CMD_RESPONSE -----------|
| { |
| "cmdType": "SET_SPEED", |
| "result": true, |
| "errorCode": 0 |
| } |
```
### 7.2 启停控制流程
```
客户端 服务器
| |
|------- SET_CONTROL ----------->|
| { |
| "msgType": "SET_CONTROL", |
| "control": true |
| } |
| |
|<------ CMD_RESPONSE -----------|
| { |
| "cmdType": "SET_CONTROL", |
| "result": true, |
| "errorCode": 0 |
| } |
| |
|<------ TEAR_RESULT ------------| (周期性上报)
| { |
| "count": 2, |
| "max": 85, |
| "visimg": "..." |
| } |
```
### 7.3 实时传输控制流程
```
客户端 服务器
| |
|------ SET_REALTIME ----------->|
| { |
| "msgType": "SET_REALTIME", |
| "enable": true |
| } |
| |
|<------ CMD_RESPONSE -----------|
| { |
| "cmdType": "SET_REALTIME", |
| "result": true, |
| "errorCode": 0 |
| } |
| |
|<--- DETECT_RESULT -------------| (基础结果始终上报)
| { ... } |
| |
|<--- REALTIME_RESULT -----------| (开启后每次检测完成额外上报)
| { |
| "msgType": "REALTIME_RESULT"|
| "count": 2, |
| "tears": [ |
| {"id":1,"status":1, |
| "length":85,"width":20, |
| "depth":5}, |
| {"id":2,"status":0, |
| "length":42,"width":15, |
| "depth":3} |
| ], |
| "visimg": "..." |
| } |
| |
|<--- REALTIME_RESULT -----------| (持续上报...)
| { ... } |
| |
|------ SET_REALTIME ----------->| (关闭实时传输)
| { |
| "msgType": "SET_REALTIME", |
| "enable": false |
| } |
| |
|<------ CMD_RESPONSE -----------|
| { |
| "cmdType": "SET_REALTIME", |
| "result": true, |
| "errorCode": 0 |
| } |
| |
| (仅停止 REALTIME_RESULT, |
| DETECT_RESULT 继续上报) |
```
---
## 8. TCP粘包处理
### 8.1 发送端处理
1. 将JSON数据转换为UTF-8字节数组
2. 计算数据长度(字节数)
3. 构造完整数据帧:
```
帧头(8字节 "##START#") + 长度(8字节字符串) + JSON数据 + 帧尾(4字节 "#END")
```
4. 发送完整数据帧
### 8.2 接收端处理
1. 维护接收缓冲区
2. 查找帧头(字符串 `##START#`)
3. 读取数据长度(8字节字符串)
4. 根据长度读取完整数据体
5. 验证帧尾(字符串 `#END`)
6. 解析JSON数据
7. 处理剩余缓冲区数据(可能包含下一帧)
---
## 9. 连接管理
### 9.1 心跳机制
为保持连接活跃,建议实现心跳机制:
**心跳消息**: `HEARTBEAT`
```json
{
"msgType": "HEARTBEAT",
"timestamp": 1699776000000
}
```
**心跳应答**: `HEARTBEAT_ACK`
```json
{
"msgType": "HEARTBEAT_ACK",
"timestamp": 1699776000000
}
```
- 心跳间隔: 30秒
- 超时时间: 90秒(3次心跳未收到则断开)
### 9.2 断线重连
- 客户端检测到连接断开后,每隔5秒尝试重连
- 最多重连次数: 无限制(或可配置)
---
## 10. 1.5/1.6 增强命令
### 10.1 报警复位与重新检测
```json
{"msgType":"RESET_ALARM","protocolVersion":"1.6","timestamp":1699776000000}
```
`RESET_ALARM` 清空 TCP/Modbus 报警锁存,并把当前仍存在的撕裂ID标记为已确认。该撕裂消失前不会重复报警,但仍会出现在实时结果和图像中。此命令不停止相机、不清空点云队列。
```json
{"msgType":"REST_DETECT","protocolVersion":"1.6","timestamp":1699776000000}
```
`REST_DETECT` 与 App 的“重新检测”功能一致:先停止检测流,清空旧点云队列、算法缓存和检测计数,再重新启动检测流;不会关闭或重新打开相机设备。两个命令均使用 `CMD_RESPONSE` 应答。
### 10.2 配置读取与部分更新
```json
{"msgType":"GET_CONFIG","protocolVersion":"1.6","requestId":"cfg-1"}
```
```json
{
"msgType":"SET_CONFIG",
"protocolVersion":"1.6",
"requestId":"cfg-2",
"config":{
"algorithmParams":{"tearingMinWidthY":10.0,"tearingMinDepthZ":3.0},
"cameraConfig":{"cameraIP":"192.168.1.100"},
"queueProcessParam":{"maxQueueSize":300,"generationInterval":100,"imageLineCount":300},
"pointCloudSendParam":{"enabled":true,"lineStep":5,"pointStep":4}
}
}
```
配置采用部分更新,未提供字段保持原值。`imageLineCount` 表示每张图使用的最近激光线数量,超过当前缓存数量时使用全部已缓存激光线。`lineStep=N` 表示每 N 条激光线发送 1 条,`pointStep=N` 表示每 N 个点发送 1 个,值为 1 时不抽样。成功时返回 `CONFIG_RESPONSE`;`reconnectRequired=true` 表示端口或相机地址改动需要重新建立相关连接。数值门槛必须大于等于0,队列参数、抽样步长和端口必须大于0。
### 10.3 协议能力查询
```json
{"msgType":"GET_PROTOCOL_INFO","protocolVersion":"1.6"}
```
服务器返回 `PROTOCOL_INFO`,包含 `protocolName`、`protocolVersion`、`minCompatibleVersion`、`softwareVersion` 和 `capabilities`。
## 11. 激光线点云实时发送
激光线点云与 JSON 控制响应共用同一条协议 TCP 连接。客户端需要根据首字节区分 JSON 帧(`##START#`)和点云二进制帧(`0x05`)。点云共用以下外层帧:
| 字段 | 字节数 | 类型 | 说明 |
|------|--------|------|------|
| dataType | 1 | uint8 | 点云固定为 `0x05` |
| payloadLength | 4 | uint32 | 点云负载长度,大端序 |
| payload | 可变 | binary | 见下表 |
| frameTail | 11 | char[11] | 固定为 `___END___\r\n` |
点云负载版本 1 的字段均采用大端序,浮点数为 IEEE 754 双精度:
| 字段 | 字节数 | 类型 | 说明 |
|------|--------|------|------|
| formatVersion | 1 | uint8 | 点云负载格式版本,当前为 1 |
| frameIndex | 8 | uint64 | 相机激光线帧号 |
| timestamp | 8 | uint64 | 相机时间戳 |
| originalPointCount | 4 | uint32 | 抽点前点数 |
| sampledPointCount | 4 | uint32 | 本包实际点数 |
| lineStep | 4 | uint32 | 当前抽线步长 |
| pointStep | 4 | uint32 | 当前抽点步长 |
| points | `sampledPointCount * 28` | repeated | 每点依次为 `int32 pointIndex`、`double x`、`double y`、`double z` |
抽线计数发生在完整激光线进入算法队列之后,抽点仅在构造 TCP 负载时执行,不会改变算法输入、点云缓存或二维图像生成数据。
---