# 网关 MC4 模块整改方案 v1.0 > **版本**: 1.0 > **日期**: 2026-06-03 > **基准**: `doc/设计文档/网关MC4模块检查报告20260603.md` --- ## 1. 整改总览 | 步骤 | 优先级 | 内容 | 文件 | 预计 | |:---:|:---:|------|------|:---:| | M1 | 🔴 P0 | Mc4AuthHelper 认证修复 | Mc4AuthHelper.cs + appsettings | 1h | | M2 | 🟠 P1 | 批量点位查询 | Mc4Adapter.cs | 30min | | M3 | 🟡 P2 | 历史告警查询 | Mc4Adapter.cs | 30min | | M4 | 🟡 P2 | B4-batch 路由改用 native batch | Program.cs | 15min | | M5 | 验证 | 编译 + 联调 | — | 30min | | **合计** | — | — | **4 文件** | **~3h** | --- ## 2. 步骤 M1: Mc4AuthHelper 认证修复(预计 1h) ### 2.1 问题 ```csharp // 当前: 调 /conf/get (返回 { "encrypt": true }),误读为 Token var resp = await _http.PostAsync($"{_baseUrl}/api/central/auth/conf/get", null); var result = JsonSerializer.Deserialize(json); _token = result?.Token ?? ""; // Token 始终为 null ``` ### 2.2 MC4.0 实际认证流程 ``` 1. POST /api/central/auth/conf/get → { "encrypt": true/false } 2. 若 encrypt=true → 密码 MD5(原始密码) 3. POST /api/central/auth/login { "account": "admin", "password": "md5或原始密码" } → { "token": "xxx", "id": 0, "account": "admin", "name": "管理员" } ``` ### 2.3 修改后的 Mc4AuthHelper ```csharp public class Mc4AuthHelper { private readonly HttpClient _http; private readonly string _baseUrl; private readonly string _account; private readonly string _password; private string? _token; private DateTime _tokenExpiry = DateTime.MinValue; private bool? _needMd5; public Mc4AuthHelper(HttpClient http, string baseUrl, string account, string password) { _http = http; _baseUrl = baseUrl.TrimEnd('/'); _account = account; _password = password; } public async Task GetTokenAsync() { if (!string.IsNullOrEmpty(_token) && DateTime.UtcNow < _tokenExpiry) return _token; // 1. 获取加密配置 if (!_needMd5.HasValue) { var confResp = await _http.PostAsync($"{_baseUrl}/api/central/auth/conf/get", null); if (confResp.IsSuccessStatusCode) { var confJson = await confResp.Content.ReadAsStringAsync(); var conf = JsonSerializer.Deserialize(confJson); _needMd5 = conf?.Encrypt ?? false; } else { _needMd5 = false; // 失败时假定不需要加密 } } // 2. 登录获取 Token var pwd = _needMd5 == true ? ComputeMd5(_password) : _password; var loginBody = JsonSerializer.Serialize(new { account = _account, password = pwd }); var resp = await _http.PostAsync($"{_baseUrl}/api/central/auth/login", new StringContent(loginBody, Encoding.UTF8, "application/json")); resp.EnsureSuccessStatusCode(); var json = await resp.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(json) ?? throw new Exception("MC4 登录失败"); _token = result.Token ?? ""; _tokenExpiry = DateTime.UtcNow.AddHours(7); // 保守估计 8h return _token; } public async Task GetAuthenticatedClientAsync() { var token = await GetTokenAsync(); var client = new HttpClient { BaseAddress = new Uri(_baseUrl) }; if (!string.IsNullOrEmpty(token)) client.DefaultRequestHeaders.Add("token", token); return client; } public void Invalidate() => _token = null; private static string ComputeMd5(string input) { /* MD5 实现 or use System.Security.Cryptography */ } private class Mc4ConfResponse { public bool? Encrypt { get; set; } } private class Mc4LoginResponse { public string? Token { get; set; } public int Id { get; set; } public string? Account { get; set; } } } ``` ### 2.4 构造函数签名变更 ```csharp // 旧: public Mc4AuthHelper(HttpClient http, string baseUrl) // 新: public Mc4AuthHelper(HttpClient http, string baseUrl, string account, string password) ``` ### 2.5 Mc4Adapter 构造函数变更 ```csharp // 旧: public Mc4Adapter(string adapterCode, HttpClient http, string baseUrl) { _auth = new Mc4AuthHelper(http, baseUrl); } // 新: public Mc4Adapter(string adapterCode, HttpClient http, string baseUrl, string account = "admin", string password = "admin") { _auth = new Mc4AuthHelper(http, baseUrl, account, password); } ``` ### 2.6 Program.cs 注册变更 ```csharp // 旧: new Mc4Adapter(code, http, m.BaseUrl) // 新: new Mc4Adapter(code, http, m.BaseUrl, // m.Username ?? "admin", m.Password ?? "admin") ``` ### 2.7 Mc4Config 增加字段 ```csharp public class Mc4Config { public string? InstanceName { get; set; } public string BaseUrl { get; set; } = ""; public string Username { get; set; } = "admin"; // 新增 public string Password { get; set; } = "admin"; // 新增 } ``` ### 2.8 appsettings.json 更新 ```json "MC4": [ { "InstanceName": "31ku", "BaseUrl": "http://localhost:3000", "Username": "admin", "Password": "your_mc4_password" } ] ``` ### 2.9 编译验证 `dotnet build gateway/IntegrationGateway.slnx` → 0 错误。 > **M1 提交点**: `Fix-M1: Mc4AuthHelper 认证修复 conf/get→login + account/password支持` --- ## 3. 步骤 M2: 批量点位查询(预计 30min) ### 3.1 文件 `gateway/src/IntegrationGateway.Adapters.MC4/Mc4Adapter.cs` ### 3.2 新增方法 ```csharp /// 批量获取多个设备的实时点位值(MC4.0 原生 multi/value/get) public async Task>> GetMultiRealtimeValuesAsync(List deviceIds) { await _limiter.WaitAsync(); var client = await _auth.GetAuthenticatedClientAsync(); var body = JsonSerializer.Serialize(new { ids = deviceIds }); var resp = await client.PostAsync("/api/central/point/multi/value/get", new StringContent(body, Encoding.UTF8, "application/json")); resp.EnsureSuccessStatusCode(); var json = await resp.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>>(json)!; return result; } ``` ### 3.3 编译验证 `dotnet build` → 0 错误。 > **M2 提交点**: `Fix-M2: MC4 批量点位查询 GetMultiRealtimeValuesAsync` --- ## 4. 步骤 M3: 历史告警查询(预计 30min) ### 4.1 新增 DTO ```csharp /// MC4.0 历史告警查询请求 public class Mc4HisAlarmQuery { public string From { get; set; } = ""; public string To { get; set; } = ""; public int Skip { get; set; } public int Limit { get; set; } public int Sort { get; set; } = 1; } ``` ### 4.2 新增方法 ```csharp /// 查询 MC4.0 历史告警(已恢复的告警) public async Task> GetHisAlarmsAsync(int page, int size, DateTime from, DateTime to) { await _limiter.WaitAsync(); var client = await _auth.GetAuthenticatedClientAsync(); var body = JsonSerializer.Serialize(new Mc4HisAlarmQuery { From = from.ToString("yyyy-MM-dd HH:mm:ss"), To = to.ToString("yyyy-MM-dd HH:mm:ss"), Skip = (page - 1) * size, Limit = size, Sort = 1 }); var resp = await client.PostAsync("/api/central/his_alarm/query", new StringContent(body, Encoding.UTF8, "application/json")); resp.EnsureSuccessStatusCode(); var json = await resp.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(json)!; return new PagedResult { Items = (result.List ?? new()).Select(MapAlarmItem).ToList(), Total = result.Total }; } private StandardAlarm MapAlarmItem(Mc4AlarmItem a) => new() { AlarmId = a.Id ?? "", AdapterCode = AdapterCode, Level = MapAlarmLevel(a.Level), Title = a.Desc ?? "", OccurTime = DateTime.TryParse(a.Stime, out var st) ? st : DateTime.MinValue, Status = MapAlarmState(a.State), ActualValue = a.Soption?.Value, ThresholdValue = a.Eoption?.Value }; ``` ### 4.3 编译验证 `dotnet build` → 0 错误。 > **M3 提交点**: `Fix-M3: MC4 历史告警查询 GetHisAlarmsAsync` --- ## 5. 步骤 M4: B4-batch 路由优化(预计 15min) ### 5.1 修改 `gateway/src/IntegrationGateway.Host/Program.cs` B4-batch 路由改用 MC4 原生批量接口: ```csharp // B4-batch 改用 MC4 原生 multi/value/get app.MapPost("/api/gateway/realtime/{adapter}/batch", async (string adapter, BatchRealtimeRequest req) => { var a = registry.FindByCode(adapter); if (a == null) return Results.NotFound(); if (a is Mc4Adapter mc4 && req.DeviceIds?.Count > 0) { // MC4.0 原生批量接口 var intIds = req.DeviceIds.Select(int.Parse).ToList(); var multi = await mc4.GetMultiRealtimeValuesAsync(intIds); return Results.Ok(multi); } // 其他适配器 fallback var results = new Dictionary>(); foreach (var id in req.DeviceIds ?? new()) try { results[id] = await a.GetRealtimeValuesAsync(id); } catch { } return Results.Ok(results); }); ``` ### 5.2 编译验证 `dotnet build` → 0 错误。 > **M4 提交点**: `Fix-M4: B4-batch 优化 MC4原生批量接口` --- ## 6. 步骤 M5: 编译验证 + 联调 - [ ] `dotnet build gateway/IntegrationGateway.slnx` → 0 错误 0 警告 - [ ] MC4 appsettings.json 填入真实 `Username/Password` - [ ] 网关启动 → A1 注册 → A3 同步 MC4 设备树 - [ ] B4-batch 调 `multi/value/get` 返回批量值 - [ ] 告警查询 `/alarms/MC4:31ku` 有数据 - [ ] Mc4AuthHelper Token 非空 → 登录流程正常 > **M5 提交点**: `Fix-M5: MC4整改全量编译验证通过` --- ## 7. 改动文件汇总 | 步骤 | 文件 | 改动 | |:---:|------|------| | M1 | `Mc4AuthHelper.cs` | 重写认证流程: conf/get → login | | M1 | `Mc4Adapter.cs` | 构造函数加 account/password | | M1 | `Program.cs` | Mc4Adapter 构造传 Username/Password | | M1 | `appsettings.json` | MC4 数组加 Username/Password | | M2 | `Mc4Adapter.cs` | 新增 GetMultiRealtimeValuesAsync | | M3 | `Mc4Adapter.cs` | 新增 GetHisAlarmsAsync + DTO | | M4 | `Program.cs` | B4-batch 优化 MC4 原生批量 |