# SecMPS 整合方案 v3.0 > 版本: 3.0 > 日期: 2025-05-17 > 状态: 草稿 --- ## 1. 背景与目标 SecMPS 需要将多套异构子系统(视频监控、IoT动环、门禁道闸、报警)统一整合到 Vol.Pro 管理端。v2.0 采用 Vol.Pro 直接对接各子系统 API,存在紧耦合、协议适配散落、扩展困难等问题。 v3.0 引入 **IntegrationGateway(整合网关)** 作为统一中间层,面向子系统做协议适配,面向 Vol.Pro 提供标准化 REST API,实现"适配一次,多处复用"。 ### 1.1 核心原则 | 原则 | 说明 | |------|------| | 适配器隔离 | 每个子系统一个 Adapter,实现统一接口,互不干扰 | | 懒加载 | 适配器按需初始化,不阻塞网关启动 | | 分页语义统一 | 统一 page/size 分页,适配器内部转换 skip/limit | | 字段分治 | 网关负责"来源标识+在线状态",Vol.Pro 负责"设备名称+扩展属性",首次入库全量,后续仅更新网关字段 | ### 1.2 子系统清单 | 子系统 | 对接方式 | 适配器 | 核心能力 | |--------|----------|--------|----------| | Owl + ZLMediaKit | REST API | OwlAdapter | 视频设备发现、实时流、PTZ、录像回放、截图 | | MC4.0 | REST API | MC4Adapter | 对象树、实时点值、设备控制、告警查询/确认/结束 | --- ## 2. 架构总览 ``` ┌──────────────────────────────────────────────────────────┐ │ Vol.Pro 管理端 │ │ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ gateway_nodes│ │ base_device │ │ device_manager │ │ │ │ Controller │ │ Controller │ │ (前端页面) │ │ │ │ A1-A4 │ │ GetRegion..│ │ RegionTree + │ │ │ │ │ │ GetDevices │ │ DeviceTable │ │ │ └──────┬───────┘ └──────┬───────┘ └────────┬────────┘ │ │ │ │ │ │ │ │ GatewayClient │ │ HTTP │ │ └────────┬────────┘ │ │ │ │ B3 (REST) │ │ └──────────────────┼─────────────────────────────┼──────────┘ │ │ ┌──────────────────┼─────────────────────────────┼──────────┐ │ IntegrationGateway (net8.0) │ │ │ │ │ │ │ ┌───────────────┴──────────────────────────────┴───────┐ │ │ │ AdapterRegistry │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ OwlAdapter │ │ MC4Adapter │ ... │ │ │ │ │ IHasFlat.. │ │ IHasOwnTree │ │ │ │ │ │ IHasStreams │ │ IHasPoints │ │ │ │ │ │ IHasPtz │ │ IHasAlarms │ │ │ │ │ └──────┬──────┘ └──────┬──────┘ │ │ │ └─────────┼────────────────┼───────────────────────────┘ │ │ │ │ │ │ ┌────────┴────────┐ ┌───┴──────────┐ │ │ │ Owl + ZLMediaKit│ │ MC4.0 │ │ │ │ (视频监控) │ │ (动环/IoT) │ │ │ └─────────────────┘ └──────────────┘ │ └──────────────────────────────────────────────────────────┘ ``` ### 2.1 数据流 ``` MC4.0 对象树 → Mc4Adapter.GetObjectTree() → SyncEngine.ProcessMc4Tree() → type=1 节点 → warehouse_regions (区域匹配) → type=2 节点 → base_device (Upsert, 字段分治) ``` ### 2.2 网关端口约定 | 服务 | 端口 | 说明 | |------|------|------| | IntegrationGateway | 5100 | 设备管理 REST API | | Owl + ZLMediaKit | 15123 | 视频流/录像 | | MC4.0 | 3000 | 动环数据/告警 | | Vol.Pro | 9991 | 管理端后端 | --- ## 3. 核心接口体系 ### 3.1 能力接口(Capability Interfaces) ```csharp // 适配器按需实现,网关通过反射或接口判断自动发现能力 interface IHasFlatDevices { Task> GetDevicesAsync(int page, int size, string? keyword); } interface IHasOwnDeviceTree { Task> GetObjectTreeAsync(); } interface IHasStreams { Task GetLiveUrlAsync(string channelId); Task GetPlaybackUrlAsync(string channelId, DateTime start, DateTime end); } interface IHasPtz { Task PtzControlAsync(string channelId, string direction, float speed); } interface IHasRecordings { Task> GetRecordingsAsync(string channelId, DateTime start, DateTime end, int page, int size); } interface IHasPoints { Task> GetRealtimeValuesAsync(string sourceDeviceId); Task SetPointValueAsync(string sourceDeviceId, int pointIndex, double value); } interface IHasAlarms { Task> GetAlarmsAsync(int page, int size, DateTime from, DateTime to, ...); Task ConfirmAlarmAsync(string alarmId); Task EndAlarmAsync(string alarmId); } interface IAcceptsMetadataPush { Task PushMetadataAsync(string sourceDeviceId, MetadataChangeSet changes); } ``` ### 3.2 网关统一模型 ```csharp class StandardDevice { int DeviceId; // Vol.Pro 侧主键(同步后回填) string AdapterCode; // "Owl:main" / "MC4:31ku" string SourceId; // 子系统原始 ID string DeviceName; string DeviceCategory; // 摄像机/温湿度变送器/... string DeviceGroup; // 视频设备/IoT设备/门禁设备/... bool IsParent; string ParentSourceId; bool IsOnline; string IpAddress; int? Port; Dictionary Extra; // 子系统扩展属性 } class StandardAlarm { string AlarmId; string DeviceId; string AdapterCode; string Level; // 提示/普通/重要/紧急 string Title; string Content; DateTime OccurTime; string Status; // 未确认/已确认/已结束 double? ActualValue; double? ThresholdValue; } class DeviceTreeNode { string SourceId; string Name; int NodeType; // 1=区域, 2=设备 int ObjectType; string Tag; Dictionary Option; List Children; } ``` ### 3.3 订阅接口(B3,供 Vol.Pro 回调) | 路由 | 方法 | 说明 | |------|------|------| | `/api/gateway/register` | POST | 网关注册 (Upsert) | | `/api/gateway/heartbeat` | POST | 心跳 | | `/api/gateway/sync/devices` | POST | 设备数据同步 | | `/api/gateway/sync/alarms` | POST | 告警同步 | ### 3.4 网关暴露接口 | 路由 | 适配器能力 | 说明 | |------|-----------|------| | `GET /devices?adapter={code}&page=&size=` | IHasFlatDevices | 分页获取设备列表 | | `GET /tree?adapter={code}` | IHasOwnDeviceTree | 获取对象树 | | `GET /streams/{adapter}/{deviceId}/live` | IHasStreams | 获取实时流地址 | | `GET /streams/{adapter}/{deviceId}/playback` | IHasStreams | 获取回放地址 | | `POST /streams/{adapter}/{deviceId}/snapshot` | IHasStreams | 获取截图 | | `POST /streams/{adapter}/{deviceId}/ptz` | IHasPtz | 云台控制 | | `GET /recordings/{adapter}/{deviceId}` | IHasRecordings | 获取录像列表 | | `GET /points/{adapter}/{deviceId}` | IHasPoints | 获取实时点值 | | `POST /points/{adapter}/{deviceId}` | IHasPoints | 控制写值 | | `GET /alarms/{adapter}` | IHasAlarms | 分页获取告警 | | `POST /alarms/{adapter}/{id}/confirm` | IHasAlarms | 确认告警 | | `POST /alarms/{adapter}/{id}/end` | IHasAlarms | 结束告警 | | `GET /health` | - | 适配器健康状态 | --- ## 4. 数据库设计 ### 4.1 新增表(5 张,Vol.Pro 侧) ```sql -- 网关节点表 CREATE TABLE gateway_nodes ( NodeId INT IDENTITY PRIMARY KEY, NodeCode NVARCHAR(50) NOT NULL, NodeName NVARCHAR(100), NodeToken NVARCHAR(200), AdapterTypes NVARCHAR(200), -- "Owl:main,MC4:31ku" BaseUrl NVARCHAR(500), IsOnline NVARCHAR(10), -- 在线/离线 Enable NVARCHAR(10), -- 启用/禁用 LastHeartbeat DATETIME, CreateDate DATETIME, CreateID INT, Creator NVARCHAR(50), ModifyDate DATETIME, ModifyID INT, Modifier NVARCHAR(50) ); -- 统一设备表 CREATE TABLE base_device ( DeviceId INT IDENTITY, AdapterCode NVARCHAR(50) NOT NULL, -- 联合主键 DeviceName NVARCHAR(100), SourceId NVARCHAR(100) NOT NULL, -- 联合主键 (AdapterCode + SourceId = 唯一) DeviceCategory NVARCHAR(50), -- 摄像机/硬盘录像机/温湿度变送器/... DeviceGroup NVARCHAR(50), -- 视频设备/IoT设备/门禁设备/... PointId INT NULL, -- FK → warehouse_devicepoint GatewayNodeId INT NULL, -- FK → gateway_nodes IsParent NVARCHAR(10), ParentDeviceId INT NULL, IsOnline NVARCHAR(10), Enable NVARCHAR(10), Protocol NVARCHAR(50), IpAddress NVARCHAR(50), Port INT NULL, LastSyncTime DATETIME, MapModelId NVARCHAR(100), MapModelScale NVARCHAR(50), MapModelRotation NVARCHAR(200), ExtraData NVARCHAR(MAX), -- JSON 扩展属性 CreateDate DATETIME, CreateID INT, Creator NVARCHAR(50), ModifyDate DATETIME, ModifyID INT, Modifier NVARCHAR(50), PRIMARY KEY (DeviceId, AdapterCode) ); -- 数据归档表 CREATE TABLE iot_devicedata ( DataId INT IDENTITY PRIMARY KEY, DeviceId INT NULL, AdapterCode NVARCHAR(50), PointIndex INT, Value FLOAT, UpdateTime DATETIME, CreateDate DATETIME ); -- 告警记录表 CREATE TABLE iot_alarm ( AlarmId INT IDENTITY PRIMARY KEY, SourceAlarmId NVARCHAR(100), DeviceId INT NULL, AdapterCode NVARCHAR(50), AlarmLevel NVARCHAR(20), AlarmDesc NVARCHAR(500), AlarmValue FLOAT, ThresholdValue FLOAT, StartTime DATETIME, EndTime DATETIME, ConfirmTime DATETIME, State NVARCHAR(20), -- 未确认/已确认/已结束 ConfirmUser NVARCHAR(50), CreateDate DATETIME ); -- 视频通道表(base_device 子表) CREATE TABLE video_channel ( ChannelId INT NOT NULL, DeviceId INT NOT NULL, -- FK → base_device ChannelNo NVARCHAR(50), SourceId NVARCHAR(100), ChannelName NVARCHAR(100), IsOnline NVARCHAR(10), CreateDate DATETIME, PRIMARY KEY (ChannelId, DeviceId) ); -- 录像文件表 CREATE TABLE video_record ( RecordId INT IDENTITY PRIMARY KEY, ChannelId INT NULL, FilePath NVARCHAR(500), Size BIGINT, StartTime DATETIME, EndTime DATETIME, Duration FLOAT, CreateDate DATETIME ); ``` ### 4.2 字典初始化 ```sql -- 设备分类字典 INSERT INTO Sys_Dictionary (DicName, DicValue, DicNo, Config) VALUES ('设备分组', '视频设备', 'device_group_1', '视频设备'), ('设备分组', 'IoT设备', 'device_group_2', 'IoT设备'), ('设备分组', '门禁设备', 'device_group_3', '门禁设备'), ('设备分组', '道闸设备', 'device_group_4', '道闸设备'), ('设备分组', '报警设备', 'device_group_5', '报警设备'); ``` --- ## 5. 管理端前端 ### 5.1 页面结构 ``` /web.vite/src/views/warehouse/DeviceManager/ ├── index.vue 左右分栏主页面 ├── api/ │ └── deviceManager.js API 封装 └── components/ ├── RegionTree.vue 区域→点位树 (左侧) ├── DeviceTable.vue 设备列表 (右侧) ├── VideoDeviceActions.vue 视频设备操作按钮组 ├── DeviceLivePreview.vue 实时预览弹窗 ├── PtzControlPanel.vue 云台方向键面板 ├── MapBindingPanel.vue 地图绑定面板 └── DeviceEditDialog.vue 设备编辑弹窗 ``` ### 5.2 路由 ``` /device-manager → DeviceManager/index.vue ``` ### 5.3 功能矩阵 | 功能 | 触发条件 | 组件 | 说明 | |------|---------|------|------| | 区域树展开 | 页面加载 | RegionTree | 调 GetRegionTree API | | 设备列表 | 点击点位 | DeviceTable | 调 GetDevicesByPoint API | | 实时预览 | 视频设备→预览 | DeviceLivePreview | WS-FLV 播放 | | 云台控制 | 视频设备→云台 | PtzControlPanel | ↑↓←→ + ZOOM | | 查看回放 | 视频设备→回放 | (待实现) | 录像时间轴 | | 获取快照 | 视频设备→快照 | (待实现) | JPEG 快照 | | 地图绑定 | 任意设备→地图 | MapBindingPanel | 模型 ID/缩放/旋转 | | 编辑设备 | 非视频设备→编辑 | DeviceEditDialog | 名称/种类/分组/启用 | --- ## 6. 实施计划 ### Phase 0: 基础设施(Day 1-2) | Day | 内容 | 产出 | |-----|------|------| | 1 | 网关项目骨架 (net8.0) | IntegrationGateway.sln, Core/Host 项目, 7 个能力接口, 10 个统一模型, 3 个基础设施 (Registry/RateLimiter/HttpClientFactory) | | 2 | Vol.Pro 侧集成 | GatewayClient, gateway_nodesController(A1-A4骨架), base_deviceController(骨架), Quartz Job, db_init.sql, 代码生成器产物 | ### Phase 1: Owl 适配器 + 管理端(Day 3-5) | Day | 内容 | 产出 | |-----|------|------| | 3 | OwlAdapter | RSA 加密登录, 3 个接口实现 (IHasFlatDevices + IHasStreams + IAcceptsMetadataPush) | | 4 | DeviceManager 页面框架 | RegionTree + DeviceTable + router | | 5 | 视频组件 | 预览/云台/地图绑定/编辑弹窗 | ### Phase 2: MC4 适配器 + 联调(Day 6-11) | Day | 内容 | 产出 | |-----|------|------| | 6 | 联调验证 (Owl + MC4) | 需子系统就绪 | | 7 | MC4Adapter | Token 认证, IHasOwnDeviceTree + IHasPoints + IHasAlarms | | 8 | 区域自动匹配 | SyncEngine, 字段分治, parentSourceId 映射 | | 9 | 物联网操作接口 | 实时值读取, 控制写值 API | | 10 | 告警集成 + SignalR | 告警查询/确认/结束, SignalR 实时推送 | | 11 | 地图绑定 + Quartz | MapBindingPanel, SyncDevicesJob, HeartbeatMonitorJob | ### Phase 3: Warehouse 端(Day 12-17) | Day | 内容 | 产出 | |-----|------|------| | 12 | 钥匙柜管理 | 钥匙柜设备 + 钥匙借还流程 | | 13 | 巡更管理 | 巡更路径/点位/排班 | | 14 | 门禁管理 | 门禁一体机 + 授权 | | 15 | 道闸管理 | 人行道闸 + 车辆道闸 | | 16 | 报警管理 | 紧急报警 + 离线报警 | | 17 | 仓库页面整合 | 菜单 + 权限 | ### Phase 4: 验证发布(Day 18-20) | Day | 内容 | 产出 | |-----|------|------| | 18 | 系统测试 | 功能测试 + 边界测试 | | 19 | 性能优化 | 流性能 + 并发 + 缓存 | | 20 | 文档 + 发布 | 部署手册, Dockerfile | --- ## 7. 风险与约束 | 风险 | 缓解措施 | |------|----------| | Vol.Pro 框架 API 与自主代码不兼容 | 网关层独立编译(dotnet build),Vol.Pro 后端逻辑骨架化,联调时一边调一边补 | | Owl 接口不稳定 | 统一 2 QPS 限流 + 重试 | | MC4 字段映射复杂 | 对象树 Option 弹性 JSON 字段,扩容不破坏现有映射 | | 设备数量大导致同步慢 | 增量同步 + 批量 Upsert | --- ## 8. 环境配置 ### 8.1 网关 appsettings.json ```json { "Owl": { "BaseUrl": "http://owl_host:15123", "Username": "admin", "Password": "your_owl_password" }, "MC4": { "BaseUrl": "http://mc4_host:3000" } } ``` ### 8.2 启动顺序 1. Owl + ZLMediaKit → 端口 15123 2. MC4.0 → 端口 3000 3. IntegrationGateway → 端口 5100 (`dotnet run --project src/IntegrationGateway.Host`) 4. Vol.Pro 后端 → 端口 9991 5. web.vite 前端 → 端口 9000 (`npm run dev`)