全部网关代码添加详细中文注释
This commit is contained in:
@@ -6,19 +6,38 @@ using System.Text.Json;
|
||||
|
||||
namespace IntegrationGateway.Adapters.MC4;
|
||||
|
||||
/// <summary>
|
||||
/// MC4.0 动环监控子系统适配器。
|
||||
///
|
||||
/// 实现的能力接口:
|
||||
/// - IHasOwnDeviceTree:对象树(区域→设备层级)
|
||||
/// - IHasPoints:实时点位值读取 + 反向控制写值
|
||||
/// - IHasAlarms:告警查询、确认、结束
|
||||
///
|
||||
/// 限流:2 QPS(MC4.0 API 推荐值)
|
||||
/// 分页转换:网关 page/size ↔ MC4.0 skip/limit
|
||||
/// </summary>
|
||||
public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly Mc4AuthHelper _auth;
|
||||
/// <summary>令牌桶限流器(2 QPS)</summary>
|
||||
private readonly RateLimiter _limiter = new(2);
|
||||
|
||||
/// <summary>适配器编码,格式 "MC4:实例名"</summary>
|
||||
public string AdapterCode { get; }
|
||||
/// <summary>人类可读的适配器名称</summary>
|
||||
public string DisplayName => $"MC4 ({AdapterCode})";
|
||||
/// <summary>适配器能力声明</summary>
|
||||
public AdapterCapabilities Capabilities => new()
|
||||
{
|
||||
HasObjectTree = true, HasPoints = true, HasAlarms = true, AcceptsControl = true
|
||||
};
|
||||
|
||||
/// <summary>创建 Mc4Adapter 实例</summary>
|
||||
/// <param name="adapterCode">适配器编码</param>
|
||||
/// <param name="http">HttpClient 实例</param>
|
||||
/// <param name="baseUrl">MC4.0 服务地址</param>
|
||||
public Mc4Adapter(string adapterCode, HttpClient http, string baseUrl)
|
||||
{
|
||||
AdapterCode = adapterCode;
|
||||
@@ -26,8 +45,10 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
_auth = new Mc4AuthHelper(http, baseUrl);
|
||||
}
|
||||
|
||||
/// <summary>初始化适配器:获取 MC4.0 Token</summary>
|
||||
public async Task InitializeAsync() => await _auth.GetTokenAsync();
|
||||
|
||||
/// <summary>健康检查:尝试调用 MC4.0 认证接口确认可达性</summary>
|
||||
public async Task<bool> HealthCheckAsync()
|
||||
{
|
||||
try
|
||||
@@ -39,7 +60,14 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
// ─── IHasOwnDeviceTree ───
|
||||
// ═══════════════════════════════════════════
|
||||
// IHasOwnDeviceTree 实现
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
/// <summary>
|
||||
/// 获取 MC4.0 完整对象树。
|
||||
/// Type=1 的节点为区域,Type=2 的节点为设备。
|
||||
/// </summary>
|
||||
public async Task<List<DeviceTreeNode>> GetObjectTreeAsync()
|
||||
{
|
||||
await _limiter.WaitAsync();
|
||||
@@ -51,15 +79,24 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
return tree.Select(MapNode).ToList();
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 树节点 → DeviceTreeNode 映射</summary>
|
||||
private static DeviceTreeNode MapNode(Mc4TreeNode n) => new()
|
||||
{
|
||||
Id = n.Id, SourceId = n.Id.ToString(), Name = n.Name ?? n.Id.ToString(),
|
||||
Type = n.Type, ObjectType = n.ObjectType, Tag = n.Tag,
|
||||
Id = n.Id,
|
||||
SourceId = n.Id.ToString(),
|
||||
Name = n.Name ?? n.Id.ToString(),
|
||||
Type = n.Type,
|
||||
ObjectType = n.ObjectType,
|
||||
Tag = n.Tag,
|
||||
Option = n.Option ?? new Dictionary<string, object?>(),
|
||||
Children = n.Children?.Select(MapNode).ToList() ?? new()
|
||||
};
|
||||
|
||||
// ─── IHasPoints ───
|
||||
// ═══════════════════════════════════════════
|
||||
// IHasPoints 实现
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
/// <summary>获取指定设备的所有实时点位值</summary>
|
||||
public async Task<List<PointValue>> GetRealtimeValuesAsync(string sourceDeviceId)
|
||||
{
|
||||
await _limiter.WaitAsync();
|
||||
@@ -72,11 +109,15 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
var values = JsonSerializer.Deserialize<List<Mc4PointValue>>(json)!;
|
||||
return values.Select(v => new PointValue
|
||||
{
|
||||
SourceDeviceId = sourceDeviceId, PointIndex = v.Index,
|
||||
Value = v.Value, UpdateTime = v.Time != null ? DateTime.Parse(v.Time) : null, Interval = v.Interval
|
||||
SourceDeviceId = sourceDeviceId,
|
||||
PointIndex = v.Index,
|
||||
Value = v.Value,
|
||||
UpdateTime = v.Time != null ? DateTime.Parse(v.Time) : null,
|
||||
Interval = v.Interval
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
/// <summary>向指定设备的指定点位写入控制值</summary>
|
||||
public async Task SetPointValueAsync(string sourceDeviceId, int pointIndex, double value)
|
||||
{
|
||||
await _limiter.WaitAsync();
|
||||
@@ -86,7 +127,14 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
new StringContent(body, Encoding.UTF8, "application/json"));
|
||||
}
|
||||
|
||||
// ─── IHasAlarms ───
|
||||
// ═══════════════════════════════════════════
|
||||
// IHasAlarms 实现
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询告警列表。
|
||||
/// 内部完成 page/size → skip/limit 转换。
|
||||
/// </summary>
|
||||
public async Task<PagedResult<StandardAlarm>> GetAlarmsAsync(int page, int size, DateTime from, DateTime to,
|
||||
string? level = null, string? state = null)
|
||||
{
|
||||
@@ -98,7 +146,7 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
To = to.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
Skip = (page - 1) * size,
|
||||
Limit = size,
|
||||
Sort = 1
|
||||
Sort = 1 // 按时间降序
|
||||
});
|
||||
var resp = await client.PostAsync("/api/central/alarm/query",
|
||||
new StringContent(body, Encoding.UTF8, "application/json"));
|
||||
@@ -109,17 +157,21 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
{
|
||||
Items = result.List?.Select(a => new StandardAlarm
|
||||
{
|
||||
AlarmId = a.Id ?? "", DeviceId = a.Sid?.ToString(),
|
||||
AlarmId = a.Id ?? "",
|
||||
DeviceId = a.Sid?.ToString(),
|
||||
AdapterCode = AdapterCode,
|
||||
Level = MapAlarmLevel(a.Level), Title = a.Desc ?? "",
|
||||
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
|
||||
ActualValue = a.Soption?.Value,
|
||||
ThresholdValue = a.Eoption?.Value
|
||||
}).ToList() ?? new(),
|
||||
Total = result.Total
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>确认告警(同时写回 MC4.0)</summary>
|
||||
public async Task ConfirmAlarmAsync(string alarmId)
|
||||
{
|
||||
await _limiter.WaitAsync();
|
||||
@@ -129,6 +181,7 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
new StringContent(body, Encoding.UTF8, "application/json"));
|
||||
}
|
||||
|
||||
/// <summary>结束告警(同时写回 MC4.0)</summary>
|
||||
public async Task EndAlarmAsync(string alarmId)
|
||||
{
|
||||
await _limiter.WaitAsync();
|
||||
@@ -138,15 +191,29 @@ public class Mc4Adapter : IHasOwnDeviceTree, IHasPoints, IHasAlarms
|
||||
new StringContent(body, Encoding.UTF8, "application/json"));
|
||||
}
|
||||
|
||||
private static string MapAlarmLevel(int level) => level switch { 1 => "提示", 2 => "普通", 3 => "重要", 4 => "紧急", _ => "提示" };
|
||||
private static string MapAlarmState(int state) => state switch { 1 => "未确认", 2 => "已确认", 3 => "已结束", _ => "未确认" };
|
||||
/// <summary>MC4.0 告警等级数字 → 中文映射</summary>
|
||||
private static string MapAlarmLevel(int level) => level switch
|
||||
{
|
||||
1 => "提示", 2 => "普通", 3 => "重要", 4 => "紧急", _ => "提示"
|
||||
};
|
||||
|
||||
/// <summary>MC4.0 告警状态数字 → 中文映射</summary>
|
||||
private static string MapAlarmState(int state) => state switch
|
||||
{
|
||||
1 => "未确认", 2 => "已确认", 3 => "已结束", _ => "未确认"
|
||||
};
|
||||
}
|
||||
|
||||
// ─── MC4 JSON Models ───
|
||||
// ═══════════════════════════════════════════
|
||||
// MC4.0 JSON 反序列化模型(内部使用)
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
/// <summary>MC4.0 对象树节点</summary>
|
||||
public class Mc4TreeNode
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
/// <summary>节点类型:1=区域,2=设备</summary>
|
||||
public int Type { get; set; }
|
||||
public int ObjectType { get; set; }
|
||||
public string? Tag { get; set; }
|
||||
@@ -154,6 +221,7 @@ public class Mc4TreeNode
|
||||
public List<Mc4TreeNode>? Children { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 点位值</summary>
|
||||
public class Mc4PointValue
|
||||
{
|
||||
public int Id { get; set; }
|
||||
@@ -163,25 +231,32 @@ public class Mc4PointValue
|
||||
public int Interval { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 告警查询请求体</summary>
|
||||
public class Mc4AlarmQuery
|
||||
{
|
||||
public string? Sid { get; set; }
|
||||
public string From { get; set; } = "";
|
||||
public string To { get; set; } = "";
|
||||
/// <summary>跳过的记录数(= (page-1)*size)</summary>
|
||||
public int Skip { get; set; }
|
||||
/// <summary>每页条数</summary>
|
||||
public int Limit { get; set; }
|
||||
/// <summary>排序方式:1=时间降序</summary>
|
||||
public int Sort { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 告警查询响应</summary>
|
||||
public class Mc4AlarmQueryResult
|
||||
{
|
||||
public int Total { get; set; }
|
||||
public List<Mc4AlarmItem>? List { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 告警条目</summary>
|
||||
public class Mc4AlarmItem
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
/// <summary>设备 SID</summary>
|
||||
public int? Sid { get; set; }
|
||||
public string? Desc { get; set; }
|
||||
public string? EngDesc { get; set; }
|
||||
@@ -192,10 +267,13 @@ public class Mc4AlarmItem
|
||||
public string? Ctime { get; set; }
|
||||
public string? Cuser { get; set; }
|
||||
public int Type { get; set; }
|
||||
/// <summary>告警触发时阈值信息</summary>
|
||||
public Mc4Option? Soption { get; set; }
|
||||
/// <summary>告警结束时阈值信息</summary>
|
||||
public Mc4Option? Eoption { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>MC4.0 告警阈值信息</summary>
|
||||
public class Mc4Option
|
||||
{
|
||||
public double? Value { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user