全部网关代码添加详细中文注释
This commit is contained in:
@@ -2,9 +2,21 @@ using IntegrationGateway.Core.Abstractions;
|
||||
using IntegrationGateway.Core.Infrastructure;
|
||||
using IntegrationGateway.Core.Models;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// IntegrationGateway 宿主启动程序
|
||||
//
|
||||
// 职责:
|
||||
// 1. 注册 IHttpClientFactory(连接池复用)
|
||||
// 2. 创建并注册 OwlAdapter + MC4Adapter
|
||||
// 3. 并行初始化所有适配器
|
||||
// 4. 注册 14 个 B 组 REST 端点
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// 注册 IHttpClientFactory
|
||||
// ── 注册 HttpClient 工厂 ──
|
||||
// 命名客户端 "VolPro":用于调用 Vol.Pro A 组接口和适配器内部 HTTP 请求
|
||||
// 连接池:最多 10 个并发连接,5 分钟生命周期
|
||||
builder.Services.AddHttpClient("VolPro", c =>
|
||||
{
|
||||
c.Timeout = TimeSpan.FromSeconds(30);
|
||||
@@ -17,20 +29,20 @@ builder.Services.AddHttpClient("VolPro", c =>
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// 读取配置
|
||||
// ── 读取配置 ──
|
||||
var gwCfg = app.Configuration.GetSection("Gateway");
|
||||
var owlCfg = app.Configuration.GetSection("Owl");
|
||||
var mc4Cfg = app.Configuration.GetSection("MC4");
|
||||
|
||||
// 创建适配器注册中心
|
||||
// ── 创建适配器注册中心 ──
|
||||
var registry = new AdapterRegistry();
|
||||
|
||||
// 创建 VolPro 客户端工厂
|
||||
// ── 创建 Vol.Pro 客户端工厂(用于 A1-A4 回调) ──
|
||||
var volProUrl = gwCfg["VolProBaseUrl"] ?? "http://localhost:9100";
|
||||
var httpFactory = app.Services.GetRequiredService<IHttpClientFactory>();
|
||||
var clientFactory = new GatewayClientFactory(httpFactory, volProUrl);
|
||||
|
||||
// 注册 OwlAdapter
|
||||
// ── 注册 OwlAdapter ──
|
||||
var owlHttp = app.Services.GetRequiredService<IHttpClientFactory>().CreateClient("VolPro");
|
||||
var owlAdapter = new IntegrationGateway.Adapters.Owl.OwlAdapter(
|
||||
"Owl:main", owlHttp,
|
||||
@@ -40,7 +52,7 @@ var owlAdapter = new IntegrationGateway.Adapters.Owl.OwlAdapter(
|
||||
);
|
||||
registry.Register(owlAdapter);
|
||||
|
||||
// 注册 MC4Adapter
|
||||
// ── 注册 MC4Adapter ──
|
||||
var mc4Http = app.Services.GetRequiredService<IHttpClientFactory>().CreateClient("VolPro");
|
||||
var mc4Adapter = new IntegrationGateway.Adapters.MC4.Mc4Adapter(
|
||||
"MC4:31ku", mc4Http,
|
||||
@@ -48,13 +60,16 @@ var mc4Adapter = new IntegrationGateway.Adapters.MC4.Mc4Adapter(
|
||||
);
|
||||
registry.Register(mc4Adapter);
|
||||
|
||||
// 并行初始化适配器
|
||||
// ── 并行初始化所有适配器 ──
|
||||
await registry.InitializeAllAsync();
|
||||
Console.WriteLine($"[Gateway] {registry.All.Count} adapter(s) registered");
|
||||
Console.WriteLine($"[Gateway] {registry.All.Count} 个适配器已注册");
|
||||
|
||||
// ═══ B 组路由 ═══
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// B 组路由(管理端 / Vol.Pro → 网关)
|
||||
// 所有路由通过适配器编码查找对应适配器,按能力接口分发请求
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
// B1: 健康检查
|
||||
// B1: 健康检查 — 返回所有适配器的健康状态和能力声明
|
||||
app.MapGet("/api/gateway/health", async () =>
|
||||
{
|
||||
var results = new List<object>();
|
||||
@@ -67,34 +82,34 @@ app.MapGet("/api/gateway/health", async () =>
|
||||
return Results.Ok(results);
|
||||
});
|
||||
|
||||
// B2: 设备列表
|
||||
// B2: 设备列表 — 分页获取扁平设备列表(Owl/门禁/道闸)
|
||||
app.MapGet("/api/gateway/devices", async (string adapter, int page, int size, string? keyword) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasFlatDevices>(adapter);
|
||||
if (a == null) return Results.NotFound(new { error = "ADAPTER_NOT_FOUND", message = $"Adapter '{adapter}' not found or does not support flat devices" });
|
||||
if (a == null) return Results.NotFound(new { error = "ADAPTER_NOT_FOUND", message = $"适配器 '{adapter}' 不存在或不支持扁平设备列表" });
|
||||
return Results.Ok(await a.GetDevicesAsync(page, size, keyword));
|
||||
});
|
||||
|
||||
// B3: 对象树
|
||||
// B3: 对象树 — 获取层级对象树(MC4.0)
|
||||
app.MapGet("/api/gateway/tree", async (string adapter) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasOwnDeviceTree>(adapter);
|
||||
if (a == null) return Results.NotFound(new { error = "CAPABILITY_NOT_SUPPORTED", message = $"Tree not supported by '{adapter}'" });
|
||||
if (a == null) return Results.NotFound(new { error = "CAPABILITY_NOT_SUPPORTED", message = $"适配器 '{adapter}' 不支持对象树" });
|
||||
return Results.Ok(await a.GetObjectTreeAsync());
|
||||
});
|
||||
|
||||
// B6a: 实时流
|
||||
// B6a: 实时取流 — 获取视频通道的实时流地址
|
||||
app.MapGet("/api/gateway/streams/{adapter}/{deviceId}/live", async (string adapter, string deviceId) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasStreams>(adapter);
|
||||
if (a == null) return Results.NotFound(new { error = "CAPABILITY_NOT_SUPPORTED", message = $"Streams not supported by '{adapter}'" });
|
||||
if (a == null) return Results.NotFound(new { error = "CAPABILITY_NOT_SUPPORTED", message = $"适配器 '{adapter}' 不支持视频取流" });
|
||||
var result = await a.GetLiveUrlAsync(deviceId);
|
||||
return result.WsFlv == null && result.Hls == null
|
||||
? Results.Problem("No stream URL returned", statusCode: 502)
|
||||
? Results.Problem("未获取到流地址", statusCode: 502)
|
||||
: Results.Ok(result);
|
||||
});
|
||||
|
||||
// B6b: 回放
|
||||
// B6b: 录像回放 — 获取历史录像 HLS 地址
|
||||
app.MapGet("/api/gateway/streams/{adapter}/{deviceId}/playback", async (string adapter, string deviceId, DateTime start, DateTime end) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasStreams>(adapter);
|
||||
@@ -102,7 +117,7 @@ app.MapGet("/api/gateway/streams/{adapter}/{deviceId}/playback", async (string a
|
||||
return Results.Ok(await a.GetPlaybackUrlAsync(deviceId, start, end));
|
||||
});
|
||||
|
||||
// 截图
|
||||
// 截图 — 获取通道实时截图
|
||||
app.MapPost("/api/gateway/streams/{adapter}/{deviceId}/snapshot", async (string adapter, string deviceId) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasStreams>(adapter);
|
||||
@@ -110,7 +125,7 @@ app.MapPost("/api/gateway/streams/{adapter}/{deviceId}/snapshot", async (string
|
||||
return Results.Ok(await a.GetSnapshotAsync(deviceId));
|
||||
});
|
||||
|
||||
// B7: PTZ
|
||||
// B7: 云台控制 — continuous 方向移动 + stop
|
||||
app.MapPost("/api/gateway/streams/{adapter}/{deviceId}/ptz", async (string adapter, string deviceId, PtzRequest req) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasStreams>(adapter);
|
||||
@@ -120,7 +135,7 @@ app.MapPost("/api/gateway/streams/{adapter}/{deviceId}/ptz", async (string adapt
|
||||
return Results.Ok();
|
||||
});
|
||||
|
||||
// B4: 实时点值
|
||||
// B4: 实时点位值 — 获取 IoT 设备测点当前读数
|
||||
app.MapGet("/api/gateway/realtime/{adapter}/{deviceId}", async (string adapter, string deviceId) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasPoints>(adapter);
|
||||
@@ -128,7 +143,7 @@ app.MapGet("/api/gateway/realtime/{adapter}/{deviceId}", async (string adapter,
|
||||
return Results.Ok(await a.GetRealtimeValuesAsync(deviceId));
|
||||
});
|
||||
|
||||
// B5: 控制
|
||||
// B5: 设备控制 — 向 IoT 设备下发控制指令
|
||||
app.MapPost("/api/gateway/realtime/{adapter}/control", async (string adapter, ControlRequest req) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasPoints>(adapter);
|
||||
@@ -137,7 +152,7 @@ app.MapPost("/api/gateway/realtime/{adapter}/control", async (string adapter, Co
|
||||
return Results.Ok();
|
||||
});
|
||||
|
||||
// B8: 告警查询
|
||||
// B8: 告警查询 — 分页获取告警列表
|
||||
app.MapGet("/api/gateway/alarms/{adapter}", async (string adapter, int page, int size, DateTime from, DateTime to, string? level, string? state) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasAlarms>(adapter);
|
||||
@@ -145,7 +160,7 @@ app.MapGet("/api/gateway/alarms/{adapter}", async (string adapter, int page, int
|
||||
return Results.Ok(await a.GetAlarmsAsync(page, size, from, to, level, state));
|
||||
});
|
||||
|
||||
// B9: 告警确认
|
||||
// B9: 告警确认 — 确认告警并写回子系统
|
||||
app.MapPost("/api/gateway/alarms/{adapter}/{alarmId}/confirm", async (string adapter, string alarmId) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasAlarms>(adapter);
|
||||
@@ -154,7 +169,7 @@ app.MapPost("/api/gateway/alarms/{adapter}/{alarmId}/confirm", async (string ada
|
||||
return Results.Ok();
|
||||
});
|
||||
|
||||
// 告警结束
|
||||
// 告警结束 — 结束告警并写回子系统
|
||||
app.MapPost("/api/gateway/alarms/{adapter}/{alarmId}/end", async (string adapter, string alarmId) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasAlarms>(adapter);
|
||||
@@ -163,7 +178,7 @@ app.MapPost("/api/gateway/alarms/{adapter}/{alarmId}/end", async (string adapter
|
||||
return Results.Ok();
|
||||
});
|
||||
|
||||
// 录像
|
||||
// 录像查询 — 分页获取录像文件列表
|
||||
app.MapGet("/api/gateway/recordings/{adapter}/{deviceId}", async (string adapter, string deviceId, DateTime start, DateTime end, int page, int size) =>
|
||||
{
|
||||
var a = registry.FindByCode<IHasRecordings>(adapter);
|
||||
@@ -171,27 +186,39 @@ app.MapGet("/api/gateway/recordings/{adapter}/{deviceId}", async (string adapter
|
||||
return Results.Ok(await a.GetRecordingsAsync(deviceId, start, end, page, size));
|
||||
});
|
||||
|
||||
// B3: 手动同步
|
||||
// B3: 手动同步 — 触发适配器全量设备同步
|
||||
app.MapPost("/api/gateway/devices/sync", async (string adapter) =>
|
||||
{
|
||||
var a = registry.FindByCode<IGatewayAdapter>(adapter);
|
||||
if (a == null) return Results.NotFound(new { error = "ADAPTER_NOT_FOUND" });
|
||||
// 根据适配器能力触发对应同步
|
||||
// 根据适配器能力触发对应同步逻辑
|
||||
if (a is IHasOwnDeviceTree tree)
|
||||
{
|
||||
var obj = await tree.GetObjectTreeAsync();
|
||||
return Results.Ok(new { nodeCount = obj.Count, message = "tree synced" });
|
||||
return Results.Ok(new { nodeCount = obj.Count, message = "对象树同步完成" });
|
||||
}
|
||||
if (a is IHasFlatDevices flat)
|
||||
{
|
||||
var dev = await flat.GetDevicesAsync(1, 1000);
|
||||
return Results.Ok(new { deviceCount = dev.Total, message = "devices synced" });
|
||||
return Results.Ok(new { deviceCount = dev.Total, message = "设备列表同步完成" });
|
||||
}
|
||||
return Results.Ok(new { message = "no sync needed" });
|
||||
return Results.Ok(new { message = "无需同步" });
|
||||
});
|
||||
|
||||
app.Run();
|
||||
|
||||
// 请求 DTO
|
||||
// ═══════════════════════════════════════════════
|
||||
// B 组请求 DTO
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
/// <summary>云台控制请求</summary>
|
||||
/// <param name="Direction">方向:up/down/left/right/zoom_in/zoom_out/stop</param>
|
||||
/// <param name="Action">动作类型:continuous 或 stop</param>
|
||||
/// <param name="Speed">速度 0.0-1.0</param>
|
||||
record PtzRequest(string? Direction, string Action, float Speed);
|
||||
|
||||
/// <summary>设备控制请求</summary>
|
||||
/// <param name="DeviceId">目标设备 SourceId</param>
|
||||
/// <param name="PointIndex">点位索引</param>
|
||||
/// <param name="Value">目标值</param>
|
||||
record ControlRequest(string? DeviceId, int PointIndex, double Value);
|
||||
|
||||
Reference in New Issue
Block a user