GrabBag/App/ParkingSpaceGuide/Doc/停机引导对接协议.md

408 lines
18 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.

# 停机引导对接协议
## 版本信息
| 项目 | 内容 |
| --- | --- |
| 文档版本 | V1.1 |
| 更新日期 | 2026-09-08 |
| 适用范围 | UDP 组播状态包、HTTP 当前状态查询 |
| 说明 | 在 1.0 基础上增加工作模式、系统激活、设备状态,以及选择机型与检测机型的区分。 |
* 状态 JSON 协议名称为 `ParkingSpaceGuideResult`,`version` 为 `1.1`。
## 1. 协议概述
停机引导系统支持通过组播主动发送检测结果,也支持作为 HTTP 服务端,由现场系统按需查询当前停机状态。本协议(组播和 HTTP)只提供当前状态,没有历史查询地址。历史引导过程从本机记录库读取,字段与第 7 节相同。现场系统获取数据后,可解析当前停机位、目标编号、机型、到停止线距离、机身偏转角等信息。
访问方式:
| 方式 | 地址 | 数据内容 |
| --- | --- | --- |
| UDP 组播 | 默认 `239.255.0.1:8800` | 当前 `ParkingSpaceGuideResult` |
| HTTP GET | `http://<设备IP>:8801/api/parking/status` | 与组播相同的当前状态,不提供历史 |
| 记录库 | 见第 11 节 | 历史引导过程,字段与第 7 节一致 |
协议特点:
- 传输方式:组播,基于 UDP 数据报
- 查询方式:HTTP,停机引导系统作为服务端,现场系统作为客户端;仅当前状态
- 历史访问:本协议无历史 URL,使用第 11 节记录库连接信息
- 数据格式:JSON;历史记录字段与 JSON 协议相同
- 字符编码:UTF-8
- 组播数据方向:停机引导系统发送,现场系统接收
- HTTP 数据方向:现场系统请求,停机引导系统响应
- 组播应答机制:无应答
- HTTP 应答机制:请求-响应
- 组播重发机制:无重发
- 组播发送时机:每次检测结果更新时发送 1 包;`status`、轮挡时间或自检状态变化时也发送 1 包
## 2. 组播网络参数
组播网络参数由停机引导系统配置。
| 参数 | 默认值 | 说明 |
| --- | --- | --- |
| enabled | true | 是否启用组播发送。 |
| address | 239.255.0.1 | 组播地址。 |
| port | 8800 | 组播端口。 |
| targetId | T001 | 目标编号,由软件配置或现场系统约定。 |
| parkId | P01 | 当前停机位编号,由软件配置。 |
## 3. HTTP 查询对接
HTTP 查询用于现场系统主动获取当前停机状态。停机引导系统作为 HTTP 服务端,返回最近一次状态;系统刚启动且尚未产生检测结果时,返回第 6 节示例中的状态包。
| 参数 | 默认值 | 说明 |
| --- | --- | --- |
| enabled | true | 是否启用 HTTP 状态服务。 |
| address | 0.0.0.0 | HTTP 服务监听地址;`0.0.0.0` 表示监听本机所有网卡。 |
| port | 8801 | HTTP 服务端口。 |
| maxQueued | 16 | 等待处理的最⼤连接队列数。|
| maxThreads | 4 | 最⼤处理线程数。|
请求方式:
| 项目 | 内容 |
| --- | --- |
| URL | `http://<停机引导设备IP>:8801/api/parking/status` |
| Method | `GET` |
| Request Body | 无 |
| Response Content-Type | `application/json; charset=utf-8` |
兼容路径:
* /
* /status
* /api/status
* /api/parking/status
响应数据:
* HTTP 状态码 200 :返回当前停机状态 JSON,数据内容与 UDP 组播状态包⼀致,字段与第 4 ⾄第 7
节定义⼀致。
* HTTP 状态码 404 :请求路径不存在。
* HTTP 状态码 405 :请求⽅法不⽀持。
现场系统建议按 timestamp 判断数据是否更新,避免重复处理同⼀包状态。
现场系统建议按 `timestamp` 判断数据是否更新。
## 4. JSON 数据格式
每包组播数据为一个 JSON 对象。实际发送时为紧凑 JSON,不包含格式化换行。
HTTP 查询返回的数据内容与 UDP 组播数据一致,字段、含义、类型、单位和取值规则相同,仅传输方式不同。
本软件每次只检测一个飞机停机位,结果字段放在顶层对象中,不包含结果数组。
接收端应允许 JSON 增加字段。组播不保证到达和顺序,应以最新 `timestamp` 为准。`timestamp` 为 Unix 毫秒整数;其余时间字段为设备本地 `yyyy-MM-dd HH:mm:ss` 字符串,未记录时为空字符串。检测内部信息不对外发送。距离、偏转角、横向偏移、速度为浮点数;状态序号和错误码为整数。
## 5. 成功数据示例
```json
{
"protocol": "ParkingSpaceGuideResult",
"version": "1.1",
"success": true,
"hasResult": true,
"targetId": "T001",
"parkId": "P01",
"expectedModelType": "A320",
"modelType": "A320",
"modelMatched": true,
"guideStateCode": 21,
"distanceToStop": 50.0,
"bodyYawAngle": 0.0,
"lateralOffset": 0.0,
"aircraftSpeed": 0.4,
"hasException": false,
"guideText": "CHOCK ON",
"personChockTime": "2026-09-07 14:40:00",
"chockOnTime": "2026-09-07 14:40:05",
"chockOffTime": "",
"status": {
"workMode": "normal",
"activated": true,
"camera": { "name": "平面相机", "connected": true },
"lidar": { "name": "雷达", "connected": true },
"emergencyStop": {
"name": "急停",
"enabled": true,
"available": true,
"active": false,
"latched": false
}
},
"selfCheck": {
"running": false,
"ok": true,
"lidarOk": true,
"cameraOk": true,
"storageOk": true,
"networkOk": true,
"errorCode": 0,
"message": "自检通过:雷达、相机、存储、网络正常"
},
"message": "轮挡区域人员检测已确认,轮挡固定流程完成",
"errorCode": 0,
"timestamp": 1783339200000
}
```
选择名称包含 `A320` 或 `B737` 的配置机型时,按检测家族匹配:
```json
"expectedModelType": "A320-200 NEO",
"modelType": "A320",
"modelMatched": true
```
选择非 A320/B737 家族的配置机型时,`expectedModelType` 为配置中的机型名称,`modelType` 仍为检测结果(`A320`、`B737` 或 `其他`),`modelMatched` 为 `false`:
```json
"expectedModelType": "C919",
"modelType": "其他",
"modelMatched": false
```
## 6. 失败或无结果数据示例
检测失败、无有效目标或尚未开始引导时,仍发送状态包。`success=false`,`hasResult=false`。空闲包仍携带 `status`。
```json
{
"protocol": "ParkingSpaceGuideResult",
"version": "1.1",
"success": false,
"hasResult": false,
"targetId": "T001",
"parkId": "P01",
"expectedModelType": "",
"modelType": "未知",
"modelMatched": false,
"guideStateCode": 0,
"distanceToStop": 0.0,
"bodyYawAngle": 0.0,
"lateralOffset": 0.0,
"aircraftSpeed": 0.0,
"hasException": true,
"guideText": "",
"personChockTime": "",
"chockOnTime": "",
"chockOffTime": "",
"status": {
"workMode": "normal",
"activated": false,
"camera": { "name": "平面相机", "connected": true },
"lidar": { "name": "雷达", "connected": false },
"emergencyStop": {
"name": "急停",
"enabled": true,
"available": true,
"active": false,
"latched": false
}
},
"selfCheck": {
"running": false,
"ok": false,
"lidarOk": false,
"cameraOk": true,
"storageOk": true,
"networkOk": true,
"errorCode": 0,
"message": ""
},
"message": "无有效结果",
"errorCode": -1,
"timestamp": 1783339200000
}
```
## 7. 字段定义
类型均为 JSON 取值类型。`int` 为整数,`float` 为浮点数,`bool` 为布尔,`string` 为字符串,`object` 为对象。历史记录字段与下表相同,不再另列。
| 字段 | 类型 | 单位 | 说明 |
| --- | --- | --- | --- |
| protocol | string | - | 固定为 `ParkingSpaceGuideResult`。 |
| version | string | - | 协议版本,当前为 `1.1`。 |
| success | bool | - | 本包含有效结果且 `errorCode=0` 时为 `true`。 |
| hasResult | bool | - | 本包是否包含有效引导结果。 |
| targetId | string | - | 目标编号,默认 `T001`。 |
| parkId | string | - | 当前停机位编号,默认 `P01`。 |
| expectedModelType | string | - | 操作员选择的机型。未选择时为空。取值来自当前配置的可选机型,不是协议写死的清单。名称包含 `A320` 或 `B737` 时按家族校验;其余名称以现场配置为准。 |
| modelType | string | - | 相机检测机型。仅 `A320`、`B737`、`其他`;未检出为 `未知`。 |
| modelMatched | bool | - | 选择名称包含 `A320` 且 `modelType` 为 `A320`,或包含 `B737` 且 `modelType` 为 `B737` 时为 `true`。选择其他机型或不选时为 `false`。 |
| personChockTime | string | 日期时间 | 人员轮挡确认时间,设备本地时间,格式 `yyyy-MM-dd HH:mm:ss`;未确认时为空。 |
| chockOnTime | string | 日期时间 | 人工上轮挡时间,设备本地时间,格式 `yyyy-MM-dd HH:mm:ss`;未记录时为空。 |
| chockOffTime | string | 日期时间 | 人工下轮挡时间,设备本地时间,格式 `yyyy-MM-dd HH:mm:ss`;未记录时为空。 |
| status | object | - | 状态:工作模式、是否激活、相机/雷达/急停,见下表。 |
| selfCheck | object | - | 开始前自检结果,见下表。 |
| guideStateCode | int | - | 引导状态序号,见第 8 节;无状态为 `0`。 |
| distanceToStop | float | 毫米 | 到停止线距离。 |
| bodyYawAngle | float | 度 | 机身偏转角。 |
| lateralOffset | float | 毫米 | 相对引导中心线的横向偏移。 |
| aircraftSpeed | float | 米/秒 | 飞机接近速度。 |
| hasException | bool | - | `errorCode != 0`,或 `guideStateCode` 为 10~20、22~24 时为 `true`。 |
| guideText | string | - | 引导显示文本。 |
| message | string | - | 说明或异常原因。 |
| errorCode | int | - | `0` 正常。设备异常码见第 10 节;`-1` 表示无有效结果。 |
| timestamp | int | 毫秒 | 本包生成时刻,Unix 毫秒时间戳。除本字段外,其余时间均使用 `yyyy-MM-dd HH:mm:ss`。 |
`expectedModelType` 是页面选择的机型,`modelType` 是检测结果,二者不要混用。可选机型由配置维护。检测只区分 `A320`、`B737`、`其他`。选择名称包含 `A320` 且检测为 `A320` 算匹配,包含 `B737` 且检测为 `B737` 同样算匹配,例如选择 `A320-200 NEO` 检测 `A320`。仅这两类家族做校验,不一致可进入状态 15;选择 A321、C919 等其他配置机型不校验。检测置信度、是否支持精确校验、轮挡区域内人员及人数等内部信息不对外发送。
`status` 与 `selfCheck` 含义不同:`status` 是当前工作模式、激活情况和设备在线状态,`selfCheck` 是本次开始前的自检结果。工作模式和是否激活只放在 `status` 中,不再出现在顶层。
| status 字段 | 类型 | 说明 |
| --- | --- | --- |
| workMode | string | `normal` 正常模式;`maintenance` 维护模式。缺省按 `normal`。维护模式引导流程与正常模式相同。 |
| activated | bool | `true`:已开始且自检通过,正在引导。`false`:未开始、自检中或已停止。缺省按 `false`。 |
| camera.name | string | `平面相机` |
| camera.connected | bool | 平面相机是否在线 |
| lidar.name | string | `雷达` |
| lidar.connected | bool | 雷达是否在线 |
| emergencyStop.name | string | `急停` |
| emergencyStop.enabled | bool | 是否启用急停 |
| emergencyStop.available | bool | 急停输入是否可用 |
| emergencyStop.active | bool | 急停是否正在触发 |
| emergencyStop.latched | bool | 急停是否已锁存 |
| selfCheck 字段 | 类型 | 说明 |
| --- | --- | --- |
| running | bool | 是否正在自检 |
| ok | bool | 是否全部通过 |
| lidarOk | bool | 雷达 |
| cameraOk | bool | 平面相机 |
| storageOk | bool | 存储 |
| networkOk | bool | 网络 |
| errorCode | int | 见第 10 节。自检失败时与顶层 `errorCode` 相同。 |
| message | string | 说明 |
自检失败时 `guideStateCode=22`,`status.activated=false`。
人员轮挡时间与人工上/下轮挡时间相互独立。
## 8. 引导状态枚举
`guideStateCode` 为 `10` 至 `20` 或 `22` 至 `24` 时按异常处理,`hasException=true`。状态 `21` 为正常完成。状态 `8` 为停稳,保持约 5 秒后进入状态 `9`。
| 序号 | 流程/功能 | 显示文本 | 说明 |
| --- | --- | --- | --- |
| 1 | 泊位引导启动 | START | 已开始,距离不大于 100 m |
| 2 | 捕获 | CAPTURE | 距离大于 25 m 且不大于 80 m |
| 3 | 跟踪 | | 内部跟踪 |
| 4 | 接近率 | | 内部接近率 |
| 5 | 对准中心线 | 距离 | 距离不大于 25 m,横向和航向在容差内 |
| 6 | 慢速 | SLOW | 距离不大于 15 m,速度不小于 2 m/s |
| 7 | 方位引导 | 距离 | 距离不大于 25 m,横向或航向超差 |
| 8 | 到达停止位置 | STOP | 到停止线距离在 ±0.1 m 内 |
| 9 | 泊位引导完成 | OK | 停稳并保持约 5 秒 |
| 10 | 越位 | TOO FAR | 越过停止线不小于 0.5 m |
| 11 | 提前停止 | | 提前停止 |
| 12 | 等待 | | 未进入 100 m 范围或空闲 |
| 13 | 异常慢速-恶劣天气 | | 恶劣天气 |
| 14 | 飞机丢失 | | 引导中连续丢失 |
| 15 | 飞机验证失败 | ID FAIL | 选择名称包含 A320/B737 且与检测家族不一致 |
| 16 | 机位受阻 | GATE BLOCK | 机位受阻 |
| 17 | 视野受阻 | VIEW BLOCK | 视野受阻 |
| 18 | SBU停止 | | 安全备份停止 |
| 19 | 速度过快 | | 速度过快 |
| 20 | 紧急停止 | STOP | 急停有效 |
| 21 | 挡轮挡 | CHOCK ON | 人员轮挡已确认 |
| 22 | 系统错误 | ERROR | 自检或系统错误 |
| 23 | 系统故障 | | 系统故障 |
| 24 | 电源故障 | | 电源故障 |
## 9. 对接说明
现场系统建议优先解析:
- `targetId`、`parkId`
- `expectedModelType`、`modelType`、`modelMatched`
- `guideStateCode`、`guideText`
- `distanceToStop`、`bodyYawAngle`、`lateralOffset`、`aircraftSpeed`
- `personChockTime`、`chockOnTime`、`chockOffTime`
- `status.workMode`、`status.activated`
- `hasException`、`errorCode`、`timestamp`
设备异常时优先看 `errorCode`(`2200`~`2205`)和 `status` 中对应设备的在线状态。
状态判断:
- `success=true` 且 `hasResult=true`:本包含有效引导结果。
- `success=false`:异常、无目标或无有效结果。
- `status.activated=true`:系统已激活。
- `status.workMode=maintenance`:维护模式。
- `guideStateCode=8`:停稳(STOP);随后为 `9`(OK)。
注意事项:
- 组播不保证到达和顺序,以最新 `timestamp` 为准。
- 接收端应允许 JSON 增加字段。
- 数值单位以本协议为准。
- `selfCheck` 不能代替 `status`。
- 轮挡时间未记录时为空字符串,不要按 `0` 解析。
- 设备异常码见第 10 节;`-1` 不是设备故障,表示当前无有效引导结果。
- 组播和 HTTP 没有历史查询地址。历史见第 11 节记录库。
## 10. 错误码
顶层 `errorCode` 与 `selfCheck.errorCode` 使用同一套取值。`0` 为正常。设备异常使用 `2200`~`2205`。
| errorCode | 含义 | 说明 |
| ---: | --- | --- |
| 0 | 正常 | 本包无设备或系统错误。 |
| -1 | 无有效结果 | 未开始、空闲或尚无检测结果。不是设备故障。 |
| 2200 | 多项设备异常 | 雷达、相机、存储、网络中两项及以上异常。 |
| 2201 | 雷达异常 | 雷达离线、未运行或自检失败。 |
| 2202 | 平面相机异常 | 平面相机离线、未打开或自检失败。 |
| 2203 | 存储异常 | 本机存储不可写。 |
| 2204 | 网络异常 | 无可用 IPv4 网卡。 |
| 2205 | 急停输入异常 | 急停已启用但输入不可用。 |
判断方式:
- `errorCode=0`:无设备错误。引导是否异常看 `hasException` 和 `guideStateCode`(如 15 ID FAIL、20 急停按下)。
- `errorCode=-1`:无有效结果,通常 `success=false`、`hasResult=false`。
- `errorCode` 为 `2200`~`2204`:自检或运行中设备异常,`guideStateCode` 一般为 `22`,`status.activated=false`。
- `errorCode=2205`:急停输入异常,`guideStateCode` 一般为 `23`。
- 急停按钮按下是引导状态 `20`,不是本表设备错误码。
- 其他非 `0` 值按一般异常处理,结合 `message` 和 `guideStateCode`。
- `status.camera.connected`、`status.lidar.connected` 是实时在线状态,不能用 `selfCheck` 代替。
雷达异常示例:
```json
"success": false,
"hasResult": false,
"guideStateCode": 22,
"guideText": "ERROR",
"hasException": true,
"errorCode": 2201,
"message": "雷达异常",
"status": {
"workMode": "normal",
"activated": false,
"camera": { "name": "平面相机", "connected": true },
"lidar": { "name": "雷达", "connected": false }
}
```
## 11. 历史记录访问
组播和 HTTP **不支持**历史查询,没有历史 URL。当前状态地址见第 2、3 节。
历史引导过程从本机记录库读取,字段与第 7 节一致,不另列。`status`、`selfCheck` 按对象内字段存储。另有会话起止时间 `startTime`、`endTime`,格式与轮挡时间相同(`yyyy-MM-dd HH:mm:ss`,进行中的结束时间为空)。
连接信息:
| 参数 | 默认值 | 说明 |
| --- | --- | --- |
| 协议 | MariaDB | 使用 MariaDB / MySQL 兼容客户端连接。 |
| 地址 | 停机引导设备 IP | 与 HTTP 查询使用同一台设备。 |
| 端口 | 3306 | 记录库端口。 |
| 库名 | parking_guide | 默认库。 |
| 用户 | parking | 默认账号。 |
| 密码 | parking | 默认密码,现场可改。 |
默认保留最近 30 天。库不可用时引导、组播和 HTTP 仍可用,仅不写历史。