恢复整合方案v3.1文档
This commit is contained in:
531
doc/整合方案/SecMPS_最终整合方案_v3.0.md
Normal file
531
doc/整合方案/SecMPS_最终整合方案_v3.0.md
Normal file
@@ -0,0 +1,531 @@
|
||||
# SecMPS 整合方案(最终版):IntegrationGateway + 统一设备管理
|
||||
|
||||
> **版本**: v3.0
|
||||
> **日期**: 2026-05-16
|
||||
> **状态**: 待实施
|
||||
> **基准**: 基于 v2.0 + Owl/ZLMediaKit 双文档验证 + 14 项修正
|
||||
|
||||
---
|
||||
|
||||
## 一、总体架构
|
||||
|
||||
```
|
||||
前端层
|
||||
web.vite 管理端(设备管理+网关管理) warehouse 大屏(Map/Live/IoT/Alarm)
|
||||
| HTTP REST | HTTP REST + SignalR
|
||||
v v
|
||||
Vol.Pro 后端 (api_sqlsugar)
|
||||
DeviceManagerController / GatewayNodeController / SignalR Hubs
|
||||
Quartz: SyncDevicesJob / RealtimePollJob / AlarmPollJob
|
||||
数据库: 6 张表 (base_device / video_channel / video_record / iot_devicedata / iot_alarm / gateway_nodes)
|
||||
| 注册/下发设备/心跳/同步数据
|
||||
v
|
||||
IntegrationGateway 实例A (:5100) IntegrationGateway 实例B (:5101)
|
||||
NodeCode: gw-31ku NodeCode: gw-11ku
|
||||
Adapters: MC4 / Owl Adapters: MC4 / HikvisionISC
|
||||
| HTTP | HTTP
|
||||
v v
|
||||
MC4.0 (:3000) Owl (:15123) MC4.0 (:3000) 海康ISC (:80)
|
||||
|
||||
注: Owl 管理端口为 15123,ZLMediaKit 由 Owl 内部管理(:8000),网关不直接接触
|
||||
```
|
||||
|
||||
### 核心设计原则
|
||||
|
||||
- **网关无状态**:配置仅 NodeCode/Token/VolProUrl,挂了重装即恢复
|
||||
- **AdapterCode 双段标识**:`"MC4:31ku"` 区分同类型多实例,格式 `{AdapterType}:{InstanceName}`,InstanceName 仅字母数字下划线
|
||||
- **DeviceGroup 路由**:基类表用字典字段决定适配器和行为,不依赖扩展表
|
||||
- **ExtraData JSON**:所有适配器特有字段存入 ExtraData,新增适配器不增表
|
||||
- **心跳机制**:网关 15s 心跳,Vol.Pro 超 30s 级联设备离线
|
||||
- **字段分治**:网关字段(ExtraData/IsOnline/IsParent/ParentDeviceId)同步覆盖,管理员字段(DeviceName/Category/Location/MapModelId)首次写入后不再覆盖
|
||||
|
||||
---
|
||||
|
||||
## 二、网关架构(方案 C+)
|
||||
|
||||
### 2.1 网关注册与心跳流程
|
||||
|
||||
```
|
||||
管理端: gateway_nodes 表新增 → 生成 NodeCode + Token
|
||||
网关配置: { NodeCode, Token, VolProUrl }
|
||||
网关启动 → POST /register { nodeCode,token,adapterTypes,baseUrl }
|
||||
Vol.Pro 校验 Token:
|
||||
NodeCode 匹配 → Upsert: 更新 AdapterTypes/BaseUrl/IsOnline=在线 → 返回已有 NodeId
|
||||
NodeCode 不匹配且 Token 验证通过 → 插入新记录 → 返回新 NodeId
|
||||
验证失败 → 401
|
||||
响应: { gatewayNodeId, devices: [base_device WHERE GatewayNodeId=当前] }
|
||||
网关按 AdapterCode 分流 → Adapter 连接第三方 → 发现子设备
|
||||
网关 → POST /sync/devices → Vol.Pro 写入/更新 base_device(首次写全量,后续仅更新网关字段)
|
||||
网关每 15s → POST /heartbeat { nodeCode, token }
|
||||
Vol.Pro Job: IsOnline=在线 且 LastHeartbeat < now-30s → IsOnline=离线 → 级联: base_device.IsOnline=离线 WHERE GatewayNodeId=该节点
|
||||
```
|
||||
|
||||
### 2.2 网关配置
|
||||
|
||||
```json
|
||||
{
|
||||
"VolProBaseUrl": "http://localhost:9100",
|
||||
"NodeCode": "gw-31ku",
|
||||
"NodeToken": "xxxxxxxxxx"
|
||||
}
|
||||
```
|
||||
|
||||
AdapterCode 格式规范:`{AdapterType}:{InstanceName}`,例如 `"MC4:31ku"`、`"Owl:main"`。
|
||||
AdapterType = 网关注册的 Adapter 类名(字母数字),InstanceName = 网关实例名(字母数字下划线),分隔符 `:`。
|
||||
|
||||
### 2.3 适配器能力矩阵
|
||||
|
||||
| 接口 | Owl | MC4.0 | 门禁(未来) |
|
||||
|------|:---:|:-----:|:----------:|
|
||||
| IHasOwnDeviceTree | ❌ | ✅ | ❌ |
|
||||
| IHasFlatDevices | ✅ | ❌ | ✅ |
|
||||
| IHasPoints | ❌ | ✅ | ❌ |
|
||||
| IHasStreams | ✅ | ❌ | ❌ |
|
||||
| IHasAlarms | ⚠️(AI事件可选) | ✅ | ✅ |
|
||||
| IAcceptsMetadataPush | ✅ | ❌ | ⚠️ |
|
||||
|
||||
> Owl PTZ 限制:仅支持 continuous(方向移动) + stop(停止),不支持预设位/绝对定位/相对定位。ONVIF PTZ 未实现。
|
||||
|
||||
### 2.4 双向同步引擎
|
||||
|
||||
| 方向 | 说明 | MC4.0 | Owl |
|
||||
|------|------|-------|-----|
|
||||
| PullToVolPro | 第三方→Vol.Pro | FullReplace | Merge |
|
||||
| PushToSource | Vol.Pro→第三方 | 告警确认/控制 | 元数据/PTZ |
|
||||
| Bidirectional | 先写第三方再更新本地 | 告警确认 | — |
|
||||
|
||||
### 2.5 对接 API 规范
|
||||
|
||||
网关与 Vol.Pro 之间有两组接口,调用方向不同。
|
||||
|
||||
#### A. 网关 → Vol.Pro(网关主动调用)
|
||||
|
||||
| # | 接口 | 说明 |
|
||||
|---|------|------|
|
||||
| A1 | `POST /api/gateway/register` | 网关启动注册(Upsert逻辑),获取所管设备列表 |
|
||||
| A2 | `POST /api/gateway/heartbeat` | 心跳(每 15s) |
|
||||
| A3 | `POST /api/gateway/sync/devices` | 上送设备数据(新增/状态变更),仅更新网关字段 |
|
||||
| A4 | `POST /api/gateway/sync/alarms` | 上送告警数据 |
|
||||
|
||||
**A1 注册** — 认证: NodeToken, 逻辑: Upsert
|
||||
|
||||
```
|
||||
Request: { nodeCode, token, adapterTypes, baseUrl }
|
||||
Response: { nodeId, devices: [ 当前网关的顶层设备 ] }
|
||||
Error: 401 认证失败(Token 错误或 NodeCode 不存在且 Token 无效)
|
||||
```
|
||||
|
||||
**A2 心跳** — 认证: NodeToken
|
||||
|
||||
```
|
||||
Request: { nodeCode, token }
|
||||
Response: { status: "ok" }
|
||||
```
|
||||
|
||||
**A3 设备同步** — 认证: NodeToken
|
||||
|
||||
```
|
||||
Request: { nodeCode, token, devices: [{ adapterCode, sourceId, name, category, group,
|
||||
isParent, parentSourceId, isOnline, ipAddress, port, extraData }] }
|
||||
Response: { added, updated, removed }
|
||||
```
|
||||
|
||||
> 字段分治规则:首次入库(DeviceId==0)写全量;已有记录仅更新 IsOnline、IsParent、ParentDeviceId、ExtraData、LastSyncTime、IpAddress、Port。DeviceName/DeviceCategory/DeviceGroup/Location/MapModelId 仅在首次入库时写入。
|
||||
> parentSourceId 解析:同步前按 (AdapterCode, SourceId) 批量查询已有 DeviceId 映射表,将 parentSourceId 转为 ParentDeviceId。
|
||||
|
||||
**A4 告警同步** — 认证: NodeToken
|
||||
|
||||
```
|
||||
Request: { nodeCode, token, alarms: [{ sourceAlarmId, deviceSourceId, adapterCode,
|
||||
level, desc, value, startTime }] }
|
||||
Response: { added }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### B. Vol.Pro / 管理端 → 网关(查询与控制)
|
||||
|
||||
| # | 接口 | 说明 |
|
||||
|---|------|------|
|
||||
| B1 | `GET /api/gateway/health` | 网关及所有适配器状态 |
|
||||
| B2 | `GET /api/gateway/devices?adapter=&page=&size=` | 设备列表 |
|
||||
| B3 | `POST /api/gateway/devices/sync?adapter=` | 手动触发全量同步 |
|
||||
| B4 | `GET /api/gateway/realtime/{adapter}/{deviceId}` | 实时点位值 |
|
||||
| B5 | `POST /api/gateway/realtime/{adapter}/control` | 反向控制 |
|
||||
| B6a | `GET /api/gateway/streams/{adapter}/{id}/live` | 实时取流 |
|
||||
| B6b | `GET /api/gateway/streams/{adapter}/{id}/playback?start=&end=` | 回放取流(HLS VOD) |
|
||||
| B7 | `POST /api/gateway/streams/{adapter}/{id}/ptz` | 云台控制(仅方向移动+停止) |
|
||||
| B8 | `GET /api/gateway/alarms/{adapter}?from=&to=&page=&size=` | 告警查询 |
|
||||
| B9 | `POST /api/gateway/alarms/{adapter}/{alarmId}/confirm` | 告警确认(写回第三方+更新本地State) |
|
||||
|
||||
> B 组接口由管理端或 Vol.Pro 后端直接调用网关,认证方式为内网直连或网关侧 IP 白名单。
|
||||
> B6a 实时取流 → Owl `POST /channels/:id/play`;B6b 回放取流 → Owl `GET /recordings/channels/:cid/index.m3u8?start_ms=&end_ms=`
|
||||
> B7 仅支持 `continuous`(方向移动: up/down/left/right/zoom_in/zoom_out) + `stop`,不支持预设位
|
||||
> B9 确认第三方成功后,同步更新本地 iot_alarm.State='已确认'
|
||||
|
||||
---
|
||||
|
||||
## 三、数据模型(6 张表)
|
||||
|
||||
### 3.1 区域表 warehouse_regions(现有)
|
||||
|
||||
层级: warehouse_regions(区域) → warehouse_devicepoint(点位) → base_device(设备)
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| Id | int PK |
|
||||
| RegionName | nvarchar(255) |
|
||||
| ParentId | int? (自引用树) |
|
||||
|
||||
### 3.2 网关节点表 gateway_nodes
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| NodeId | INT AUTO_INCREMENT | 网关节点ID |
|
||||
| NodeCode | NVARCHAR(50) | 网关唯一编码 |
|
||||
| NodeName | NVARCHAR(100) | 网关名称 |
|
||||
| NodeToken | NVARCHAR(100) | 认证令牌 |
|
||||
| AdapterTypes | NVARCHAR(200) | 适配器类型(网关上报) |
|
||||
| BaseUrl | NVARCHAR(200) | 网关地址(网关上报) |
|
||||
| LastHeartbeat | DATETIME | 上次心跳时间 |
|
||||
| IsOnline | NVARCHAR(20) | 在线状态(字典: 在线/离线) |
|
||||
| Enable | NVARCHAR(20) | 启用状态(字典: 启用/禁用) |
|
||||
|
||||
### 3.3 统一设备主表 base_device
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| DeviceId | INT AUTO_INCREMENT | Vol.Pro内部ID |
|
||||
| DeviceName | NVARCHAR(100) | 设备名称(管理员字段) |
|
||||
| AdapterCode | NVARCHAR(50) | "MC4:31ku"(类型:实例) |
|
||||
| SourceId | NVARCHAR(100) | 源系统设备ID |
|
||||
| DeviceCategory | NVARCHAR(50) | 设备种类(字典) |
|
||||
| DeviceGroup | NVARCHAR(20) | 设备分组(字典) |
|
||||
| PointId | INT? | 所属点位ID |
|
||||
| GatewayNodeId | INT? | 所属网关节点ID |
|
||||
| IsParent | NVARCHAR(20) | 是否父设备(字典: 是/否) |
|
||||
| ParentDeviceId | INT? | 父设备自引用 |
|
||||
| IsOnline | NVARCHAR(20) | 在线状态(网关字段) |
|
||||
| MapModelId | NVARCHAR(100) | VgoMap模型ID(管理员字段) |
|
||||
| MapModelScale | FLOAT | |
|
||||
| MapModelRotation | NVARCHAR(100) | |
|
||||
| ExtraData | TEXT | ★ 适配器扩展JSON(网关字段) |
|
||||
| LastSyncTime | DATETIME | 上次同步时间 |
|
||||
| Enable | NVARCHAR(20) | 启用状态(字典: 启用/禁用) |
|
||||
|
||||
唯一约束: (AdapterCode, SourceId)
|
||||
|
||||
> 网关字段(同步覆盖):ExtraData/IsOnline/IsParent/ParentDeviceId/IpAddress/Port/LastSyncTime
|
||||
> 管理员字段(首次写入后不覆盖):DeviceName/DeviceCategory/DeviceGroup/PointId/Location/Lat/Lng/MapModelId/MapModelScale/MapModelRotation
|
||||
|
||||
### 3.4 DeviceGroup 分组规则
|
||||
|
||||
| DeviceGroup | 网关适配器 | 前端按钮组 | 同步模式 |
|
||||
|:---:|------|------|:---:|
|
||||
| 视频设备 | OwlAdapter → IHasStreams | 实时预览/云台/回放/快照 | Merge |
|
||||
| IoT设备 | Mc4Adapter → IHasPoints | 实时数据/控制/告警 | FullReplace |
|
||||
| 门禁设备 | AccessAdapter | 远程开门/记录/告警 | Merge |
|
||||
| 道闸设备 | BarrierAdapter | 抬杆/落杆/记录 | Merge |
|
||||
| 报警设备 | AlarmAdapter | 查看告警/布防撤防 | Merge |
|
||||
|
||||
### 3.5 ExtraData 格式示例
|
||||
|
||||
```json
|
||||
// 摄像机 (Owl)
|
||||
{ "owlDeviceId": "gb_xxx", "protocol": "GB28181", "manufacturer": "海康" }
|
||||
|
||||
// 温湿度变送器 (MC4子设备)
|
||||
{ "mc4DeviceId": 1001, "pointIndex": 0, "unit": "℃", "isControlPoint": false }
|
||||
|
||||
// 空调控制器 (MC4子设备)
|
||||
{ "mc4DeviceId": 1002, "pointIndex": 2, "unit": null, "isControlPoint": true }
|
||||
```
|
||||
|
||||
### 3.6 层级示例
|
||||
|
||||
```
|
||||
gateway_nodes: gw-31ku
|
||||
|
||||
warehouse_regions → warehouse_devicepoint → base_device
|
||||
|
||||
例: 厂区 → 新库区 → 31号库房(点位) → 设备
|
||||
|
||||
base_device (PointId=点位ID, GatewayNodeId=gw-31ku.NodeId):
|
||||
NVR-01 (DeviceCategory=硬盘录像机, DeviceGroup=视频设备, IsParent=是)
|
||||
├── 通道01 (ParentDeviceId=NVR, video_channel.DeviceId=通道01.DeviceId, OwlStreamApp="rtp")
|
||||
├── 通道02 (ParentDeviceId=NVR, video_channel.DeviceId=通道02.DeviceId, OwlStreamApp="rtp")
|
||||
东北角高位摄像机 (DeviceCategory=摄像机, DeviceGroup=视频设备)
|
||||
动环采集器 (DeviceCategory=动环采集器, DeviceGroup=IoT设备, IsParent=是)
|
||||
├── 温湿度变送器 (ParentDeviceId=采集器, ExtraData={pointIndex:0,unit:"℃"})
|
||||
├── 空调控制器 (ParentDeviceId=采集器, ExtraData={pointIndex:2,isControlPoint:true})
|
||||
└── 紧急报警按钮 (DeviceGroup=报警设备, ParentDeviceId=采集器)
|
||||
|
||||
video_channel 表(通道Owl流信息):
|
||||
{ ChannelId=1, DeviceId=通道01.DeviceId(→base_device), OwlStreamApp="rtp", HasPtz=1 }
|
||||
{ ChannelId=2, DeviceId=通道02.DeviceId(→base_device), OwlStreamApp="rtp", HasPtz=0 }
|
||||
|
||||
> 通道 = base_device 子记录(名称/在线/层级) + video_channel 扩展记录(流地址/云台能力/录像模式)
|
||||
> video_channel 的 DeviceId 指向通道自身的 base_device.DeviceId(不是 NVR 的 DeviceId)
|
||||
> video_channel 的 OwlStreamApp/OwlStreamName/SnapshotUrl 为缓存,首次取流后写入,后续优先读缓存
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、Vol.Pro 同步接口(新增适配器零改动)
|
||||
|
||||
```csharp
|
||||
// POST /api/gateway/sync/devices
|
||||
public async Task SyncDevices(string nodeCode, List<StandardDevice> devices)
|
||||
{
|
||||
var node = await _db.gateway_nodes.FirstAsync(n => n.NodeCode == nodeCode);
|
||||
|
||||
// ★ 批量查询已有设备映射表 (用于 parentSourceId 解析)
|
||||
var existingIds = await _db.base_device
|
||||
.Where(x => x.GatewayNodeId == node.NodeId)
|
||||
.ToDictionaryAsync(x => (x.AdapterCode, x.SourceId), x => x.DeviceId);
|
||||
|
||||
foreach (var d in devices)
|
||||
{
|
||||
var key = (d.AdapterCode, d.SourceId);
|
||||
existingIds.TryGetValue(key, out var existingId);
|
||||
var entity = existingId > 0
|
||||
? await _db.base_device.FindAsync(existingId)
|
||||
: new base_device { AdapterCode = d.AdapterCode, SourceId = d.SourceId };
|
||||
|
||||
bool isNew = entity.DeviceId == 0;
|
||||
|
||||
// ★ 解析 parentSourceId → ParentDeviceId
|
||||
int? parentDeviceId = null;
|
||||
if (!string.IsNullOrEmpty(d.ParentSourceId))
|
||||
{
|
||||
existingIds.TryGetValue((d.AdapterCode, d.ParentSourceId), out var pid);
|
||||
if (pid > 0) parentDeviceId = pid;
|
||||
}
|
||||
|
||||
// 仅首次入库写管理员字段
|
||||
if (isNew)
|
||||
{
|
||||
entity.DeviceName = d.Name;
|
||||
entity.DeviceCategory = d.Category;
|
||||
entity.DeviceGroup = d.Group;
|
||||
}
|
||||
|
||||
// 每次同步写网关字段
|
||||
entity.IsOnline = d.IsOnline ? "在线" : "离线";
|
||||
entity.IsParent = d.IsParent ? "是" : "否";
|
||||
entity.ParentDeviceId = parentDeviceId;
|
||||
entity.ExtraData = d.ExtraDataJson;
|
||||
entity.GatewayNodeId = node.NodeId;
|
||||
entity.IpAddress = d.IpAddress;
|
||||
entity.Port = d.Port;
|
||||
entity.LastSyncTime = DateTime.UtcNow;
|
||||
|
||||
if (isNew) _db.base_device.Add(entity);
|
||||
else _db.base_device.Update(entity);
|
||||
}
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、管理端设备操作集成
|
||||
|
||||
> **设计决策**: 不再需要独立的设备管理页面。Vol.Pro 框架自带三级主从表显示能力(warehouse_regions → warehouse_devicepoint → base_device),可直接在框架生成的 base_device 列表页面中嵌入操作按钮,按 DeviceGroup 动态渲染。
|
||||
|
||||
### 5.1 操作按钮矩阵
|
||||
|
||||
| DeviceGroup | 操作按钮 | 说明 |
|
||||
|:---:|------|------|
|
||||
| 视频设备 | 实时预览 / 云台控制(仅方向键) / 查看回放 / 获取快照 / 同步通道 | 全部通过网关 B 组接口代理到 Owl |
|
||||
| IoT设备 | 查看实时数据 / 设备控制 / 刷新点位 / 查看告警 | 通过网关 B4/B5 代理到 MC4.0 |
|
||||
| 门禁设备 | 远程开门 / 查看记录 / 查看告警 | Phase 3 接入海康ISC后启用 |
|
||||
| 道闸设备 | 抬杆 / 落杆 / 查看记录 | Phase 3 接入 |
|
||||
| 报警设备 | 查看告警 / 布防撤防 | Phase 3 接入 |
|
||||
|
||||
### 5.2 前端按钮嵌入方案
|
||||
|
||||
框架生成的 base_device 列表页面的"操作"列默认只有"编辑/删除"。在 **base_deviceController Partial** 中扩展前端分组逻辑,替换默认操作列为自定义渲染。
|
||||
|
||||
```javascript
|
||||
// web.vite/src/extension/warehouse/base_device.jsx 或 views/warehouse/base_device/components/ActionColumn.vue
|
||||
const actionMap = {
|
||||
'视频设备': VideoDeviceActions, // 实时预览/云台/回放/快照/同步通道
|
||||
'IoT设备': IoTDeviceActions, // 实时数据/控制/刷新/告警
|
||||
'门禁设备': AccessDeviceActions, // 远程开门/记录/告警
|
||||
'道闸设备': BarrierDeviceActions,// 抬杆/落杆/记录
|
||||
'报警设备': AlarmDeviceActions, // 告警/布防撤防
|
||||
}
|
||||
|
||||
// 操作列模板中根据 row.deviceGroup 动态渲染对应组件
|
||||
<template v-for="(row, idx) in data">
|
||||
<component :is="actionMap[row.deviceGroup] || DefaultActions" :row="row" />
|
||||
</template>
|
||||
```
|
||||
|
||||
**要点**:
|
||||
- 框架"操作"列通过自定义插槽替换,不修改框架生成的 Vue 文件本体
|
||||
- 组件放在 `views/warehouse/base_device/components/` 下,防代码生成覆盖
|
||||
- 五个分组组件各自独立(~80-150 行),新增分组仅加一个文件
|
||||
|
||||
### 5.3 前端操作组件清单
|
||||
|
||||
| 文件 | 大小 | 说明 |
|
||||
|------|:---:|------|
|
||||
| `VideoDeviceActions.vue` | ~120行 | 预览/云台/回放/快照按钮组,预览弹窗内嵌 Jessibuca 播放器(或 <video> 标签回退),云台仅 ↑↓←→+ZOOM+停止 |
|
||||
| `IoTDeviceActions.vue` | ~100行 | 实时数据表格弹窗(轮询 B4),控制面板(B5 写值),告警快捷入口 |
|
||||
| `AccessDeviceActions.vue` | ~60行 | 远程开门按钮 + 记录查询入口 |
|
||||
| `BarrierDeviceActions.vue` | ~60行 | 抬杆/落杆按钮 |
|
||||
| `AlarmDeviceActions.vue` | ~60行 | 告警列表 + 布防/撤防开关 |
|
||||
|
||||
### 5.4 后端操作 API
|
||||
|
||||
> 以下 API 由网关 B 组接口代理,Vol.Pro 前端不直连子系统,统一经网关中转。
|
||||
|
||||
| 接口 | 方法 | 说明 | 对应网关接口 |
|
||||
|------|:---:|------|------|
|
||||
| `/api/gateway/streams/{adapter}/{sourceId}/live` | GET | 获取实时流地址 | B6a |
|
||||
| `/api/gateway/streams/{adapter}/{sourceId}/playback?start=&end=` | GET | 获取回放地址 | B6b |
|
||||
| `/api/gateway/streams/{adapter}/{sourceId}/snapshot` | POST | 获取截图 | — |
|
||||
| `/api/gateway/streams/{adapter}/{sourceId}/ptz` | POST | 云台方向控制 | B7 |
|
||||
| `/api/gateway/realtime/{adapter}/{sourceId}` | GET | 获取实时点位值 | B4 |
|
||||
| `/api/gateway/realtime/{adapter}/control` | POST | 设备控制写值 | B5 |
|
||||
| `/api/gateway/alarms/{adapter}` | GET | 分页查询告警 | B8 |
|
||||
| `/api/gateway/alarms/{adapter}/{alarmId}/confirm` | POST | 确认告警 | B9 |
|
||||
|
||||
> Vol.Pro 前端直接请求网关(:5100),不经过 Vol.Pro 后端中转。跨域问题通过网关 CORS 或 nginx 反向代理解决。
|
||||
|
||||
---
|
||||
|
||||
## 六、同步策略
|
||||
|
||||
### MC4.0 → 区域树+设备
|
||||
- type=1 节点 → 名称匹配 warehouse_regions → 绑区或新建
|
||||
- type=2 节点 → Upsert base_device (DeviceGroup=IoT设备, ExtraData 存点位属性)
|
||||
- 子设备在线状态由网关按 MC4.0 数据如实上报,Vol.Pro 不做推断
|
||||
- 模式: FullReplace, 频率限制: 2次/秒
|
||||
|
||||
### Owl → 设备
|
||||
- GET /devices → Upsert base_device (DeviceGroup=视频设备, IsParent=是)
|
||||
- GET /channels → Upsert base_device (ParentDeviceId=NVR) + video_channel 扩展记录
|
||||
- Owl 无区域概念 → PointId=NULL, 管理员手动分配
|
||||
- 可手动触发 `POST /devices/:id/catalog` 刷新通道目录
|
||||
- 模式: Merge
|
||||
|
||||
### 录像同步
|
||||
- 管理端点击"查看回放"时,网关实时调 Owl `GET /recordings` → 返回给前端 + 同步写入 video_record
|
||||
- Phase 3 可选:网关定时(每 10 分钟)后台同步录像记录
|
||||
|
||||
### Owl AI 事件(可选)
|
||||
- OwlAdapter 可选实现 IHasAlarms,将 Owl `GET /events` 的 YOLO AI 检测事件映射为 StandardAlarm,走 A4 告警同步
|
||||
|
||||
### 反方向写回
|
||||
|
||||
| 操作 | Owl | MC4.0 |
|
||||
|------|:---:|:-----:|
|
||||
| 设备改名 | ✅ PUT /devices/:id | ❌ |
|
||||
| 告警确认 | ⚠️ | ✅ |
|
||||
| 设备控制 | ✅ PTZ(仅方向键) | ✅ 点位写值 |
|
||||
|
||||
---
|
||||
|
||||
## 七、部署拓扑
|
||||
|
||||
```
|
||||
Docker: Owl+ZLM (:15123) MC4.0-1 (:3000) MC4.0-2 (:3000)
|
||||
| | |
|
||||
+----------+--------------+-------------------+
|
||||
|
|
||||
+----------+-----------+
|
||||
| Gateway gw-31ku | Gateway gw-11ku
|
||||
| :5100 | :5101
|
||||
+----------+-----------+
|
||||
|
|
||||
+----------+-----------+
|
||||
| VolPro.WebApi |
|
||||
| :9100 |
|
||||
| MySQL / Redis |
|
||||
+----------+-----------+
|
||||
|
|
||||
+--------------+---------------+
|
||||
| web.vite :9000 warehouse :9200 |
|
||||
+--------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、实施路线
|
||||
|
||||
| 阶段 | 工期 | 内容 |
|
||||
|------|------|------|
|
||||
| Phase 0 | Day 1-2 | Gateway骨架 + 6张表建表 + 代码生成 + 字典初始化 |
|
||||
| Phase 1 | Day 3-6 | OwlAdapter + base_device操作按钮组件(视频) + [可选]AI事件接入 |
|
||||
| Phase 2 | Day 7-11 | Mc4Adapter + IoT管理 + 区域树匹配 + SignalR |
|
||||
| Phase 3 | Day 12-17 | warehouse端改造 + 全链路联调 |
|
||||
| Phase 4 | Day 18-20 | 验证 + 缓冲 |
|
||||
|
||||
总计: 18-20 个工作日
|
||||
|
||||
---
|
||||
|
||||
## 九、新增整合流程
|
||||
|
||||
以接入「海康门禁」为例:
|
||||
1. 新建 IntegrationGateway.Adapters.HikvisionAccess 项目
|
||||
2. 实现 IHasFlatDevices + IHasAlarms → 设备同步时填充 DeviceGroup=门禁设备
|
||||
3. 管理端字典加一条"门禁设备"分组 → 按钮自动出现
|
||||
4. Vol.Pro 同步接口零改动(ExtraData 承载门禁字段)
|
||||
5. 前端新增 AccessDeviceActions.vue (~80行)
|
||||
总工作量: 1-2 天
|
||||
|
||||
---
|
||||
|
||||
## 十、代码组织规范
|
||||
|
||||
| 代码类型 | 路径 | 被覆盖? |
|
||||
|----------|------|:---:|
|
||||
| 第三方对接 | gateway/ | ❌ |
|
||||
| 扩展Controller | Controllers/*/Partial/ | ❌ |
|
||||
| Entity扩展 | DomainModels/*/partial/ | ❌ |
|
||||
| 前端业务逻辑 | extension/warehouse/*.jsx | ❌ |
|
||||
| 自定义页面 | views/warehouse/DeviceManager/ | ❌ |
|
||||
| 自动生成代码 | 生成器默认路径 | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 附录 A:字典初始化清单
|
||||
|
||||
Phase 0 建表后需在 Vol.Pro 管理端创建以下数据字典:
|
||||
|
||||
| 字典名称 | 字典值 |
|
||||
|----------|--------|
|
||||
| 设备种类 | 门磁/空调/智能断路器/人行道闸/车辆道闸/485钥匙柜/网络钥匙柜/紧急报警按钮/红外报警器/门禁一体机/除湿_恒湿机/空调控制器/烟雾报警器/气体报警器/温湿度变送器/摄像机/硬盘录像机/动环采集器 |
|
||||
| 设备分组 | 视频设备/IoT设备/门禁设备/道闸设备/报警设备 |
|
||||
| 是否父设备 | 是/否 |
|
||||
| 在线状态 | 在线/离线 |
|
||||
| 启用状态 | 启用/禁用 |
|
||||
| 是否控制点 | 只读/可写 |
|
||||
| 告警等级 | 提示/普通/重要/紧急 |
|
||||
| 告警状态 | 未确认/已确认/已结束 |
|
||||
|
||||
---
|
||||
|
||||
## 附录 B:AdapterCode 格式规范
|
||||
|
||||
```
|
||||
格式: {AdapterType}:{InstanceName}
|
||||
示例: "MC4:31ku"、"Owl:main"、"HikvisionISC:center"
|
||||
规则:
|
||||
- AdapterType: 网关注册的 Adapter 类名,仅字母数字
|
||||
- InstanceName: 网关实例名称,仅字母数字下划线
|
||||
- 分隔符: ':'
|
||||
- base_device.AdapterCode 存储完整双段标识
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **版本历史**:
|
||||
> - v1.0 (2026-04-29) — 初始 Owl+MC4 独立方案
|
||||
> - v2.0 (2026-05-16) — 整合 Gateway 架构 + 数据字典 + ExtraData JSON
|
||||
> - v3.0 (2026-05-16) — Owl/ZLMediaKit 双文档验证 + 14 项修正(P0/P1/P2 修复)
|
||||
> - v3.1 (2026-05-17) — 第五章修订:取消独立设备管理页面,改为框架主从表嵌入操作按钮
|
||||
Reference in New Issue
Block a user