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(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 { _zzDataCacheContainer.Write(id, value, timestamp, ""); } 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(); } } } }