Files
SecMPS/doc/整合方案/SecMPS_最终整合方案_v3.0.md
2026-05-17 04:39:44 +08:00

532 lines
22 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 整合方案最终版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 管理端口为 15123ZLMediaKit 由 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设备/门禁设备/道闸设备/报警设备 |
| 是否父设备 | 是/否 |
| 在线状态 | 在线/离线 |
| 启用状态 | 启用/禁用 |
| 是否控制点 | 只读/可写 |
| 告警等级 | 提示/普通/重要/紧急 |
| 告警状态 | 未确认/已确认/已结束 |
---
## 附录 BAdapterCode 格式规范
```
格式: {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) — 第五章修订:取消独立设备管理页面,改为框架主从表嵌入操作按钮