using Microsoft.ClearScript.JavaScript;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Utilities;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using YunDa.Server.ISMSTcp.Domain;
using YunDa.Server.ISMSTcp.Models;
using YunDa.SOMS.DataTransferObject.ExternalEntities.BeijingYounuo;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace YunDa.Server.ISMSTcp.Services
{
///
/// 虚端子处理服务
/// 负责处理虚端子相关的业务逻辑
///
public class VirtualTerminalHandler
{
private readonly ILogger _logger;
private readonly WebApiRequest _webApiRequest;
private readonly ZzDataCacheContainerInit _zzDataCacheContainerInit;
// 🔧 新增:光纤虚点处理相关字段
private readonly ConcurrentDictionary _virtualPointToOpticalFiberMapping = new ConcurrentDictionary();
// 初始化状态
public volatile bool _isOpticalFiberMappingInitialized = false;
private readonly object _opticalFiberInitLock = new object();
//数据缓冲队列
private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(ZzDataCacheContainerDataType.eVA, 5);
public VirtualTerminalHandler(ILogger logger, WebApiRequest webApiRequest, ZzDataCacheContainerInit zzDataCacheContainerInit)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_webApiRequest = webApiRequest ?? throw new ArgumentNullException(nameof(webApiRequest));
_zzDataCacheContainerInit = zzDataCacheContainerInit;
_zzDataCacheContainerInit.InitVariantBaseinfo(_zzDataCacheContainer);
}
///
/// 初始化光纤虚点映射
///
/// 最大重试次数
/// 重试间隔(毫秒)
/// 初始化任务
public async Task InitOpticalFiberMappingAsync(int maxRetries = 3, int retryDelayMs = 2000)
{
if (_isOpticalFiberMappingInitialized)
{
_logger.LogInformation("光纤虚点映射已经初始化完成");
return true;
}
lock (_opticalFiberInitLock)
{
if (_isOpticalFiberMappingInitialized)
{
return true;
}
_logger.LogInformation("开始初始化光纤虚点映射...");
}
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
_logger.LogInformation("第 {Attempt}/{MaxRetries} 次尝试获取光纤配置数据", attempt, maxRetries);
// 获取光纤配置数据
var opticalFibers = await _webApiRequest.GetOpticalFiberListAsync();
if (opticalFibers == null || opticalFibers.Count == 0)
{
_logger.LogWarning("第 {Attempt} 次查询光纤配置数据为空", attempt);
if (attempt < maxRetries)
{
_logger.LogInformation("等待 {DelayMs} 毫秒后重试...", retryDelayMs);
await Task.Delay(retryDelayMs);
continue;
}
else
{
_logger.LogError("所有重试都失败,无法获取光纤配置数据");
return false;
}
}
// 创建虚点编码到光纤配置的映射
int mappingCount = 0;
foreach (var fiber in opticalFibers.Where(f => f.IsActive && !string.IsNullOrWhiteSpace(f.VirtualPointCode)))
{
if (_virtualPointToOpticalFiberMapping.TryAdd(fiber.VirtualPointCode, fiber))
{
mappingCount++;
}
else
{
_logger.LogWarning("虚点编码重复: {VirtualPointCode}", fiber.VirtualPointCode);
}
}
lock (_opticalFiberInitLock)
{
_isOpticalFiberMappingInitialized = true;
}
_logger.LogInformation("光纤虚点映射初始化成功!光纤配置: {OpticalFiberCount} 个,虚点映射: {MappingCount} 个",
opticalFibers.Count, mappingCount);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "第 {Attempt} 次初始化光纤虚点映射时发生错误", attempt);
if (attempt < maxRetries)
{
_logger.LogInformation("等待 {DelayMs} 毫秒后重试...", retryDelayMs);
await Task.Delay(retryDelayMs);
}
else
{
_logger.LogError("所有重试都失败,初始化光纤虚点映射失败");
return false;
}
}
}
return false;
}
///
/// 处理虚端子数据
///
/// 虚端子数据对象
/// 处理任务
public async Task ProcessVirtualTerminalDataAsync(VirtualTerminalData virtualTerminalData)
{
try
{
if (virtualTerminalData == null)
{
_logger.LogWarning("虚端子数据为空,跳过处理");
return;
}
if (!virtualTerminalData.IsValid())
{
_logger.LogWarning("虚端子数据无效:{Data}", virtualTerminalData);
return;
}
_logger.LogInformation("开始处理虚端子数据:{Data}", virtualTerminalData);
// 解析时间戳
if (virtualTerminalData.TryParseDateTime(out DateTime timestamp))
{
_logger.LogInformation("虚端子时间戳解析成功:{Timestamp}", timestamp);
}
else
{
_logger.LogInformation("虚端子时间戳解析失败:{TimeString}", virtualTerminalData.T);
}
// 解析数值
if (virtualTerminalData.TryParseValue(out double value))
{
_logger.LogInformation("虚端子数值解析成功:{Value}", value);
}
else
{
_logger.LogInformation("虚端子数值为非数字类型:{ValueString}", virtualTerminalData.V);
}
// 根据UA_ID执行不同的处理逻辑
await ProcessByUAId(virtualTerminalData);
//存入缓存
SaveDataToCache(virtualTerminalData.VA_ID, value, timestamp);
_logger.LogInformation("虚端子数据处理完成:{UA_ID}", virtualTerminalData.VA_ID);
}
catch (Exception ex)
{
_logger.LogError(ex, "处理虚端子数据时发生异常:{Data}", virtualTerminalData);
}
}
///
/// 根据UA_ID执行不同的处理逻辑
///
/// 虚端子数据
/// 处理任务
private async Task ProcessByUAId(VirtualTerminalData data)
{
try
{
await ProcessDefaultLogic(data);
}
catch (Exception ex)
{
_logger.LogError(ex, "根据UA_ID处理虚端子数据时发生异常:{UA_ID}", data.VA_ID);
}
}
///
/// 默认处理逻辑 - 处理光纤虚点
///
/// 虚端子数据
/// 处理任务
private async Task ProcessDefaultLogic(VirtualTerminalData data)
{
try
{
if (!_isOpticalFiberMappingInitialized)
{
_logger.LogDebug("光纤虚点映射尚未初始化,跳过处理");
return;
}
// 检查是否有对应的光纤配置
if (!_virtualPointToOpticalFiberMapping.TryGetValue(data.VA_ID, out var opticalFiber))
{
_logger.LogDebug("未找到虚点编码 {VA_ID} 对应的光纤配置", data.VA_ID);
return;
}
// 解析虚点值
if (!data.TryParseValue(out double value))
{
_logger.LogWarning("无法解析虚点值: {Value}, 虚点编码: {VA_ID}", data.V, data.VA_ID);
return;
}
_logger.LogDebug("处理光纤虚点: {VA_ID}, 值: {Value}, 光纤: {TwinId}", data.VA_ID, value, opticalFiber.TwinId);
// 根据虚点值处理报警
//Boolean型变量的值(真,假,不定)2018-04-26从uPro设备
//TVariantBoolValue = (vbTrue = 0,vbFalse = 1 vbUncertain = 2):
if (Math.Abs(value) < 0.0001) // 故障状态
{
await PushOpticalFiberAlarmAsync(opticalFiber, data);
}
else if (Math.Abs(value - 1) < 0.0001) // 正常状态
{
await DeleteOpticalFiberAlarmAsync(opticalFiber, data);
}
else
{
_logger.LogWarning("光纤虚点值异常: {Value}, 预期值为0或1, 虚点编码: {VA_ID}", value, data.VA_ID);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "处理光纤虚点默认逻辑时发生错误: {VA_ID}", data.VA_ID);
}
}
///
/// 尝试从JSON字符串解析虚端子数据
///
/// JSON字符串
/// 解析后的虚端子数据
/// 是否解析成功
public bool TryParseVirtualTerminalData(string json, out VirtualTerminalData virtualTerminalData)
{
virtualTerminalData = null;
try
{
if (string.IsNullOrEmpty(json))
{
return false;
}
virtualTerminalData = JsonConvert.DeserializeObject(json);
return virtualTerminalData != null && virtualTerminalData.IsValid();
}
catch (Exception ex)
{
_logger.LogDebug(ex, "解析虚端子数据失败:{Json}", json);
return false;
}
}
///
/// 推送光纤报警到3D系统
///
/// 光纤配置
/// 虚端子数据
///
private async Task PushOpticalFiberAlarmAsync(OpticalFiberDto opticalFiber, VirtualTerminalData virtualTerminalData)
{
try
{
if (string.IsNullOrWhiteSpace(opticalFiber.TwinId))
{
_logger.LogWarning("光纤配置缺少TwinId: {VirtualPointCode}", opticalFiber.VirtualPointCode);
return;
}
// 解析时间戳
var timestamp = DateTime.Now;
if (virtualTerminalData.TryParseDateTime(out DateTime parsedTime))
{
timestamp = parsedTime;
}
// 构造报警数据
var alarmData = new YounuoAlert
{
TwinID = opticalFiber.TwinId,
Severity = 1, // 默认严重级别
Status = 1, // 活跃报警
SourceAlertKey = "光纤故障",
Summary = $"光纤 {opticalFiber.CiCode ?? opticalFiber.TwinId} 故障,虚点编码: {opticalFiber.VirtualPointCode}",
SourceIdentifier = $"OpticalFiber_{opticalFiber.TwinId}_{opticalFiber.VirtualPointCode}",
LastOccurrence = timestamp.ToString("yyyy-MM-dd HH:mm:ss"),
};
_logger.LogInformation("推送光纤报警: TwinId={TwinId}, 虚点编码={VirtualPointCode}, 值={Value}",
opticalFiber.TwinId, opticalFiber.VirtualPointCode, virtualTerminalData.V);
await _webApiRequest.CallPushAlarmsApiAsync(alarmData);
}
catch (Exception ex)
{
_logger.LogError(ex, "推送光纤报警时发生错误: TwinId={TwinId}, 虚点编码={VirtualPointCode}",
opticalFiber.TwinId, opticalFiber.VirtualPointCode);
}
}
///
/// 删除光纤报警
///
/// 光纤配置
/// 虚端子数据
///
private async Task DeleteOpticalFiberAlarmAsync(OpticalFiberDto opticalFiber, VirtualTerminalData virtualTerminalData)
{
try
{
if (string.IsNullOrWhiteSpace(opticalFiber.TwinId))
{
_logger.LogWarning("光纤配置缺少TwinId: {VirtualPointCode}", opticalFiber.VirtualPointCode);
return;
}
_logger.LogInformation("删除光纤报警: TwinId={TwinId}, 虚点编码={VirtualPointCode}, 值={Value}",
opticalFiber.TwinId, opticalFiber.VirtualPointCode, virtualTerminalData.V);
// TODO: 实现实际的API调用到BeijingYounuoApiAppService.DeleteAlarmsByTwinIdAsync
// 由于架构限制,可能需要通过HTTP API或消息队列来实现
await _webApiRequest.CallDeleteAlarmsByTwinIdApiAsync(opticalFiber.TwinId);
}
catch (Exception ex)
{
_logger.LogError(ex, "删除光纤报警时发生错误: TwinId={TwinId}, 虚点编码={VirtualPointCode}",
opticalFiber.TwinId, opticalFiber.VirtualPointCode);
}
}
//缓存遥信数据到内存
private void SaveDataToCache(string id, double value, DateTime timestamp)
{
try
{
string valStr = "不定";
switch((int)value)
{
case 0:
valStr = "报警";
break;
case 1:
valStr = "正常";
break;
}
_zzDataCacheContainer.Write(id, value, timestamp, "", valStr);
}
catch (Exception ex)
{
_logger.LogError(ex, "VirtualTerminalHandler: SaveDataToCache 出错");
}
}
//查询数据
public async Task> GetDataByIds(List ids, int seconds, int timeWindowType, CancellationToken cancellationToken)
{
try
{
return await _zzDataCacheContainer.Read(ids, seconds, timeWindowType, cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "VirtualTerminalHandler: GetDataByIds 出错");
return new List();
}
}
}
}