917 lines
34 KiB
C#
Raw Normal View History

2025-07-31 18:51:24 +08:00
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using YunDa.Server.Communication.Framework;
using YunDa.Server.ISMSTcp.Domain;
2025-07-31 18:51:24 +08:00
using YunDa.Server.ISMSTcp.Interfaces;
using YunDa.Server.ISMSTcp.Models;
using YunDa.Server.ISMSTcp.Services;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
using YunDa.SOMS.Redis.Repositories;
2025-07-31 18:51:24 +08:00
namespace YunDa.Server.ISMSTcp.Controllers
{
/// <summary>
/// 查询API控制器
/// </summary>
[ApiController]
[Route("api")]
public class QueryController : ControllerBase
{
private readonly ILogger<QueryController> _logger;
private readonly IQueryService _queryService;
private readonly IWebSocketMessageBroadcaster _webSocketBroadcaster;
private readonly IRedisRepository<ProtectionDeviceCommInfoOutput, string> _protectionDeviceCommInfoOutputredisRepository;
private readonly WebApiRequest _webApiRequest;
private readonly ITcpClient _tcpClient;
private readonly TelemeteringHandle _telemeteringHandle;
2025-07-31 18:51:24 +08:00
/// <summary>
/// 构造函数
/// </summary>
/// <param name="logger">日志记录器</param>
/// <param name="queryService">查询服务</param>
/// <param name="webSocketBroadcaster">WebSocket消息广播器</param>
/// <param name="protectionDeviceCommInfoOutputredisRepository">保护装置通信信息Redis仓储</param>
/// <param name="webApiRequest">Web API请求服务</param>
/// <param name="tcpClient">TCP客户端</param>
/// <param name="telemeteringHandle">遥测数据处理服务</param>
public QueryController(
ILogger<QueryController> logger,
IQueryService queryService,
IRedisRepository<ProtectionDeviceCommInfoOutput, string> protectionDeviceCommInfoOutputredisRepository,
IWebSocketMessageBroadcaster webSocketBroadcaster,
WebApiRequest webApiRequest,
ITcpClient tcpClient,
TelemeteringHandle telemeteringHandle)
2025-07-31 18:51:24 +08:00
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_queryService = queryService ?? throw new ArgumentNullException(nameof(queryService));
_protectionDeviceCommInfoOutputredisRepository = protectionDeviceCommInfoOutputredisRepository ?? throw new ArgumentNullException(nameof(protectionDeviceCommInfoOutputredisRepository));
_webSocketBroadcaster = webSocketBroadcaster ?? throw new ArgumentNullException(nameof(webSocketBroadcaster));
_webApiRequest = webApiRequest ?? throw new ArgumentNullException(nameof(webApiRequest));
_tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
_telemeteringHandle = telemeteringHandle ?? throw new ArgumentNullException(nameof(telemeteringHandle));
2025-07-31 18:51:24 +08:00
}
/// <summary>
/// 处理查询请求
/// </summary>
/// <param name="dz">定值参数</param>
/// <param name="faultRpt">故障报告参数</param>
/// <param name="waveCfg">波形配置参数</param>
/// <param name="waveDat">波形文件参数</param>
/// <param name="version">装置版本参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
[HttpGet]
public async Task<IActionResult> ProcessQuery(
[FromQuery] string? dz = null,
[FromQuery] string? faultRpt = null,
[FromQuery] string? waveCfg = null,
[FromQuery] string? waveDat = null,
[FromQuery] string? version = null,
CancellationToken cancellationToken = default)
{
try
{
LogQueryRequest(dz, faultRpt, waveCfg, waveDat, version);
2025-07-31 18:51:24 +08:00
var result = await DetermineAndExecuteQueryAsync(dz, faultRpt, waveCfg, waveDat, version, cancellationToken);
2025-07-31 18:51:24 +08:00
return CreateActionResult(result);
}
catch (OperationCanceledException)
{
return HandleOperationCanceled();
}
catch (Exception ex)
{
return HandleUnexpectedException(ex);
}
}
/// <summary>
/// 记录查询请求日志
/// </summary>
/// <param name="dz">定值参数</param>
/// <param name="faultRpt">故障报告参数</param>
/// <param name="waveCfg">波形配置参数</param>
/// <param name="waveDat">波形文件参数</param>
/// <param name="version">装置版本参数</param>
private void LogQueryRequest(string? dz, string? faultRpt, string? waveCfg, string? waveDat, string? version)
{
_logger.LogWarning("收到查询请求 - dz:{Dz}, faultRpt:{FaultRpt}, waveCfg:{WaveCfg}, waveDat:{WaveDat}, version:{Version}",
dz, faultRpt, waveCfg, waveDat, version);
}
/// <summary>
/// 确定查询类型并执行相应的查询
/// </summary>
/// <param name="dz">定值参数</param>
/// <param name="faultRpt">故障报告参数</param>
/// <param name="waveCfg">波形配置参数</param>
/// <param name="waveDat">波形文件参数</param>
/// <param name="version">装置版本参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> DetermineAndExecuteQueryAsync(
string? dz,
string? faultRpt,
string? waveCfg,
string? waveDat,
string? version,
CancellationToken cancellationToken)
{
//_logger.LogWarning("收到查询命令: {Item}", yxItem?.ToString());
if (!string.IsNullOrEmpty(dz))
{
return await ExecuteSettingValueQueryAsync(dz, cancellationToken);
}
else if (!string.IsNullOrEmpty(faultRpt))
{
return await ExecuteFaultReportQueryAsync(faultRpt, cancellationToken);
}
else if (!string.IsNullOrEmpty(waveCfg))
{
return await ExecuteWaveConfigQueryAsync(waveCfg, cancellationToken);
}
else if (!string.IsNullOrEmpty(waveDat))
{
return await ExecuteWaveDataQueryAsync(waveDat, cancellationToken);
}
else if (!string.IsNullOrEmpty(version))
{
return await ExecuteVersionQueryAsync(version, cancellationToken);
}
else
{
return WebResult<object>.InvalidParameter();
}
}
/// <summary>
/// 执行定值查询
/// </summary>
/// <param name="parameter">查询参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> ExecuteSettingValueQueryAsync(string parameter, CancellationToken cancellationToken)
{
return await _queryService.ProcessRequestAsync(parameter, "dz", "定值", cancellationToken);
}
/// <summary>
/// 执行故障报告查询
/// </summary>
/// <param name="parameter">查询参数格式GetFaultRptByTime|2025-08-20 00:00|2025-08-20 23:59</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> ExecuteFaultReportQueryAsync(string parameter, CancellationToken cancellationToken)
{
return await _queryService.ProcessRequestAsync(parameter, "faultRpt", "故障报告", cancellationToken);
}
/// <summary>
/// 执行波形配置查询
/// </summary>
/// <param name="parameter">查询参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> ExecuteWaveConfigQueryAsync(string parameter, CancellationToken cancellationToken)
{
return await _queryService.ProcessRequestAsync(parameter, "waveCfg", "波形配置", cancellationToken);
}
/// <summary>
/// 执行波形文件查询
/// </summary>
/// <param name="parameter">查询参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> ExecuteWaveDataQueryAsync(string parameter, CancellationToken cancellationToken)
{
return await _queryService.ProcessRequestAsync(parameter, "waveDat", "波形文件", cancellationToken);
}
/// <summary>
/// 执行装置版本查询
/// </summary>
/// <param name="parameter">查询参数</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>查询结果</returns>
private async Task<WebResult<object>> ExecuteVersionQueryAsync(string parameter, CancellationToken cancellationToken)
{
return await _queryService.ProcessRequestAsync(parameter, "version", "装置版本", cancellationToken);
}
/// <summary>
/// 创建ActionResult响应
/// </summary>
/// <param name="result">查询结果</param>
/// <returns>ActionResult</returns>
private IActionResult CreateActionResult(WebResult<object> result)
{
return StatusCode(result.StatusCode, result);
}
/// <summary>
/// 处理操作取消异常
/// </summary>
/// <returns>ActionResult</returns>
private IActionResult HandleOperationCanceled()
{
_logger.LogWarning("查询请求被取消");
return StatusCode(504, "请求超时");
}
/// <summary>
/// 处理未预期的异常
/// </summary>
/// <param name="ex">异常信息</param>
/// <returns>ActionResult</returns>
private IActionResult HandleUnexpectedException(Exception ex)
{
_logger.LogError(ex, "处理查询请求时发生异常");
return StatusCode(500, $"服务器内部错误: {ex.Message}");
}
/// <summary>
/// 根据数据ID召唤遥测数据
/// </summary>
/// <param name="cmd">数据ID字符串格式CallYCByDataID|DataID1#DataID2#DataID3#......</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>召唤结果</returns>
/// <remarks>
/// 示例请求GET /api/CallYCByDataId?dataIds=CallYCByDataID|001#002#003
/// </remarks>
[HttpGet("CallYCByDataId")]
public async Task<IActionResult> CallYCByDataId(
[FromQuery] string cmd,
[FromQuery] int times,
CancellationToken cancellationToken = default)
{
try
{
// 参数验证
var validationResult = ValidateDataIdsParameter(cmd);
if (!validationResult.IsValid)
2025-07-31 18:51:24 +08:00
{
return BadRequest(new
{
success = false,
message = validationResult.ErrorMessage,
timestamp = DateTime.Now
});
2025-07-31 18:51:24 +08:00
}
_logger.LogInformation("收到遥测数据召唤请求 - cmd: {cmd}", cmd);
// 发送TCP消息
int sucessCount = 0;
for (int i = 0; i < times; i++)
2025-07-31 18:51:24 +08:00
{
var sendResult = await SendTcpMessageAsync(cmd, cancellationToken);
if (sendResult.Success)
{
sucessCount++;
}
await Task.Delay(1000);
2025-07-31 18:51:24 +08:00
}
if (times-sucessCount<3)
2025-07-31 18:51:24 +08:00
{
return Ok(new
{
success = true,
message = "遥测数据召唤命令已发送",
timestamp = DateTime.Now
});
2025-07-31 18:51:24 +08:00
}
else
2025-07-31 18:51:24 +08:00
{
return StatusCode(500, new
{
success = false,
message = $"发送命令失败",
timestamp = DateTime.Now
});
2025-07-31 18:51:24 +08:00
}
}
catch (OperationCanceledException)
{
_logger.LogWarning("遥测数据召唤请求被取消 - cmd: {cmd}", cmd);
return StatusCode(504, new
2025-07-31 18:51:24 +08:00
{
success = false,
message = "请求超时",
timestamp = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogError(ex, "处理遥测数据召唤请求时发生异常 - cmd: {cmd}", cmd);
return StatusCode(500, new
2025-07-31 18:51:24 +08:00
{
success = false,
message = $"服务器内部错误: {ex.Message}",
timestamp = DateTime.Now
});
}
}
2025-07-31 18:51:24 +08:00
/// <summary>
/// 验证数据ID参数
/// </summary>
/// <param name="dataIds">数据ID字符串</param>
/// <returns>验证结果</returns>
private (bool IsValid, string ErrorMessage) ValidateDataIdsParameter(string dataIds)
{
if (string.IsNullOrWhiteSpace(dataIds))
{
return (false, "参数 dataIds 不能为空");
2025-07-31 18:51:24 +08:00
}
// 检查格式是否符合 CallYCByDataID|DataID1#DataID2#...
if (!dataIds.StartsWith("CallYCByDataID|", StringComparison.OrdinalIgnoreCase))
{
return (false, "参数格式错误应为CallYCByDataID|DataID1#DataID2#DataID3#......");
}
// 检查是否包含数据ID
var parts = dataIds.Split('|');
if (parts.Length < 2 || string.IsNullOrWhiteSpace(parts[1]))
{
return (false, "未提供数据ID格式应为CallYCByDataID|DataID1#DataID2#DataID3#......");
}
return (true, string.Empty);
}
/// <summary>
/// 发送TCP消息
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>发送结果</returns>
private async Task<(bool Success, string ErrorMessage)> SendTcpMessageAsync(string message, CancellationToken cancellationToken)
{
try
2025-07-31 18:51:24 +08:00
{
// 检查TCP连接状态
if (_queryService == null)
{
return (false, "查询服务未初始化");
}
// 使用QueryService的TCP客户端发送消息
// 注意这里直接通过ITcpClient发送不需要等待响应
var tcpClient = GetTcpClientFromQueryService();
if (tcpClient == null)
{
return (false, "TCP客户端未初始化");
}
if (!tcpClient.IsConnected)
{
return (false, "TCP连接未建立");
}
var sendResult = await tcpClient.SendMessageAsync(message, cancellationToken);
if (!sendResult)
{
return (false, "TCP消息发送失败");
}
return (true, string.Empty);
2025-07-31 18:51:24 +08:00
}
catch (Exception ex)
{
_logger.LogError(ex, "发送TCP消息时发生异常");
return (false, ex.Message);
2025-07-31 18:51:24 +08:00
}
}
/// <summary>
/// 从QueryService获取TCP客户端
/// </summary>
/// <returns>TCP客户端实例</returns>
private ITcpClient GetTcpClientFromQueryService()
{
return _tcpClient;
}
2025-07-31 18:51:24 +08:00
/// <summary>
/// 获取服务状态
/// </summary>
/// <returns>服务状态</returns>
[HttpGet("status")]
public IActionResult GetStatus()
{
try
{
var status = new
{
IsQueryInProgress = _queryService.IsQueryInProgress,
Timestamp = DateTime.Now,
Status = "Running"
};
return Ok(status);
2025-07-31 18:51:24 +08:00
}
catch (Exception ex)
{
_logger.LogError(ex, "获取服务状态时发生异常");
return StatusCode(500, $"获取状态失败: {ex.Message}");
}
}
/// <summary>
/// 健康检查端点
/// </summary>
/// <returns>健康状态</returns>
[HttpGet("health")]
public IActionResult HealthCheck()
{
return Ok("Healthy");
}
/// <summary>
/// HTTP消息转发到WebSocket
/// 支持ThingJS语法的事件和数据转发
/// </summary>
/// <param name="request">转发请求</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>转发结果</returns>
[HttpPost("forward-to-websocket")]
public async Task<IActionResult> ForwardToWebSocket([FromBody] object request, CancellationToken cancellationToken = default)
{
try
{
// 参数验证
if (request == null)
{
return BadRequest(new { message = "请求体不能为空" });
}
var jsonData = JToken.FromObject(request);
// 🔧 修复:智能确定目标分组,而不是硬编码为"thing"
var targetGroups = DetermineTargetGroupsFromMessage(jsonData);
// 处理检修状态消息
await ProcessMaintenanceStatusMessage(jsonData);
var forwardResults = new List<string>();
// 转发到所有确定的目标分组
foreach (var targetGroup in targetGroups)
{
try
{
await _webSocketBroadcaster.PushToGroupAsync(targetGroup, "ex", jsonData, useRawData: true);
forwardResults.Add($"{targetGroup}: 成功");
_logger.LogDebug("消息已成功转发到WebSocket分组: {Group}", targetGroup);
}
catch (Exception groupEx)
{
forwardResults.Add($"{targetGroup}: 失败 - {groupEx.Message}");
_logger.LogError(groupEx, "转发消息到分组 {Group} 失败", targetGroup);
}
}
_logger.LogInformation("消息转发完成 - 目标分组: {Groups}, 结果: {Results}",
string.Join(", ", targetGroups), string.Join("; ", forwardResults));
return Ok(new
{
success = true,
message = "消息转发完成",
targetGroups = targetGroups,
results = forwardResults,
timestamp = DateTime.UtcNow
});
}
catch (JsonException jsonEx)
{
_logger.LogError(jsonEx, "解析JSON数据时发生错误");
return BadRequest(new { message = $"JSON格式错误: {jsonEx.Message}" });
}
catch (Exception ex)
{
_logger.LogError(ex, "转发消息到WebSocket时发生异常");
return StatusCode(500, new { message = $"服务器内部错误: {ex.Message}" });
}
}
/// <summary>
/// 根据消息内容确定目标分组
/// </summary>
/// <param name="jsonData">消息数据</param>
/// <returns>目标分组列表</returns>
private List<string> DetermineTargetGroupsFromMessage(JToken jsonData)
{
var targetGroups = new List<string>();
try
{
// 检查消息是否包含检修状态信息
if (IsMaintenanceStatusMessage(jsonData))
{
// 检修状态消息发送到thing分组进行处理
targetGroups.Add("thing");
return targetGroups;
}
// 检查消息类型并确定分组
var messageType = DetermineMessageType(jsonData);
switch (messageType.ToUpper())
{
case "YC":
case "TELEMETERING":
targetGroups.Add("YC");
break;
case "YX":
case "TELESIGNALISATION":
targetGroups.Add("YX");
break;
case "ALARM":
case "ALERT":
targetGroups.Add("ALERT");
break;
case "COMMSTATE":
targetGroups.Add("COMMSTATE");
break;
case "THING":
default:
// 默认发送到thing分组
targetGroups.Add("thing");
break;
}
// 同时发送到ALL分组以保持兼容性
if (!targetGroups.Contains("ALL"))
{
targetGroups.Add("ALL");
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "确定目标分组时发生错误,使用默认分组");
targetGroups.Clear();
targetGroups.Add("thing");
}
return targetGroups;
}
/// <summary>
/// 判断是否为检修状态消息
/// </summary>
/// <param name="jsonData">消息数据</param>
/// <returns>是否为检修状态消息</returns>
private bool IsMaintenanceStatusMessage(JToken jsonData)
{
try
{
if (jsonData is JObject obj)
{
// 检查是否包含检修状态的键值对
foreach (var property in obj.Properties())
{
if (property.Value?.ToString().Contains("检修") == true)
{
return true;
}
}
}
}
catch (Exception ex)
{
_logger.LogDebug(ex, "检查检修状态消息时发生错误");
}
return false;
}
/// <summary>
/// 确定消息类型
/// </summary>
/// <param name="jsonData">消息数据</param>
/// <returns>消息类型</returns>
private string DetermineMessageType(JToken jsonData)
{
try
{
// 检查消息中是否包含类型字段
if (jsonData["type"] != null)
{
return jsonData["type"].ToString();
}
if (jsonData["messageType"] != null)
{
return jsonData["messageType"].ToString();
}
// 根据数据结构推断类型
if (jsonData["AlarmLevel"] != null || jsonData["AlarmType"] != null)
{
return "ALARM";
}
if (jsonData["ResultValue"] != null && jsonData["ResultTime"] != null)
{
return "YC"; // 遥测数据
}
if (jsonData["Value"] != null && jsonData["Time"] != null)
{
return "YX"; // 遥信数据
}
}
catch (Exception ex)
{
_logger.LogDebug(ex, "确定消息类型时发生错误");
}
return "THING"; // 默认类型
}
/// <summary>
/// 处理检修状态消息
/// </summary>
/// <param name="jsonData">消息数据</param>
/// <returns>处理任务</returns>
private async Task ProcessMaintenanceStatusMessage(JToken jsonData)
{
try
{
if (IsMaintenanceStatusMessage(jsonData) && jsonData is JObject obj)
{
var maintenanceData = new Dictionary<string, string>();
foreach (var property in obj.Properties())
{
var value = property.Value?.ToString();
if (!string.IsNullOrEmpty(value))
{
maintenanceData[property.Name] = value;
}
}
if (maintenanceData.Any())
{
_logger.LogInformation("检测到检修状态消息: {MaintenanceData}",
string.Join(", ", maintenanceData.Select(kvp => $"{kvp.Key}={kvp.Value}")));
// 🔧 更新Redis中的设备检修状态
await UpdateDeviceMaintenanceStatusInRedis(maintenanceData);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "处理检修状态消息时发生错误");
}
}
/// <summary>
/// 🔧 新增更新Redis中的设备检修状态
/// </summary>
/// <param name="maintenanceData">检修状态数据</param>
/// <returns>处理任务</returns>
private async Task UpdateDeviceMaintenanceStatusInRedis(Dictionary<string, string> maintenanceData)
{
try
{
const string protectionDeviceCommInfoRedisKey = "protectionDeviceCommInfo";
foreach (var kvp in maintenanceData)
{
var twinId = kvp.Key;
var maintenanceStatus = kvp.Value;
var isInMaintenance = maintenanceStatus.Contains("检修");
try
{
// 使用TwinIdApiService查询TwinId对应的EquipmentInfoId
var equipmentInfoId = await _webApiRequest.GetTwIdAsync(twinId);
// 从Redis获取所有保护装置通信信息
var allDevices = await _protectionDeviceCommInfoOutputredisRepository.HashSetGetAllAsync(protectionDeviceCommInfoRedisKey);
// 查找匹配的设备
var targetDevice = allDevices.FirstOrDefault(d => d.EquipmentInfoId == equipmentInfoId);
if (targetDevice != null)
{
// 更新检修状态
targetDevice.IsMaintenance = isInMaintenance;
// 更新Redis中的数据
await _protectionDeviceCommInfoOutputredisRepository.HashSetUpdateOneAsync(
protectionDeviceCommInfoRedisKey,
targetDevice.DeviceAddr.ToString(),
targetDevice);
_logger.LogInformation("已更新设备检修状态 - TwinId: {TwinId}, EquipmentInfoId: {EquipmentInfoId}, IsMaintenance: {IsMaintenance}",
twinId, equipmentInfoId, isInMaintenance);
}
else
{
_logger.LogWarning("未找到对应的保护装置设备 - EquipmentInfoId: {EquipmentInfoId}", equipmentInfoId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "更新设备检修状态失败 - TwinId: {TwinId}", twinId);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "更新Redis中的设备检修状态时发生错误");
}
}
/// <summary>
/// 解析ThingJS语法的数据
/// </summary>
/// <param name="data">原始数据字符串</param>
/// <returns>解析后的数据</returns>
private object ParseThingJSData(string data)
{
try
{
// 检查是否是ThingJS语法以#开头)
if (data.StartsWith("#"))
{
// 解析ThingJS语法例如 #UINO_T1
var thingId = data.Substring(1); // 移除#前缀
return new
{
type = "thing",
thingId = thingId,
selector = data,
originalData = data
};
}
// 尝试解析为JSON
try
{
return JsonConvert.DeserializeObject(data);
}
catch
{
// 如果不是JSON返回原始字符串
return data;
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "解析ThingJS数据时发生警告返回原始数据: {Data}", data);
return data;
}
}
/// <summary>
/// 根据事件名称和数据确定目标分组
/// </summary>
/// <param name="eventName">事件名称</param>
/// <param name="data">数据内容</param>
/// <returns>目标分组名称</returns>
private string DetermineTargetGroup(string eventName, string data)
{
// 根据事件名称确定分组
var eventLower = eventName.ToLower();
if (eventLower.Contains("yc") || eventLower.Contains("telemetering"))
{
return WebSocketGroups.YC;
}
if (eventLower.Contains("yx") || eventLower.Contains("telesignalisation"))
{
return WebSocketGroups.YX;
}
if (eventLower.Contains("alarm") || eventLower.Contains("alert"))
{
return WebSocketGroups.ALERT;
}
if (eventLower.Contains("comm") || eventLower.Contains("communication"))
{
return WebSocketGroups.COMMSTATE;
}
// 检查是否是Thing相关的事件
if (data.StartsWith("#") || eventLower.Contains("thing"))
{
return "thing"; // Thing专用分组
}
// 默认发送到ALL分组
return WebSocketGroups.ALL;
}
/// <summary>
/// 获取召唤的遥测数据
/// </summary>
/// <param name="dataIds">数据ID字符串格式DataID1#DataID2#DataID3#......</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>遥测数据列表</returns>
/// <remarks>
/// 示例请求GET /api/GetCollectedYCData?dataIds=001#002#003
/// </remarks>
[HttpGet("GetCollectedYCData")]
public async Task<IActionResult> GetCollectedYCData(
[FromQuery] string dataIds,
CancellationToken cancellationToken = default)
{
try
{
// 参数验证
if (string.IsNullOrWhiteSpace(dataIds))
{
return BadRequest(new
{
success = false,
message = "参数 dataIds 不能为空",
timestamp = DateTime.Now
});
}
_logger.LogInformation("收到获取遥测数据请求 - dataIds: {DataIds}", dataIds);
// 解析DataId列表
var dataIdList = dataIds.Split('#', StringSplitOptions.RemoveEmptyEntries)
.Select(id => id.Trim())
.Where(id => !string.IsNullOrWhiteSpace(id))
.ToList();
if (dataIdList.Count == 0)
{
return BadRequest(new
{
success = false,
message = "未提供有效的数据ID",
timestamp = DateTime.Now
});
}
// 从TelemeteringHandle获取数据
var ycDataList = _telemeteringHandle.GetYCDataByDataIds(dataIdList);
_logger.LogInformation("获取遥测数据成功 - 请求DataId数: {RequestCount}, 返回数据数: {ResultCount}",
dataIdList.Count, ycDataList.Count);
return Ok(new
{
success = true,
message = "获取遥测数据成功",
data = ycDataList,
count = ycDataList.Count,
timestamp = DateTime.Now
});
}
catch (OperationCanceledException)
{
_logger.LogWarning("获取遥测数据请求被取消 - dataIds: {DataIds}", dataIds);
return StatusCode(504, new
{
success = false,
message = "请求超时",
timestamp = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogError(ex, "获取遥测数据时发生异常 - dataIds: {DataIds}", dataIds);
return StatusCode(500, new
{
success = false,
message = $"服务器内部错误: {ex.Message}",
timestamp = DateTime.Now
});
}
}
2025-07-31 18:51:24 +08:00
}
2025-07-31 18:51:24 +08:00
}