# VolPro.WebApi 网关相关接口文档 > **版本**: 1.0 > **日期**: 2026-06-04 > **基址**: `http://{host}:{port}`(默认 `http://localhost:9100`) > **内容类型**: `application/json` > **接口来源**: `api_sqlsugar/VolPro.WebApi/Controllers/Warehouse/` --- ## 目录 1. [A 组 — 网关注册通信](#1-a-组--网关注册通信) - A1: 网关注册 `POST /api/gateway/register` - A2: 心跳上报 `POST /api/gateway/heartbeat` - A3: 设备同步 `POST /api/gateway/sync/devices` - A4: 告警同步 `POST /api/gateway/sync/alarms` 2. [设备管理](#2-设备管理) - 区域树 `GET /api/DeviceManager/GetRegionTree` - 点位设备 `GET /api/DeviceManager/GetDevicesByPoint` 3. [定时任务](#3-定时任务) - 设备同步任务 `POST /api/task/syncDevices` - 心跳监控任务 `POST /api/task/heartbeatMonitor` - 实时轮询任务 `POST /api/task/realtimePoll` - 规则引擎任务 `POST /api/task/ruleEngine` 4. [错误代码](#4-错误代码) --- ## 1. A 组 — 网关注册通信 > A 组接口是 VolPro 向网关暴露的管理端点,由网关主动调用。所有 A 组使用 `[AllowAnonymous]` + `NodeToken` 二次认证,不走 VolPro JWT 体系。 > > **实现文件**: `Controllers/Warehouse/Partial/gateway_nodesController.cs` ### A1: 网关注册(Upsert) ``` POST /api/gateway/register ``` 网关启动时调用,注册自身节点信息。NodeCode 已存在则更新,不存在则插入。返回当前网关的已有设备列表供网关对比差异。 **请求头**: `Content-Type: application/json` **请求体 (GatewayRegisterRequest)**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `NodeCode` | string | ✅ | 网关节点编码,如 `gw-31ku` | | `Token` | string | ✅ | 认证令牌(由环境变量 `SECMPS_GATEWAY_TOKEN` 注入) | | `AdapterTypes` | string | ✅ | 适配器类型列表(逗号分隔),如 `Owl:main,MC4:31ku` | | `BaseUrl` | string | ✅ | 网关自身地址,如 `http://192.168.1.10:5100` | **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `nodeId` | int | 网关节点 ID(base_device.NodeId 外键) | | `devices` | array | 该网关已有的设备列表 | **devices[] 条目**: | 字段 | 类型 | 说明 | |------|------|------| | `deviceId` | int | 设备自增 ID | | `deviceName` | string | 设备名称 | | `adapterCode` | string | 适配器编码 | | `sourceId` | string | 子系统设备原始 ID | | `deviceCategory` | string | 设备种类 | | `deviceGroup` | string | 设备分组 | | `isParent` | string | 是否父设备("是"/"否") | | `isOnline` | string | 是否在线("在线"/"离线") | | `extraData` | string? | 扩展数据 JSON | **返回示例**: ```json { "nodeId": 1, "devices": [ { "deviceId": 10, "deviceName": "NVR-1", "adapterCode": "Owl:main", "sourceId": "nvr_001", "deviceCategory": "硬盘录像机", "deviceGroup": "视频设备", "isParent": "是", "isOnline": "在线" } ] } ``` **错误响应**: | HTTP | 说明 | |:---:|------| | 400 | `NodeCode` 或 `Token` 为空 | | 401 | `NodeToken` 不匹配(已有节点 Token 变更) | --- ### A2: 心跳上报 ``` POST /api/gateway/heartbeat ``` 网关每 15s 调用一次,更新 `LastHeartbeat` 字段。连续失败 ≥3 次(45s)后网关自动触发 A1+A3 重注册。 **请求体 (GatewayHeartbeatRequest)**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `NodeCode` | string | ✅ | 网关节点编码 | | `Token` | string | ✅ | 认证令牌 | **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `status` | string | 固定 `"ok"` | | `serverTime` | string | 服务器时间 (`yyyy-MM-dd HH:mm:ss`) | **错误响应**: | HTTP | 说明 | |:---:|------| | 400 | `NodeCode` 或 `Token` 为空 | | 401 | NodeCode+Token 组合不匹配 | --- ### A3: 设备数据同步 ``` POST /api/gateway/sync/devices ``` 网关每次设备变更后调用,将全量设备列表推送到 VolPro。采用字段分治策略:首次入库写全量,后续只更新网关字段。 **请求体 (SyncDevicesRequest)**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `NodeCode` | string | ✅ | 网关节点编码 | | `Token` | string | ✅ | 认证令牌 | | `Devices` | array | ✅ | 设备列表 | **Devices[].SyncDeviceItemDto**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `AdapterCode` | string | ✅ | 适配器编码 | | `SourceId` | string | ✅ | 子系统设备原始 ID | | `Name` | string? | ❌ | 设备名称 | | `Category` | string? | ❌ | 设备种类 | | `Group` | string? | ❌ | 设备分组 | | `IsParent` | bool | ❌ | 是否父设备 | | `ParentSourceId` | string? | ❌ | 父设备 SourceId(用于解析 ParentDeviceId) | | `IsOnline` | bool | ❌ | 是否在线 | | `IpAddress` | string? | ❌ | IP 地址 | | `Port` | int? | ❌ | 端口号 | | `ExtraDataJson` | string? | ❌ | 扩展数据 JSON | **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `added` | int | 新增设备数 | | `updated` | int | 更新设备数 | | `removed` | int | 固定 `0`(当前版本不移除下线设备) | **错误响应**: | HTTP | 说明 | |:---:|------| | 400 | `NodeCode` 或 `Token` 为空 | | 401 | NodeCode+Token 认证失败 | --- ### A4: 告警数据同步 ``` POST /api/gateway/sync/alarms ``` 网关检测到新告警后调用,推送告警列表到 VolPro。通过 `SourceAlarmId` 去重(同一告警不重复入库)。 **请求体 (SyncAlarmsRequest)**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `NodeCode` | string | ✅ | 网关节点编码 | | `Token` | string | ✅ | 认证令牌 | | `Alarms` | array | ✅ | 告警列表 | **Alarms[].SyncAlarmItemDto**: | 字段 | 类型 | 必填 | 说明 | |------|------|:--:|------| | `SourceAlarmId` | string | ✅ | 子系统告警唯一 ID(用于去重) | | `DeviceSourceId` | string | ✅ | 关联设备 SourceId(用于映射 DeviceId) | | `AdapterCode` | string | ✅ | 适配器编码 | | `Level` | string | ✅ | 告警等级:`提示`/`普通`/`重要`/`紧急` | | `Desc` | string | ✅ | 告警描述 | | `Value` | double? | ❌ | 告警实际值 | | `StartTime` | string | ✅ | 告警发生时间 | **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `added` | int | 新增告警数 | **错误响应**: | HTTP | 说明 | |:---:|------| | 400 | `NodeCode` 或 `Token` 为空 | | 401 | NodeCode+Token 认证失败 | --- ## 2. 设备管理 > **实现文件**: `Controllers/Warehouse/Partial/base_deviceController.cs` ### 区域树 ``` GET /api/DeviceManager/GetRegionTree ``` 返回 区域→点位 的层级结构,供管理端左侧树形控件使用。 **请求参数**: 无 **返回参数**: `TreeNode[]` | 字段 | 类型 | 说明 | |------|------|------| | `id` | string | 节点 ID(`r_{regionId}` 或 `p_{pointId}`) | | `label` | string | 节点显示名称 | | `type` | string | 节点类型:`region`(区域) 或 `point`(点位) | | `deviceCount` | int | 该节点下的设备数量 | | `children` | array? | 子节点列表(仅 region 节点有) | **返回示例**: ```json [ { "id": "r_1", "label": "库房A区", "type": "region", "deviceCount": 3, "children": [ { "id": "p_10", "label": "温湿度监测点1", "type": "point", "deviceCount": 5 }, { "id": "p_11", "label": "门禁点1", "type": "point", "deviceCount": 2 } ] } ] ``` --- ### 点位设备列表 ``` GET /api/DeviceManager/GetDevicesByPoint?pointId={pointId}&page={page}&size={size} ``` 获取指定点位下的设备列表(含子设备),支持分页。 **请求参数**: | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|:--:|------|------| | `pointId` | int | ✅ | — | 点位 ID | | `page` | int | ❌ | 1 | 页码 | | `size` | int | ❌ | 20 | 每页条数 | **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `items` | array | 设备列表 | | `total` | int | 总设备数 | **items[] 条目**: | 字段 | 类型 | 说明 | |------|------|------| | `deviceId` | int | 设备自增 ID | | `deviceName` | string | 设备名称 | | `adapterCode` | string | 适配器编码 | | `sourceId` | string | 子系统设备原始 ID | | `deviceCategory` | string | 设备种类 | | `deviceGroup` | string | 设备分组(`视频设备`/`IoT设备`/`门禁设备`) | | `isParent` | string | 是否父设备("是"/"否") | | `parentDeviceId` | int? | 父设备 ID | | `isOnline` | string | 是否在线("在线"/"离线") | | `ipAddress` | string? | IP 地址 | | `port` | int? | 端口号 | | `location` | string? | 位置描述 | | `extraData` | string? | 扩展数据 JSON | | `lastSyncTime` | DateTime? | 最后同步时间 | | `mapModelId` | string? | 3D 地图模型 ID | | `mapModelScale` | decimal? | 模型缩放比例 | | `mapModelRotation` | string? | 模型旋转参数 JSON | | `enable` | string | 启用状态("启用"/"停用") | --- ## 3. 定时任务 > VolPro 框架通过 `Sys_QuartzOptions` 表配置 URL+Cron 定时调用。每个端点加 `[ApiTask]` 属性以允许框架匿名调用。 > > **实现文件**: `Controllers/Warehouse/TaskController.cs` ### 设备同步任务 ``` POST /api/task/syncDevices ``` 遍历所有在线网关,触发全量设备同步至 VolPro。 **Cron**: `0 */5 * * * ?`(每 5 分钟) **请求参数**: 无 **返回参数**: | 字段 | 类型 | 说明 | |------|------|------| | `time` | DateTime | 执行时间 | | `status` | string | 固定 `"ok"` | **错误响应**: | HTTP | 说明 | |:---:|------| | 500 | `gateway_nodesService` 未注册 | --- ### 心跳监控任务 ``` POST /api/task/heartbeatMonitor ``` 扫描心跳超时 ≥30s 的网关节点,标记离线并级联标记该节点下所有设备离线。 **Cron**: `0/15 * * * * ?`(每 15 秒) **请求参数**: 无 **返回**: 同设备同步任务 --- ### 实时轮询任务 ``` POST /api/task/realtimePoll ``` 轮询所有在线 MC4 IoT 设备的实时值,写入 `iot_devicedata` 表。 **Cron**: `0/10 * * * * ?`(每 10 秒) **请求参数**: 无 **返回**: 同设备同步任务 --- ### 规则引擎任务 ``` POST /api/task/ruleEngine ``` 加载启用规则 → 从网关批量获取实时值 → 逐规则评估条件 → 触发动作(控制/告警/通知)。 **Cron**: `0/10 * * * * ?`(每 10 秒) **请求参数**: 无 **返回**: 同设备同步任务 **当前状态**: 桩实现。`RuleEngineService.EvaluateAllAsync()` 抛出 `NotImplementedException`,需先执行 SQL ALTER TABLE + 代码生成器。 --- ## 4. 错误代码 ### HTTP 状态码 | 状态码 | 含义 | 触发条件 | |:---:|------|------| | 200 | OK | 请求成功 | | 400 | Bad Request | 必填参数缺失(`NodeCode`/`Token`/`pointId`) | | 401 | Unauthorized | A 组接口 NodeToken 认证失败 | | 500 | Internal Server Error | 服务未注册或内部异常 | ### A 组认证错误 所有 A 组接口在认证失败时返回: ```json { "message": "认证失败:Token 无效" } ``` 或 ```json { "message": "认证失败" } ``` ### 定时任务错误 定时任务在服务未注册时返回: ```json { "error": "服务未注册: gateway_nodesService" } ``` --- > **接口总数**: 10 个端点(A 组 4 + 设备管理 2 + 定时任务 4) > **实现位置**: `api_sqlsugar/VolPro.WebApi/Controllers/Warehouse/`