# 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 更新 ``` --- > **文档结束**