Files
SecMPS/doc/整合方案/SecMPS_整合方案_最终评估报告.md
2026-05-16 13:34:03 +08:00

291 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SecMPS 整合方案 — 最终评估报告
> **评估日期**: 2026-05-16
> **评估对象**: SecMPS_最终整合方案_v2.0.md
> **参考依据**: Owl API 文档 / Owl GitHub / ZLMediaKit 官方文档 / ZLMediaKit GitHub / 数据字典设计
---
## 一、评估方法
以资深架构师经验,对整合方案进行三个维度的交叉验证:
1. **方案自洽性**章节间逻辑是否一致API 定义 ↔ 数据模型 ↔ 同步策略是否闭环
2. **对 Owl+ZLMediaKit 的准确性**:方案定义的接口和流程是否与 Owl v1.3.0 / ZLMediaKit master 实际行为匹配
3. **工程可落地性**:是否所有细节都有明确定义,是否存在"开发时再说"的模糊地带
共发现 **14 个问题**,按严重程度分为 P0阻塞实施、P1影响质量、P2优化项
---
## 二、P0 — 必须修复4 项)
### P0-1第四章示例代码与 A3 接口规范矛盾
**问题描述**
§四示例代码(第 263-265 行)在每次同步时写入 `DeviceName = d.Name``DeviceCategory = d.Category`。但 A3 接口规范明确说"网关不碰管理员字段,首次入库写全量,后续仅更新网关负责的列"。这导致管理员手动改过的设备名称每次同步后被网关覆盖。
**影响**:管理员的设备重命名操作会被同步覆盖,用户投诉
**解决方案**
```csharp
// 区分首次入库与增量更新
if (entity.DeviceId == 0) // 首次入库
{
entity.DeviceName = d.Name;
entity.DeviceCategory = d.Category;
entity.DeviceGroup = d.Group;
}
// 增量更新:只写网关负责的字段
entity.IsOnline = d.IsOnline ? "在线" : "离线";
entity.IsParent = d.IsParent ? "是" : "否";
entity.ExtraData = d.ExtraDataJson;
entity.LastSyncTime = DateTime.UtcNow;
```
---
### P0-2A3 设备同步中 `parentSourceId` → `ParentDeviceId` 解析链路缺失
**问题描述**
A3 请求中设备携带 `parentSourceId: "1001"`(第三方 ID但 Vol.Pro 需要 `ParentDeviceId`(本地主键)。从第三方 ID 到本地主键的映射逻辑完全未定义。
**影响**:子设备无法挂到父设备下,设备树断裂
**解决方案**
同步前先做映射表查询:
```csharp
// 批量取出当前网关所有设备
var allIds = await _db.base_device
.Where(x => x.GatewayNodeId == nodeId)
.ToDictionaryAsync(x => (x.AdapterCode, x.SourceId), x => x.DeviceId);
// 解析 parentSourceId
int? parentDeviceId = null;
if (!string.IsNullOrEmpty(d.ParentSourceId))
allIds.TryGetValue((d.AdapterCode, d.ParentSourceId), out var pid);
parentDeviceId = pid > 0 ? pid : null;
entity.ParentDeviceId = parentDeviceId;
```
补充到 §四 代码示例中。
---
### P0-3网关重启注册时 NodeId 分配逻辑未定义
**问题描述**
网关重启再次调用 A1 `/register``gateway_nodes` 表中 `NodeCode` 已存在。当前文档只说注册流程,没有说明是覆盖还是报错。如果新建 NodeId`base_device.GatewayNodeId` 指向旧 ID 断裂。
**影响**:网关重启后设备归属丢失
**解决方案**
A1 接口改为 Upsert 逻辑:
```
POST /register →
NodeCode 匹配 → 更新 AdapterTypes/BaseUrl/IsOnline=在线 → 返回已有 NodeId
NodeCode 不匹配 → 插入新记录 → 返回新 NodeId → 401防止未授权节点
```
补充到 §2.1 流程描述和 A1 API 规范中。
---
### P0-4Owl 管理端口错误
**问题描述**
Owl README 和 Docker Compose 明确 Owl Web 管理端口 = `15123`。方案 `appsettings.json` 和 §七部署拓扑均写 `owl_host:80`
**影响**:网关无法连接 Owl所有视频功能不可用
**解决方案**
- `appsettings.json` 中 Owl BaseUrl → `http://owl_host:15123`
- §七部署拓扑中 Owl 端口标记为 `:15123`
- 注意ZLM 自身 HTTP 端口是 `8000`,但由 Owl 内部调用,网关不接触
---
## 三、P1 — 影响实施质量6 项)
### P1-1PTZ 接口仅实现 continuous + stop
**问题描述**
owl_api_research.md §6.1 和 Owl GitHub 确认Owl 代码中仅实现了 `continuous`(持续移动)和 `stop`(停止),`preset`(预置位)、`absolute`(绝对定位)、`relative`相对定位均返回错误。ONVIF PTZ 标记为 TODO。
方案 §2.3 适配器矩阵和 B7 API 没有注明此限制。
**影响**:开发前端云台面板时做了预置位下拉等功能,部署后不可用
**解决方案**
- B7 接口标注:"仅支持 continuous (方向移动) + stop (停止)"
- 前端云台面板:仅显示方向键(↑↓←→)+ 停止按钮,不显示预置位
- OwlAdapter.PtzControlAsync 实现ONVIF 设备直接返回错误
---
### P1-2视频通道在 base_device 和 video_channel 中的双重身份不清
**问题描述**
§6 Owl 同步说 "Upsert base_device(ParentDeviceId=NVR) + video_channel",但 §3.6 层级示例中摄像机是叶子节点没有子设备。一个 Owl 通道到底是 base_device 的子记录还是 video_channel 的独立记录?还是两者都是?
**影响**:开发者不清楚通道数据写入哪张表的哪个字段
**解决方案**
明确:一个 Owl 通道 = 2 条记录:
1. `base_device` 子记录DeviceName="通道01", DeviceCategory=摄像机, ParentDeviceId=NVR的DeviceId, ExtraData=null
2. `video_channel` 扩展记录DeviceId=通道的DeviceId, OwlStreamApp, OwlStreamName, HasPtz, SnapshotUrl
在 §3.6 层级示例中增加通道示例:
```
NVR (IsParent=是)
├── 通道01 (base_device子记录, video_channel.OwlStreamApp="rtp")
├── 通道02 (base_device子记录, video_channel.OwlStreamApp="rtp")
```
---
### P1-3回放取流与实时取流走不同的 Owl 端点
**问题描述**
- 实时播放:`POST /channels/:id/play`
- 回放播放:`GET /recordings/channels/:cid/index.m3u8?start_ms=&end_ms=&token=`
两者是 Owl 的不同端点,方案 B6 只有一个 `/live` 路径。
**影响**:回放功能无法对接 Owl
**解决方案**
B6 拆分为两个端点:
```
GET /streams/{adapter}/{channelId}/live → Owl POST /channels/:id/play
GET /streams/{adapter}/{channelId}/playback?start=&end= → Owl GET /recordings/channels/:cid/index.m3u8
```
IHasStreams 接口不变(已有 GetLiveUrlAsync 和 GetPlaybackUrlAsync只修正 B 组 API 路径。
---
### P1-4告警确认后 Vol.Pro 本地状态更新不闭环
**问题描述**
B9 调网关确认告警写回第三方成功,但 `iot_alarm.State` 谁来更新?当前文档没有说明这个回写链路。
**影响**:管理端显示告警仍为"未确认",需等下次 A4 同步才刷新
**解决方案**
B9 确认成功后Vol.Pro 侧同步更新本地:
```
POST /alarms/{adapter}/{alarmId}/confirm 成功 →
Vol.Pro 更新 iot_alarm SET State='已确认', ConfirmTime=NOW()
```
不需要网关二次推送。在 B9 接口规范中补充此说明。
---
### P1-5video_record 同步策略缺失
**问题描述**
§六同步策略有设备同步、告警同步、反向控制,但没有录像记录的同步时机和频率。
**影响**:录像数据永远不会写入 video_record 表
**解决方案**
补充 §六Owl 录像数据同步策略 ——
- **方式一**(推荐):管理端点击"查看回放"时,网关实时调 Owl `GET /recordings` → 返回给管理端 → 同时写入 video_record 表
- **方式二**(备选):网关定时(每 10 分钟)调 Owl `GET /recordings` → 走 A3 扩展同步 → 写入 video_record
建议先用方式一,方式二在 Phase 3 优化时引入。
---
### P1-6AdapterCode 双段格式无约束
**问题描述**
`"mc4:31号库房"` 中分隔符 `:` 和实例名字符集没有规范。如果实例名包含 `:` 会导致解析歧义。
**影响**:网关配置或同步时数据损坏
**解决方案**
定义格式规范(补充到 §2.2
```
AdapterCode = "{AdapterType}:{InstanceName}"
AdapterType: 字母数字,对应网关注册的 Adapter 类名(如 MC4、Owl
InstanceName: 字母数字下划线,对应具体网关实例(如 31ku
分隔符: ':'
示例: "MC4:31ku"、"Owl:main"、"HikvisionISC:center"
```
---
## 四、P2 — 优化项4 项)
### P2-1子设备离线状态级联规则明确即可
**问题描述**
§2.1 说网关离线 → 设备离线,但网关在线时父设备(采集器)离线,子设备是否级联标记离线?
**解决方案**
网关在 A3 同步时如实上报每个子设备的 isOnlineMC4.0 树中已有此信息Vol.Pro 不做推断,信任网关数据。在 §六同步策略中补充此行说明即可。
---
### P2-2数据字典初始化运维指引补充附录
**问题描述**
方案依赖 7 个数据字典DeviceCategory 18 值、DeviceGroup 5 值、IsParent/IsOnline/Enable/IsControlPoint/AlarmLevel/State但没有初始化指引。
**解决方案**
在文档末尾增加「附录 A字典初始化清单」列出每个字典的 Code/Name/Value 对照表,运维人员在 Vol.Pro 管理端按表创建。
---
### P2-3video_channel 流地址字段用途说明(补充注释)
**问题描述**
video_channel 有 `OwlStreamApp/OwlStreamName/SnapshotUrl`B6 取流实时调网关获取。这些字段的实际用途没说。
**解决方案**
注明为缓存——首次取流后写入 video_channel下次先查缓存缓存过期或 Owl 重启后)再调 B6 实时获取。在 video_channel 表注释中补充说明。
---
### P2-4Owl AI 事件可接入告警(建议纳入 Phase 1 可选范围)
**问题描述**
Owl 有 YOLO 本地检测 + `GET /events` 接口AI 事件可走 A4 告警同步。
**解决方案**
在 OwlAdapter 中可选实现 IHasAlarms`GET /events` 的 AI 检测事件映射为 StandardAlarmAlarmLevel=提示或普通)。在 §六同步策略中补充可选说明,建议 Phase 1 范围中列入。
---
## 五、架构正确性确认
以下方面经过 Owl+ZLMediaKit 双文档验证,确认正确:
| 验证项 | 状态 |
|--------|:--:|
| 三层架构前端→网关→Owl不直接接触 ZLM | ✅ |
| Owl 代理播放地址 `/proxy/sms/...` | ✅ |
| Owl RTP 收流→ZLM 转协议→多格式输出的链路 | ✅ |
| Owl Webhook 自动配置 ZLM启动时 SetServerConfig | ✅ |
| JWT Token 管理 + RSA 加密登录 | ✅ |
| 设备/通道 CRUD 对应 Owl API | ✅ |
| 取流端点返回 WS-FLV/HTTP-FLV/HLS/WebRTC/RTMP/RTSP | ✅ |
| Owl↔ZLM 联动OpenRtpServer/CloseRtpServer/AddStreamProxy 等) | ✅ |
| 按需拉流 + 30s 无人观看自动关闭ZLM on_stream_none_reader → Owl 通知 ZLM 关流) | ✅ |
| 云录像由 Owl 管理ZLM MP4 录制→Owl on_record_mp4 hook→入库 | ✅ |
| GB28181 设备注册与心跳是 SIP 层自动完成Vol.Pro 只查 HTTP API | ✅ |
| 播放地址通过 Owl `/proxy/sms/` 反向代理到 ZLM前端不直接访问 ZLM | ✅ |
---
## 六、总结
| 优先级 | 数量 | 类型 |
|:---:|:--:|------|
| P0 | 4 | 阻塞性缺陷(代码矛盾、链路缺失、端口错误、注册逻辑缺失) |
| P1 | 6 | 实施质量影响PTZ限制、通道身份、回放端点、告警闭环、录像缺失、格式规范 |
| P2 | 4 | 优化项级联规则、字典指引、缓存说明、AI事件 |
| ✅ | 12 | 已验证正确 |
**总体评价**方案架构方向完全正确Owl+ZLMediaKit 对接路径准确。14 个问题中 P0/P1 共 10 项,全部为配置级或接口路径级微调,不涉及架构推翻。修复后可直接作为实施基准。
---
> 本报告应作为 SecMPS_最终整合方案_v2.0.md 的修正依据。建议将 P0/P1 问题修复合入方案文档后再开始 Phase 1。