diff --git a/doc/对接文档/网关与Vol.Pro对接API手册.md b/doc/对接文档/网关与Vol.Pro对接API手册.md new file mode 100644 index 0000000..e6f47e3 --- /dev/null +++ b/doc/对接文档/网关与Vol.Pro对接API手册.md @@ -0,0 +1,748 @@ +# SecMPS 网关与 Vol.Pro 对接 API 手册 + +> **版本**: v1.0 +> **日期**: 2026-05-16 +> **基于**: SecMPS_最终整合方案_v3.0.md +> **接口数量**: 13 个(A 组 4 个 + B 组 9 个) + +--- + +## 1. 引言 + +### 1.1 目标与范围 + +本手册定义 IntegrationGateway(网关)与 Vol.Pro 后端之间所有 HTTP API 的接口规范。供网关开发、Vol.Pro 后端开发、前端开发和 AI Agent 编码时参考。 + +### 1.2 基本约定 + +| 约定 | 说明 | +|------|------| +| 请求方法 | A 组使用 **POST**,B 组使用 **GET / POST** | +| 数据格式 | **JSON**,`Content-Type: application/json` | +| 字符编码 | **UTF-8** | +| 认证方式 | A 组: `NodeToken`(请求体中携带),B 组: 内网直连,无认证 | +| 网关端口 | **5100**(默认) | +| Vol.Pro 端口 | **9100**(默认) | + +### 1.3 响应格式 + +**成功**: +```json +{ + // 具体数据,见各接口定义 +} +``` +HTTP Status: 200 + +**失败**: +```json +{ + "message": "错误描述" +} +``` +HTTP Status: 400(业务错误)/ 401(认证失败)/ 500(服务器错误) + +--- + +## 2. A 组接口:网关 → Vol.Pro + +> 调用方: 网关 +> 接收方: Vol.Pro 后端 +> 端口: 9100 + +--- + +### 2.1 A1 — 网关注册 + +网关启动时调用,上报身份与能力,获取所管理的顶层设备列表。 + +- **Endpoint**: `POST /api/gateway/register` +- **认证**: NodeToken +- **逻辑**: Upsert — NodeCode 匹配则更新,不匹配则插入 + +#### 请求体 + +```json +{ + "nodeCode": "gw-31ku", + "token": "a1b2c3d4e5f6", + "adapterTypes": "MC4,Owl", + "baseUrl": "http://192.168.1.100:5100" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| nodeCode | string | ✅ | 网关唯一编码,管理端生成 | +| token | string | ✅ | 认证令牌,管理端生成 | +| adapterTypes | string | ✅ | 支持的适配器类型,逗号分隔,例如 "MC4,Owl" | +| baseUrl | string | ✅ | 网关自身地址(含端口),供管理端回调 | + +#### 响应体(成功) + +```json +{ + "nodeId": 1, + "devices": [ + { + "deviceId": 10, + "deviceName": "动环采集器", + "adapterCode": "MC4:31ku", + "sourceId": "1001", + "deviceCategory": "动环采集器", + "deviceGroup": "IoT设备", + "isParent": "是", + "parentSourceId": null, + "isOnline": "在线", + "ipAddress": "10.0.1.100", + "port": 3000, + "extraData": { + "mc4DeviceId": 1001 + } + } + ] +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| nodeId | int | 网关在 Vol.Pro 中的 NodeId | +| devices | array | 当前网关负责的顶层设备列表(base_device 中 GatewayNodeId=本网关 且 ParentDeviceId IS NULL 的记录) | +| devices[].deviceId | int | Vol.Pro 内部设备ID | +| devices[].adapterCode | string | 双段标识 "MC4:31ku" | +| devices[].sourceId | string | 第三方原始设备ID | +| devices[].extraData | object | 适配器扩展数据 | + +#### 响应体(失败) + +```json +// HTTP 401 +{ + "message": "认证失败" +} +``` + +#### 请求示例 + +```bash +curl -X POST http://localhost:9100/api/gateway/register \ + -H "Content-Type: application/json" \ + -d '{"nodeCode":"gw-31ku","token":"a1b2c3d4e5f6","adapterTypes":"MC4,Owl","baseUrl":"http://192.168.1.100:5100"}' +``` + +--- + +### 2.2 A2 — 网关心跳 + +网关每 15 秒调用,Vol.Pro 更新 LastHeartbeat 和 IsOnline。 + +- **Endpoint**: `POST /api/gateway/heartbeat` +- **认证**: NodeToken +- **频率**: 每 15 秒 + +#### 请求体 + +```json +{ + "nodeCode": "gw-31ku", + "token": "a1b2c3d4e5f6" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| nodeCode | string | ✅ | 网关唯一编码 | +| token | string | ✅ | 认证令牌 | + +#### 响应体 + +```json +{ + "status": "ok", + "serverTime": "2026-05-16 15:30:00" +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| status | string | 固定 "ok" | +| serverTime | string | Vol.Pro 当前时间,供网关校时 | + +#### 请求示例 + +```bash +curl -X POST http://localhost:9100/api/gateway/heartbeat \ + -H "Content-Type: application/json" \ + -d '{"nodeCode":"gw-31ku","token":"a1b2c3d4e5f6"}' +``` + +--- + +### 2.3 A3 — 设备数据同步 + +网关发现新设备或设备状态变更后,上送到 Vol.Pro。 + +- **Endpoint**: `POST /api/gateway/sync/devices` +- **认证**: NodeToken +- **字段分治**: 首次入库写全量,已有记录仅更新网关字段 + +#### 请求体 + +```json +{ + "nodeCode": "gw-31ku", + "token": "a1b2c3d4e5f6", + "devices": [ + { + "adapterCode": "MC4:31ku", + "sourceId": "1001", + "name": "动环采集器", + "category": "动环采集器", + "group": "IoT设备", + "isParent": true, + "parentSourceId": null, + "isOnline": true, + "ipAddress": "10.0.1.100", + "port": 3000, + "extraData": { + "mc4DeviceId": 1001 + } + }, + { + "adapterCode": "MC4:31ku", + "sourceId": "1001_0", + "name": "温湿度变送器", + "category": "温湿度变送器", + "group": "IoT设备", + "isParent": false, + "parentSourceId": "1001", + "isOnline": true, + "ipAddress": null, + "port": null, + "extraData": { + "mc4DeviceId": 1001, + "pointIndex": 0, + "unit": "℃" + } + } + ] +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| nodeCode | string | ✅ | 网关编码 | +| token | string | ✅ | 认证令牌 | +| devices | array | ✅ | 设备列表 | +| devices[].adapterCode | string | ✅ | 双段标识 | +| devices[].sourceId | string | ✅ | 第三方原始ID | +| devices[].name | string | ✅ | 设备名称(仅首次写入) | +| devices[].category | string | ✅ | 设备种类(仅首次写入) | +| devices[].group | string | ✅ | 设备分组(仅首次写入) | +| devices[].isParent | bool | ✅ | 是否父设备 | +| devices[].parentSourceId | string? | | 父设备第三方ID,Vol.Pro 解析为 ParentDeviceId | +| devices[].isOnline | bool | ✅ | 在线状态 | +| devices[].ipAddress | string? | | IP 地址 | +| devices[].port | int? | | 端口 | +| devices[].extraData | object | | 适配器扩展数据 | + +**字段分治规则**: +- **首次入库**(DeviceId=0): 所有字段写入 +- **已有记录**: 仅更新 isOnline、isParent、parentDeviceId(解析后)、extraData、ipAddress、port、lastSyncTime +- deviceName、category、group、pointId、location、lat/lng、mapModelId 仅在首次写入 + +#### 响应体 + +```json +{ + "added": 2, + "updated": 0, + "removed": 0 +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| added | int | 新增设备数 | +| updated | int | 更新设备数 | +| removed | int | 删除设备数(FullReplace 模式下可能 >0) | + +#### 请求示例 + +```bash +curl -X POST http://localhost:9100/api/gateway/sync/devices \ + -H "Content-Type: application/json" \ + -d '{"nodeCode":"gw-31ku","token":"a1b2c3d4e5f6","devices":[...]}' +``` + +--- + +### 2.4 A4 — 告警数据同步 + +网关发现新告警后上送。 + +- **Endpoint**: `POST /api/gateway/sync/alarms` +- **认证**: NodeToken + +#### 请求体 + +```json +{ + "nodeCode": "gw-31ku", + "token": "a1b2c3d4e5f6", + "alarms": [ + { + "sourceAlarmId": "2183fda3-9e32-48ae-b433-f807cc81a237", + "deviceSourceId": "1001_0", + "adapterCode": "MC4:31ku", + "level": "重要", + "desc": "温度超限: [温湿度变送器][45℃]", + "value": 45.0, + "startTime": "2026-05-16 14:30:00" + } + ] +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| nodeCode / token | string | ✅ | 认证信息 | +| alarms | array | ✅ | 告警列表 | +| alarms[].sourceAlarmId | string | ✅ | 源系统告警ID(用于去重) | +| alarms[].deviceSourceId | string | ✅ | 告警所属设备的第三方ID | +| alarms[].adapterCode | string | ✅ | 双段标识 | +| alarms[].level | string | ✅ | 告警等级(字典: 提示/普通/重要/紧急) | +| alarms[].desc | string | ✅ | 告警描述 | +| alarms[].value | double | | 触发值 | +| alarms[].startTime | string | ✅ | 告警开始时间 "yyyy-MM-dd HH:mm:ss" | + +#### 响应体 + +```json +{ + "added": 1 +} +``` + +--- + +## 3. B 组接口:Vol.Pro / 管理端 → 网关 + +> 调用方: Vol.Pro 后端 / 管理端 / warehouse 端 +> 接收方: 网关 +> 端口: 5100 +> 认证: 内网直连(无认证) + +--- + +### 3.1 B1 — 健康检查 + +- **Endpoint**: `GET /api/gateway/health` + +#### 响应体 + +```json +{ + "gateway": "ok", + "adapters": { + "MC4:31ku": true, + "Owl:main": true + } +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| gateway | string | 固定 "ok" | +| adapters | object | key=AdapterCode, value=true(在线)/false(离线) | + +#### 请求示例 + +```bash +curl http://localhost:5100/api/gateway/health +``` + +--- + +### 3.2 B2 — 设备列表 + +获取指定适配器下的设备列表(实时查询第三方)。 + +- **Endpoint**: `GET /api/gateway/devices` +- **适配器**: IHasFlatDevices + +#### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| adapter | string | ✅ | AdapterCode,例如 "Owl:main" | +| page | int | | 页码,默认 1 | +| size | int | | 每页大小,默认 50 | +| keyword | string | | 名称/ID 模糊搜索 | + +#### 响应体 + +```json +{ + "items": [ + { + "sourceId": "gb_34020000001320000001", + "adapterCode": "Owl:main", + "name": "NVR-01", + "category": "硬盘录像机", + "group": "视频设备", + "isOnline": true, + "isParent": true, + "ipAddress": "192.168.1.100", + "port": 5060, + "channelCount": 4, + "extraData": { + "owlDeviceId": "gb_34020000001320000001", + "protocol": "GB28181", + "transport": "UDP" + } + } + ], + "total": 50 +} +``` + +--- + +### 3.3 B3 — 手动触发同步 + +管理端手动触发全量设备同步。 + +- **Endpoint**: `POST /api/gateway/devices/sync` +- **适配器**: 所有实现了 IHasFlatDevices 或 IHasOwnDeviceTree 的适配器 + +#### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| adapter | string | ✅ | AdapterCode | + +#### 响应体 + +```json +{ + "adapterCode": "Owl:main", + "added": 5, + "updated": 3, + "removed": 1, + "errors": [], + "startTime": "2026-05-16T15:30:00", + "endTime": "2026-05-16T15:30:05" +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| adapterCode | string | 适配器编码 | +| added | int | 新增数 | +| updated | int | 更新数 | +| removed | int | 删除数 | +| errors | array | 错误信息列表 | +| startTime / endTime | string | 同步起止时间 | + +--- + +### 3.4 B4 — 实时点位值 + +获取设备所有点位的实时值。 + +- **Endpoint**: `GET /api/gateway/realtime/{adapter}/{deviceSourceId}` +- **适配器**: IHasPoints (MC4.0) + +#### 路径参数 + +| 参数 | 说明 | +|------|------| +| adapter | AdapterCode,例如 "MC4:31ku" | +| deviceSourceId | 设备在第三方系统中的 ID | + +#### 响应体 + +```json +{ + "deviceSourceId": "1001", + "points": [ + { + "pointIndex": 0, + "name": "温度", + "value": 26.5, + "unit": "℃", + "updateTime": "2026-05-16 15:30:00", + "isValid": true + }, + { + "pointIndex": 1, + "name": "湿度", + "value": 55.0, + "unit": "%", + "updateTime": "2026-05-16 15:30:00", + "isValid": true + } + ] +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| deviceSourceId | string | 设备ID | +| points[].pointIndex | int | 点位索引 | +| points[].name | string | 点位名称 | +| points[].value | double | 当前值 | +| points[].unit | string | 单位 | +| points[].updateTime | string | 数据更新时间 | +| points[].isValid | bool | 数据是否有效(false=传感器异常) | + +--- + +### 3.5 B5 — 设备控制 + +反向控制设备(调空调温度、开关阀门等)。 + +- **Endpoint**: `POST /api/gateway/realtime/{adapter}/control` +- **适配器**: IHasPoints (MC4.0) + +#### 路径参数 + 请求体 + +```json +// POST /api/gateway/realtime/MC4:31ku/control +{ + "deviceSourceId": "1001", + "pointIndex": 2, + "value": 1 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| deviceSourceId | string | ✅ | 第三方设备ID | +| pointIndex | int | ✅ | 点位索引 | +| value | double | ✅ | 设置值(开关: 0/1, 模拟量: 实际数值) | + +#### 响应体 + +```json +{ + "status": "sent" +} +``` + +> 注意: 响应仅表示指令已发送,不保证设备已执行。如需确认,应再次调 B4 查询实时值。 + +--- + +### 3.6 B6a — 实时取流 + +获取实时播放流地址。 + +- **Endpoint**: `GET /api/gateway/streams/{adapter}/{channelId}/live` +- **适配器**: IHasStreams (Owl) + +#### 响应体 + +```json +{ + "wsFlv": "ws://192.168.1.108/proxy/sms/rtp/gb_xxx.live.flv", + "httpFlv": "http://192.168.1.108/proxy/sms/rtp/gb_xxx.live.flv", + "hls": "http://192.168.1.108/proxy/sms/rtp/gb_xxx/hls.fmp4.m3u8", + "webrtc": "webrtc://192.168.1.108/proxy/sms/index/api/webrtc?app=rtp&stream=gb_xxx&type=play", + "rtmp": "rtmp://192.168.1.108:1935/rtp/gb_xxx", + "rtsp": "rtsp://192.168.1.108:554/rtp/gb_xxx" +} +``` + +| 协议 | 建议用途 | 延迟 | +|------|----------|:---:| +| wsFlv | Web 实时预览(首选) | <1s | +| httpFlv | 兼容旧浏览器 | 1-2s | +| hls | iOS Safari / 回放 | 3-5s | +| webrtc | 超低延迟场景 | <500ms | + +> 注意: GB28181 首次拉流有 1-3 秒 SIP 信令延迟。建议前端播放器在 3 秒内无画面时自动重试一次。 + +--- + +### 3.7 B6b — 回放取流 + +获取历史录像 HLS 播放地址。 + +- **Endpoint**: `GET /api/gateway/streams/{adapter}/{channelId}/playback` +- **适配器**: IHasStreams (Owl) + +#### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| start | string | ✅ | 开始时间 "yyyy-MM-dd HH:mm:ss" | +| end | string | ✅ | 结束时间 "yyyy-MM-dd HH:mm:ss" | + +#### 响应体 + +```json +{ + "hls": "http://192.168.1.108/recordings/channels/gb_xxx/index.m3u8?start_ms=1714982400000&end_ms=1714982700000&token=xxx" +} +``` + +> 回放使用 HLS (VOD) 格式,Owl 将指定时间范围内的 MP4 片段动态拼接为 m3u8 播放列表。 + +--- + +### 3.8 B7 — 云台控制 + +控制摄像机云台转动。 + +- **Endpoint**: `POST /api/gateway/streams/{adapter}/{channelId}/ptz` +- **适配器**: IHasStreams (Owl) + +#### 请求体 + +```json +{ + "direction": "left", + "speed": 0.5 +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| direction | string | ✅ | **仅支持**: `up` / `down` / `left` / `right` / `zoom_in` / `zoom_out` / `stop` | +| speed | float | | 速度 0.0~1.0,默认 0.5 | + +> ⚠️ Owl 当前版本仅实现了方向移动 (`continuous`) 和停止 (`stop`),**不支持**预设位操作 (`preset/set/goto/remove`) 和绝对/相对定位。ONVIF PTZ 未实现。 + +#### 响应体 + +```json +{ + "status": "ok" +} +``` + +--- + +### 3.9 B8 — 告警查询 + +查询告警列表。 + +- **Endpoint**: `GET /api/gateway/alarms/{adapter}` +- **适配器**: IHasAlarms + +#### 请求参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|:---:|------| +| from | string | ✅ | 开始时间 "yyyy-MM-dd HH:mm:ss" | +| to | string | ✅ | 结束时间 | +| page | int | | 页码,默认 1 | +| size | int | | 每页大小,默认 50 | +| confirmState | int | | MC4.0: 0=所有, 1=未确认, 2=已确认 | +| level | string | | 告警等级: 提示/普通/重要/紧急 | + +#### 响应体 + +```json +{ + "items": [ + { + "alarmId": "2183fda3-9e32-48ae-b433-f807cc81a237", + "deviceId": "1001", + "adapterCode": "MC4:31ku", + "level": "重要", + "title": "温度超限", + "content": "[温湿度变送器][45℃]", + "occurTime": "2026-05-16 14:30:00", + "status": "未确认", + "thresholdValue": 40.0, + "actualValue": 45.0 + } + ], + "total": 120 +} +``` + +--- + +### 3.10 B9 — 告警确认 + +确认告警,写回第三方系统。 + +- **Endpoint**: `POST /api/gateway/alarms/{adapter}/{alarmId}/confirm` +- **适配器**: IHasAlarms + +#### 路径参数 + +| 参数 | 说明 | +|------|------| +| adapter | AdapterCode | +| alarmId | 源系统告警 ID | + +#### 响应体 + +```json +{ + "status": "confirmed" +} +``` + +> Vol.Pro 在收到成功响应后,同步更新本地 `iot_alarm.State='已确认'` 和 `ConfirmTime=当前时间`。 + +--- + +## 4. 错误码对照表 + +| HTTP Status | 含义 | 说明 | +|:----------:|------|------| +| 200 | 成功 | 正常响应 | +| 400 | 请求错误 | 参数缺失或格式错误 | +| 401 | 认证失败 | A 组接口 NodeCode 或 Token 不正确 | +| 404 | 未找到 | 适配器不存在或设备不存在 | +| 500 | 服务器错误 | 网关或 Vol.Pro 内部异常 | +| 502 | 第三方错误 | 网关调用 Owl/MC4.0 失败 | + +--- + +## 5. 数据类型约定 + +| 类型 | JSON 示例 | 说明 | +|------|-----------|------| +| string | "hello" | 字符串 | +| int | 42 | 整数 | +| double | 26.5 | 浮点数 | +| bool | true / false | 布尔值 | +| object | { "key": "value" } | JSON 对象 | +| array | [ ... ] | JSON 数组 | +| datetime | "2026-05-16 15:30:00" | 日期时间字符串,格式 yyyy-MM-dd HH:mm:ss | + +--- + +## 6. 对接检查清单 + +网关开发和 Vol.Pro 开发完成后,按以下清单逐项验证: + +``` +□ A1: 网关启动 → 注册成功 → 返回 nodeId + 设备列表 +□ A2: 网关心跳 → Vol.Pro gateway_nodes.LastHeartbeat 更新 +□ A3: 首次同步 → 设备入库,字段分治规则正确(管理员字段不覆盖) +□ A3: 二次同步 → 仅网关字段更新,DeviceName 不变 +□ A3: parentSourceId → Vol.Pro 正确解析为 ParentDeviceId +□ A4: 告警上报 → iot_alarm 表有数据 +□ B1: 健康检查 → 返回所有适配器状态 +□ B2: 设备列表 → 分页 + 关键字搜索正常 +□ B3: 手动同步 → 返回 added/updated/removed 统计 +□ B4: 实时数据 → 返回点位值和更新时间 +□ B5: 设备控制 → 指令发送成功,设备实际响应 +□ B6a: 实时取流 → 返回 6 种协议地址,前端可播放 +□ B6b: 回放取流 → 返回 HLS 地址,前端可播放历史录像 +□ B7: 云台控制 → 方向键有效,stop 有效 +□ B8: 告警查询 → 分页 + 筛选正常 +□ B9: 告警确认 → 第三方确认成功 + Vol.Pro 本地 State 更新 +``` + +--- + +> **文档结束**