From 906700e0fe67091fd07bd244f40f0384b4ce51a3 Mon Sep 17 00:00:00 2001 From: g82tt Date: Sat, 16 May 2026 10:45:20 +0800 Subject: [PATCH] v2.0_final_synced_with_db_and_gateway --- doc/整合方案/SecMPS_最终整合方案_v2.0.md | 307 ++++++++++++++--------- 1 file changed, 182 insertions(+), 125 deletions(-) diff --git a/doc/整合方案/SecMPS_最终整合方案_v2.0.md b/doc/整合方案/SecMPS_最终整合方案_v2.0.md index 7e1f47b..9214e6c 100644 --- a/doc/整合方案/SecMPS_最终整合方案_v2.0.md +++ b/doc/整合方案/SecMPS_最终整合方案_v2.0.md @@ -1,9 +1,9 @@ # SecMPS 整合方案(最终版):IntegrationGateway + 统一设备管理 > **版本**: v2.0 -> **日期**: 2026-05-15 +> **日期**: 2026-05-16 > **状态**: 待实施 -> **替代**: Vol.Pro_MC4.0_整合方案_v1.0、Vol.Pro_Owl_ZLMediaKit_整合方案_v1.0、Vol.Pro_统一设备管理_区域树与地图绑定方案_v1.0 +> **替代**: v1.0 系列方案文档 --- @@ -11,49 +11,88 @@ ``` 前端层 - web.vite 管理端(设备管理页+标准CRUD) warehouse 大屏(Map/Live/IoT/Alarm) - │ HTTP REST │ HTTP REST + SignalR - ▼ ▼ + web.vite 管理端(设备管理+网关管理) warehouse 大屏(Map/Live/IoT/Alarm) + | HTTP REST | HTTP REST + SignalR + v v Vol.Pro 后端 (api_sqlsugar) - DeviceManagerController / GatewayClient / SignalR Hubs + DeviceManagerController / GatewayNodeController / SignalR Hubs Quartz: SyncDevicesJob / RealtimePollJob / AlarmPollJob - 数据库: Base_Device / warehouse_regions / Device_Video_Ext / Device_IoT_Ext / IoT_DevicePoint / IoT_Alarm - │ HTTP REST - ▼ -IntegrationGateway (独立服务 :5100) - Adapters.Owl (IHasFlatDevices+IHasStreams+IAcceptsMetadataPush) - Adapters.MC4 (IHasOwnDeviceTree+IHasPoints+IHasAlarms) - Core: AdapterRegistry / SyncEngine / TokenManager / RateLimiter - │ HTTP │ HTTP - ▼ ▼ -Owl + ZLMediaKit MC4.0 采集网关 -Docker Compose HTTP API :3000 + 数据库: 8 张表 (base_device / 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 (:80) MC4.0 (:3000) 海康ISC (:80) ``` +### 网关多实例架构(方案 C+) + +- Vol.Pro 管理网关实例:gateway_nodes 表注册所有网关节点 +- 网关启动时主动注册:POST /api/gateway/register 上报 NodeCode/Token/AdapterTypes/BaseUrl +- Vol.Pro 下发顶层设备:Base_Device.GatewayNodeId 关联设备归属 +- 网关无状态:配置只有 3 个值(NodeCode/Token/VolProUrl),挂了重装即恢复 +- AdapterCode 双段标识:"mc4:31号库房" 区分同类型多实例 +- 心跳机制:网关每 15s 上报心跳,Vol.Pro 超 30s 无心跳级联设备离线 + --- ## 二、IntegrationGateway 设计 -### 2.1 项目结构 +### 2.1 项目结构(位于 gateway/ 独立文件夹) ``` -IntegrationGateway/ -├── src/ -│ ├── Host/Controllers/ → Devices / Points / Streams / Alarms / Sync / Health -│ ├── Core/Abstractions/ → 分型接口 -│ │ ├── IIntegrationAdapter -│ │ ├── IHasOwnDeviceTree (MC4.0) -│ │ ├── IHasFlatDevices (Owl) -│ │ ├── IHasPoints (MC4.0) -│ │ ├── IHasStreams (Owl) -│ │ ├── IHasAlarms (通用) -│ │ └── IAcceptsMetadataPush (Owl) -│ ├── Core/Infrastructure/ → SyncEngine / AdapterRegistry / TokenManager / RateLimiter -│ ├── Adapters.Owl/ → OwlAdapter -│ └── Adapters.MC4/ → Mc4Adapter +gateway/ +├── IntegrationGateway.sln +└── src/ + ├── IntegrationGateway.Host/ # WebAPI (:5100) + | ├── Controllers/ + | | ├── HealthController.cs + | | ├── DevicesController.cs + | | ├── PointsController.cs + | | ├── StreamsController.cs + | | ├── AlarmsController.cs + | | ├── SyncController.cs + | | └── RegisterController.cs # 网关注册/心跳 + | ├── appsettings.json # { NodeCode, Token, VolProUrl } + | └── Program.cs + ├── IntegrationGateway.Core/ + | ├── Abstractions/ → 7 个分型接口 + | ├── Models/ → 10 个标准化模型 + | └── Infrastructure/ → AdapterRegistry / TokenManager / RateLimiter + ├── IntegrationGateway.Adapters.Owl/ + └── IntegrationGateway.Adapters.MC4/ ``` -### 2.2 适配器能力矩阵 +### 2.2 网关注册与心跳流程 + +``` +管理端: gateway_nodes 表新增记录 → 生成 NodeCode + Token +网关配置: appsettings.json { NodeCode, Token, VolProUrl } +网关启动 → POST /api/gateway/register { nodeCode,token,adapterTypes,baseUrl } +Vol.Pro 校验 Token → 更新 AdapterTypes/BaseUrl/IsOnline=1 +响应: { gatewayNodeId, devices: [Base_Device WHERE GatewayNodeId=当前网关] } +网关根据 AdapterCode 分流 → Adapter 连接第三方 → 发现子设备 +网关 → POST /api/gateway/sync → Vol.Pro 写入 Base_Device 及子设备 +网关每 15s → POST /api/gateway/heartbeat { nodeCode, token } +Vol.Pro 后台任务: IsOnline=1 且 LastHeartbeat < now-30s → IsOnline=0 → 级联设备离线 +``` + +### 2.3 网关配置 + +```json +{ + "VolProBaseUrl": "http://localhost:9100", + "NodeCode": "gw-31ku", + "NodeToken": "xxxxxxxxxx" +} +``` + +适配器类型由网关启动时扫描已注册的 Adapter 类自动获取,无需在配置中声明。 + +### 2.4 适配器能力矩阵 | 接口 | Owl | MC4.0 | 门禁(未来) | |------|:---:|:-----:|:----------:| @@ -64,7 +103,7 @@ IntegrationGateway/ | IHasAlarms | ⚠️ | ✅ | ✅ | | IAcceptsMetadataPush | ✅ | ❌ | ⚠️ | -### 2.3 双向同步引擎 +### 2.5 双向同步引擎 | 方向 | 说明 | MC4.0 | Owl | |------|------|-------|-----| @@ -72,10 +111,14 @@ IntegrationGateway/ | PushToSource | Vol.Pro→第三方 | 告警确认/控制 | 元数据/PTZ | | Bidirectional | 先写第三方再更新本地 | 告警确认 | — | -### 2.4 Gateway API +### 2.6 Gateway API ``` -GET /api/gateway/health +# 注册与心跳 +POST /api/gateway/register { nodeCode, token, adapterTypes, baseUrl } +POST /api/gateway/heartbeat { nodeCode, token } + +# 设备与数据 GET /api/gateway/devices?adapter=&page=&size= GET /api/gateway/devices/sync?adapter= GET /api/gateway/realtime/{adapter}/{deviceId} @@ -84,11 +127,12 @@ GET /api/gateway/streams/{adapter}/{id}/live POST /api/gateway/streams/{adapter}/{id}/ptz GET /api/gateway/alarms/{adapter}?from=&to= POST /api/gateway/alarms/{adapter}/{id}/confirm +GET /api/gateway/health ``` --- -## 三、数据模型 +## 三、数据模型(8 张表) ### 3.1 区域表 warehouse_regions(现有) @@ -98,51 +142,67 @@ POST /api/gateway/alarms/{adapter}/{id}/confirm | RegionName | nvarchar(255) | | ParentId | int? (自引用树) | -### 3.2 统一设备主表 Base_Device(新建) +### 3.2 网关节点表 gateway_nodes(新建) | 字段 | 类型 | 说明 | |------|------|------| -| DeviceId | uniqueidentifier PK | Vol.Pro内部ID | -| DeviceName | nvarchar(100) | 本地名称 | -| **AdapterCode** | nvarchar(50) | owl/mc4/hikvision_access | -| **SourceId** | nvarchar(100) | 第三方原始ID | -| DeviceCategory | int | 1=视频 2=IoT 3=门禁 4=道闸 5=报警 | -| DeviceType | nvarchar(50) | GB28181/TempSensor... | -| **RegionId** | int? | FK→warehouse_regions.Id | -| **IsParent** | bit | 是否父设备 | -| **ParentDeviceId** | uniqueidentifier? | 父设备自引用 | -| IsOnline | int | 0/1 | -| **MapModelId** | nvarchar(100) | VgoMap模型ID | -| MapModelScale | float | | -| MapModelRotation | nvarchar(100) | | -| Lat/Lng | float | WGS84 | -| ExtraData | nvarchar(max) | 适配器原始JSON | -| LocalOverrides | nvarchar(max) | 本地覆盖JSON | -| SyncVersion | bigint | 乐观锁 | -| LastSyncTime | datetime | | +| NodeId | INT AUTO_INCREMENT | 网关节点ID | +| NodeCode | NVARCHAR(50) | 网关唯一编码(管理端配置) | +| NodeName | NVARCHAR(100) | 网关名称 | +| NodeToken | NVARCHAR(100) | 认证令牌(管理端生成) | +| AdapterTypes | NVARCHAR(200) | 适配器类型(网关上报) | +| BaseUrl | NVARCHAR(200) | 网关地址(网关上报) | +| LastHeartbeat | DATETIME | 上次心跳时间 | +| IsOnline | TINYINT DEFAULT 0 | 在线状态 | +| Enable | TINYINT DEFAULT 1 | 启用 | + +### 3.3 统一设备主表 Base_Device + +| 字段 | 类型 | 说明 | +|------|------|------| +| DeviceId | INT AUTO_INCREMENT | Vol.Pro内部ID | +| DeviceName | NVARCHAR(100) | 本地名称 | +| AdapterCode | NVARCHAR(50) | "mc4:31号库房"(类型:实例) | +| SourceId | NVARCHAR(100) | 第三方原始ID | +| DeviceCategory | INT | 1=视频 2=IoT 3=门禁 4=道闸 5=报警 | +| RegionId | INT? | 所属区域ID | +| GatewayNodeId | INT? | 所属网关节点ID | +| IsParent | TINYINT | 是否父设备 | +| ParentDeviceId | INT? | 父设备自引用 | +| IsOnline | TINYINT | 在线状态 | +| MapModelId | NVARCHAR(100) | VgoMap模型ID | +| MapModelScale | FLOAT | | +| MapModelRotation | NVARCHAR(100) | | +| Lat/Lng | DOUBLE | WGS84 | +| ExtraData | TEXT | 适配器原始JSON | +| LocalOverrides | TEXT | 本地覆盖JSON | +| SyncVersion | BIGINT | 乐观锁 | +| LastSyncTime | DATETIME | | 唯一约束: (AdapterCode, SourceId) -### 3.3 扩展表 +### 3.4 扩展表 -- **Device_Video_Ext**: 视频设备扩展(OwlDeviceId, Protocol, ChannelCount) -- **Device_IoT_Ext**: IoT设备扩展(Mc4DeviceId, ObjectType, Tag) -- **Video_Channel**: 视频通道(OwlChannelId, DeviceId, HasPtz) -- **Video_Record**: 录像记录 -- **IoT_DevicePoint**: 点位表(PointIndex, PointName, Unit, IsControlPoint) -- **IoT_DeviceData**: 历史归档(仅存快照,实时不入库) -- **IoT_Alarm**: 告警记录(Mc4AlarmId, AlarmLevel, State) +- Device_Video_Ext: 视频设备扩展(OwlDeviceId, Protocol, ChannelCount) +- Video_Channel: 视频通道扩展(OwlChannelId, DeviceId, OwlStreamApp/Name, HasPtz, SnapshotUrl) +- Video_Record: 录像记录(ChannelId, OwlRecordId, StartedAt, FilePath) +- Device_IoT_Ext: IoT设备扩展(Mc4DeviceId, PointIndex, Unit, IsControlPoint, ObjectType) +- IoT_DeviceData: 历史归档(DeviceId→子设备, PointValue, 仅存快照) +- IoT_Alarm: 通用告警(SourceAlarmId, DeviceId, AlarmLevel, State) -### 3.4 层级示例 +### 3.5 层级示例 ``` +gateway_nodes: gw-31ku (32号库房网关, MC4+Owl) + warehouse_regions: 厂区 → 新库区 → 31号库房 -Base_Device (RegionId=3): - 东北角高位摄像机 (Category=1) - 人员计数摄像机 (Category=1) - 动环采集器 (Category=2, IsParent=1) - ├── 温湿度探头 (ParentDeviceId=采集器) - ├── 空调控制器 (ParentDeviceId=采集器) + +Base_Device (RegionId=3, GatewayNodeId=gw-31ku.NodeId): + 东北角高位摄像机 (Category=1, Device_Video_Ext) + 人员计数摄像机 (Category=1, Device_Video_Ext) + 动环采集器 (Category=2, IsParent=1, Device_IoT_Ext) + ├── 温湿度探头 (ParentDeviceId=采集器, Device_IoT_Ext.PointIndex=0) + ├── 空调控制器 (ParentDeviceId=采集器, Device_IoT_Ext.IsControlPoint=1) ├── 除湿机 (ParentDeviceId=采集器) └── 紧急报警按钮 (ParentDeviceId=采集器) ``` @@ -154,47 +214,43 @@ Base_Device (RegionId=3): ### 4.1 布局 ``` -┌──────────────────┬───────────────────────────────────────┐ -│ 顶部工具栏 │ │ -├──────────────────┼───────────────────────────────────────┤ -│ 左侧区域树 │ 右侧设备列表 │ -│ │ │ -│ 📁 厂区 │ 区域:31号库房 最后同步:05-15 │ -│ 📁 新库区 │ ┌──────────────────────────────┐ │ -│ 📁 31号库房 ● │ │ ▸动环采集器 MC4.0 █在线 │ │ -│ 📁 11号库房 │ │ 东北角摄像机 Owl █在线 │ │ -│ │ └──────────────────────────────┘ │ -│ [+新建区域] │ │ -└──────────────────┴───────────────────────────────────────┘ ++------------------+---------------------------------------+ +| 顶部工具栏 | | ++------------------+---------------------------------------+ +| 左侧区域树 | 右侧设备列表 | +| | | +| 📁 厂区 | 区域:31号库房 最后同步:05-15 | +| 📁 新库区 | +---------------------------------+ | +| 📁 31号库房 ● | | ▸动环采集器 MC4.0 █在线 | | +| 📁 11号库房 | | 东北角摄像机 Owl █在线 | | +| | +---------------------------------+ | +| [+新建区域] | | ++------------------+---------------------------------------+ ``` ### 4.2 前端文件 ``` web.vite/src/views/warehouse/DeviceManager/ -├── index.vue # 主页面(左树右表) +├── index.vue # 主页面 ├── components/ │ ├── RegionTree.vue # el-tree 区域树 │ ├── DeviceTable.vue # el-table 可展开行 │ ├── DeviceEditDialog.vue # 编辑弹框 │ ├── MapBindingPanel.vue # 地图绑定面板 -│ ├── VideoDeviceActions.vue # 视频操作按钮组 -│ └── IoTDeviceActions.vue # IoT操作按钮组 +│ ├── VideoDeviceActions.vue # 视频按钮组 +│ └── IoTDeviceActions.vue # IoT按钮组 └── api/deviceManager.js - -路由: /device-manager ``` ### 4.3 后端 API | 接口 | 说明 | |------|------| -| GET `/api/DeviceManager/GetRegionTree` | 区域树+设备数量 | -| GET `/api/DeviceManager/GetDevicesByRegion?regionId=3` | 区域设备列表(含子设备) | -| PUT `/api/DeviceManager/{deviceId}` | 更新设备(含地图绑定) | -| POST `/api/DeviceManager/SyncFromGateway` | 手动同步 | - -Controller 路径: `Controllers/Warehouse/Partial/DeviceManagerController.cs` +| GET /api/DeviceManager/GetRegionTree | 区域树+设备数量 | +| GET /api/DeviceManager/GetDevicesByRegion | 区域设备列表(含子设备) | +| PUT /api/DeviceManager/{deviceId} | 更新设备(含地图绑定) | +| POST /api/DeviceManager/SyncFromGateway | 手动同步 | ### 4.4 操作按钮矩阵 @@ -210,13 +266,13 @@ Controller 路径: `Controllers/Warehouse/Partial/DeviceManagerController.cs` ## 五、同步策略 ### MC4.0 → 区域树+设备 -- `type=1` 节点 → 名称匹配 warehouse_regions → 绑区或新建 -- `type=2` 节点 → Upsert Base_Device, RegionId=叶子区域 +- type=1 节点 → 名称匹配 warehouse_regions → 绑区或新建 +- type=2 节点 → Upsert Base_Device, RegionId=叶子区域, GatewayNodeId=当前网关 - 模式: FullReplace, 频率限制: 2次/秒 ### Owl → 设备 -- `GET /devices` → Upsert Base_Device (Category=1, IsParent=1) -- `GET /channels` → Upsert Base_Device (ParentDeviceId=NVR) +- GET /devices → Upsert Base_Device (Category=1, IsParent=1) +- GET /channels → Upsert Base_Device (ParentDeviceId=NVR) - Owl 无区域概念 → RegionId=NULL, 管理员手动分配 - 模式: Merge @@ -233,20 +289,24 @@ Controller 路径: `Controllers/Warehouse/Partial/DeviceManagerController.cs` ## 六、部署拓扑 ``` -Docker: Owl+ZLM (:80,:5060) │ Docker: MC4.0 (:3000) - │ - ┌──────────────┴──────────────┐ - │ IntegrationGateway :5100 │ - └──────────────┬──────────────┘ - │ - ┌──────────────┴──────────────┐ - │ VolPro.WebApi :9100 │ - │ MySQL / Redis │ - └──────────────┬──────────────┘ - │ - ┌──────────────────┴──────────────────┐ - │ web.vite :9000 warehouse :9200 │ - └─────────────────────────────────────┘ +Docker: Owl+ZLM (:80) 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 | + +--------------------------------+ ``` --- @@ -255,27 +315,25 @@ Docker: Owl+ZLM (:80,:5060) │ Docker: MC4.0 (:3000) | 阶段 | 工期 | 内容 | |------|------|------| -| Phase 0 | Day 1-2 | Gateway骨架 + Base_Device建表 + 代码生成 | +| Phase 0 | Day 1-2 | Gateway骨架 + 8张表建表 + 代码生成 | | Phase 1 | Day 3-6 | OwlAdapter + 管理端视频设备页 | | Phase 2 | Day 7-11 | Mc4Adapter + IoT管理 + 区域树匹配 + SignalR | | Phase 3 | Day 12-17 | warehouse端改造 + 全链路联调 | | Phase 4 | Day 18-20 | 验证 + 缓冲 | -**总计: 18-20 个工作日** +总计: 18-20 个工作日 --- ## 八、新增整合流程 以接入「海康门禁」为例: -1. 新建 `IntegrationGateway.Adapters.HikvisionAccess` 项目 -2. 实现 `IHasFlatDevices + IHasAlarms` -3. 注册到 Host -4. 前端新增 `AccessDeviceActions.vue` (~80行) -5. DeviceTable.vue 加 `v-else-if (Category===3)` -6. Vol.Pro 后端零改动 - -**总工作量: 1-2 天** +1. 新建 IntegrationGateway.Adapters.HikvisionAccess 项目 +2. 实现 IHasFlatDevices + IHasAlarms +3. 注册到 Host → 网关启动时自动上报到 Vol.Pro +4. 前端新增 AccessDeviceActions.vue (~80行) +5. Vol.Pro 后端零改动 +总工作量: 1-2 天 --- @@ -283,7 +341,7 @@ Docker: Owl+ZLM (:80,:5060) │ Docker: MC4.0 (:3000) | 代码类型 | 路径 | 被覆盖? | |----------|------|:---:| -| 第三方对接 | IntegrationGateway/ | ❌ | +| 第三方对接 | gateway/ | ❌ | | 扩展Controller | Controllers/*/Partial/ | ❌ | | Entity扩展 | DomainModels/*/partial/ | ❌ | | 前端业务逻辑 | extension/warehouse/*.jsx | ❌ | @@ -292,5 +350,4 @@ Docker: Owl+ZLM (:80,:5060) │ Docker: MC4.0 (:3000) --- -> **文档结束** -> **取代**: Vol.Pro_MC4.0_整合方案_v1.0、Vol.Pro_Owl_ZLMediaKit_整合方案_v1.0、Vol.Pro_统一设备管理_区域树与地图绑定方案_v1.0、Vol.Pro_整合项目_实施方案_v1.0 +> 取代: V1.0 系列所有整合方案文档