From d490f510dcfdfa298c42328a38029cbb897efd25 Mon Sep 17 00:00:00 2001 From: qsp89 Date: Fri, 21 Nov 2025 10:24:04 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E4=B8=89=E7=BB=B4?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=A2=9E=E5=8A=A0=E6=96=87=E6=9C=AC=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YunDa.Server.ISMSTcp/Program.cs | 3 ++ .../Services/ThingService.cs | 53 +++++++++++++++++-- .../Services/VirtualTerminalHandler.cs | 14 ++++- .../Services/ZzDataCacheContainer.cs | 4 +- .../YunDa.Server.ISMSTcp/appsettings.json | 6 +++ 5 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Program.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Program.cs index f07798f..ceea2f3 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Program.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Program.cs @@ -97,6 +97,9 @@ namespace YunDa.Server.ISMSTcp // 注册 WebApi 配置类 services.Configure(context.Configuration.GetSection("WebApi")); + + // 注册 ThingApiService配置 + services.Configure(context.Configuration.GetSection("ThingApiService")); }) .UseSerilog() .UseConsoleLifetime(); diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs index bec3175..876cb0a 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; using StackExchange.Redis; using System; @@ -30,6 +31,15 @@ using static System.Net.Mime.MediaTypeNames; namespace YunDa.Server.ISMSTcp.Services { + //ThingApiService配置 + public class ThingApiServiceSettings + { + public string ApiServerUrl { get; set; } = string.Empty; + public string LoginCode { get; set; } = string.Empty; + public string LoginKey { get; set; } = string.Empty; + public string EsAuthorization { get; set; } = string.Empty; + } + public class ThingDeviceStatusModel { public string TwinID { get; set; } = string.Empty; @@ -623,16 +633,31 @@ namespace YunDa.Server.ISMSTcp.Services } //推送全体性能数据 + + private int _updateAllSimDatasCnt = 0; private async Task UpdateAllSimDatas() { + + /*******************推送遥测全体性能数据/*******************/ var telemeteringModels = await _telemeteringModelListRedis.HashSetGetAllAsync(_telemeteringModelListRediskey); - await UpdateYCSimDatasStatus(telemeteringModels); /*******************推送遥信全体性能数据/*******************/ var telesignalisationModels = await _telesignalisationModelListRedis.HashSetGetAllAsync(_telesignalisationModelListRediskey); - await UpdateYXSimDatasStatus(telesignalisationModels); + + if(_updateAllSimDatasCnt == 0) + { + await UpdateThingYCStatus(telemeteringModels); + await UpdateThingYXStatus(telesignalisationModels); + } + else + { + await UpdateYCSimDatasStatus(telemeteringModels); + await UpdateYXSimDatasStatus(telesignalisationModels); + } + + ++_updateAllSimDatasCnt; } //推送遥测性能数据 @@ -1213,14 +1238,36 @@ namespace YunDa.Server.ISMSTcp.Services private DateTime _apiTokenTime = DateTime.MinValue; private readonly SemaphoreSlim _apiTokenSemaphore = new SemaphoreSlim(1, 1); + private readonly ThingApiServiceSettings _thingApiServiceSettings; + public ThingApiService( - ILogger logger) + ILogger logger, + IOptions thingApiServiceSettings) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _deviceStatusChannel = Channel.CreateUnbounded>(); _alarmDataChannel = Channel.CreateUnbounded>(); + + _thingApiServiceSettings = thingApiServiceSettings.Value; + + if (!string.IsNullOrWhiteSpace(_thingApiServiceSettings.ApiServerUrl)) + _apiServerUrl = _thingApiServiceSettings.ApiServerUrl; + + if (!string.IsNullOrWhiteSpace(_thingApiServiceSettings.LoginCode)) + _loginCode = _thingApiServiceSettings.LoginCode; + + if (!string.IsNullOrWhiteSpace(_thingApiServiceSettings.LoginKey)) + _loginKey = _thingApiServiceSettings.LoginKey; + + if (!string.IsNullOrWhiteSpace(_thingApiServiceSettings.EsAuthorization)) + _esAuthorization = _thingApiServiceSettings.EsAuthorization; + + System.Console.WriteLine($"ThingApiService Url: {_apiServerUrl}"); + + + StartPushDeviceStatus(); StarPushAlarmStatus(); diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs index 611585c..2949424 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs @@ -375,7 +375,19 @@ namespace YunDa.Server.ISMSTcp.Services { try { - _zzDataCacheContainer.Write(id, value, timestamp, ""); + string valStr = "不定"; + switch((int)value) + { + case 0: + valStr = "报警"; + break; + + case 1: + valStr = "正常"; + break; + } + + _zzDataCacheContainer.Write(id, value, timestamp, "", valStr); } catch (Exception ex) { diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs index 549047d..1cce302 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs @@ -272,14 +272,14 @@ namespace YunDa.Server.ISMSTcp.Services { string cmd = "CallVAByStat|B001"; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 5; i++) { var sendResult = await _zTcpService.SendTcpMessageAsync(cmd, CancellationToken.None); if (sendResult.Success) { break; } - await Task.Delay(1000); + await Task.Delay(2000); } } } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/appsettings.json b/src/YunDa.Server/YunDa.Server.ISMSTcp/appsettings.json index e3a1c24..4410f15 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/appsettings.json +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/appsettings.json @@ -52,6 +52,12 @@ "EnableCors": true, "AllowedOrigins": ["*"] }, + "ThingApiService":{ + "ApiServerUrl": "http://192.168.81.22", + "LoginCode": "admin", + "LoginKey": "Thing@123", + "EsAuthorization": "admin:uino", + }, "CommunicationFramework": { "Port": 7110, "WorkerThreads": 4, From 01fed80784dbfa8e7b2e49c1606a4a15cd8dffb2 Mon Sep 17 00:00:00 2001 From: qsp89 Date: Fri, 21 Nov 2025 18:07:07 +0800 Subject: [PATCH 2/4] =?UTF-8?q?1=E3=80=81=E5=B7=A1=E6=A3=80=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E6=97=B6=E9=97=B4=E4=B8=8D=202=E3=80=81=E4=B8=8E?= =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=8A=B6=E6=80=81=E4=B8=8D=E5=AF=B9=203?= =?UTF-8?q?=E3=80=81=E5=8F=91=E9=80=81=E9=81=A5=E6=B5=8B=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E5=A4=AA=E9=95=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YunDa.SOMS.MongoDB.Application.xml | 6 ++ .../Controllers/QueryController.cs | 74 +++++++++++++++++-- .../Domain/WebApiRequest.cs | 26 +++++++ .../SecondaryCircuitInspectionPlanService.cs | 2 +- .../Services/TelesignalisationHandle.cs | 1 + .../Services/ThingService.cs | 13 +++- 6 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml b/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml index d7807cb..007af48 100644 --- a/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml +++ b/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml @@ -1236,6 +1236,12 @@ + + + 测试报警api + + + 获取报警信息 diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Controllers/QueryController.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Controllers/QueryController.cs index 19d47eb..7000025 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Controllers/QueryController.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Controllers/QueryController.cs @@ -255,6 +255,49 @@ namespace YunDa.Server.ISMSTcp.Controllers return StatusCode(500, $"服务器内部错误: {ex.Message}"); } + + private List GetValidZzCmd(string cmdName, List ids) + { + const int maxLength = 250; + + var cmds = new List(); + + // 开始构建 + string prefix = cmdName + "|"; // 固定前缀 + int prefixLength = prefix.Length; + + var currentIds = new List(); + int currentLength = prefixLength; // 当前命令的长度(含前缀) + + foreach (var id in ids) + { + // 如果添加这个ID会超长,则先生成一个命令 + int idLength = (currentIds.Count == 0 ? id.Length : (1 + id.Length)); // 第一个ID不需要 '#' + + if (currentLength + idLength > maxLength) + { + // 将当前批次加入 cmds + cmds.Add(prefix + string.Join("#", currentIds)); + + // 清空并重建 + currentIds.Clear(); + currentLength = prefixLength; + } + + // 添加新的 ID + currentIds.Add(id); + currentLength += idLength; + } + + // 收尾:如果还有剩余 IDs,生成最后一个命令 + if (currentIds.Count > 0) + { + cmds.Add(prefix + string.Join("#", currentIds)); + } + + return cmds; + } + /// /// 根据数据ID召唤遥测数据 /// @@ -282,9 +325,11 @@ namespace YunDa.Server.ISMSTcp.Controllers id.RemoveAll(string.IsNullOrWhiteSpace); - string cmd = string.Format("CallYCByDataID|{0}", string.Join("#", id)); + //string cmd = string.Format("CallYCByDataID|{0}", string.Join("#", id)); - System.Console.WriteLine($"发送遥测命令:{cmd}"); + //System.Console.WriteLine($"发送遥测命令:{cmd}"); + + var cmds = GetValidZzCmd("CallYCByDataID", id); try { @@ -299,7 +344,7 @@ namespace YunDa.Server.ISMSTcp.Controllers }); } - _logger.LogInformation("收到遥测数据召唤请求 - cmd: {cmd}", cmd); + _logger.LogInformation("收到遥测数据召唤请求 - cmd: {cmd}", string.Join("#", id)); // 发送TCP消息 DateTime cmdTime = DateTime.Now; @@ -310,8 +355,23 @@ namespace YunDa.Server.ISMSTcp.Controllers { for (int i = 0; i < times; i++) { - var sendResult = await SendTcpMessageAsync(cmd, cancellationToken); - if (sendResult.Success) + bool isSuccess = true; + + foreach (var cmd in cmds) + { + var sendResult = await SendTcpMessageAsync(cmd, cancellationToken); + isSuccess &= sendResult.Success; + if (!isSuccess) + { + break; + } + else + { + await Task.Delay(5); + } + } + + if (isSuccess) { sucessCount++; } @@ -375,7 +435,7 @@ namespace YunDa.Server.ISMSTcp.Controllers } catch (OperationCanceledException) { - _logger.LogWarning("遥测数据召唤请求被取消 - cmd: {cmd}", cmd); + _logger.LogWarning("遥测数据召唤请求被取消 - cmd: {cmd}", string.Join("#", id)); return StatusCode(504, new { success = false, @@ -385,7 +445,7 @@ namespace YunDa.Server.ISMSTcp.Controllers } catch (Exception ex) { - _logger.LogError(ex, "处理遥测数据召唤请求时发生异常 - cmd: {cmd}", cmd); + _logger.LogError(ex, "处理遥测数据召唤请求时发生异常 - cmd: {cmd}", string.Join("#", id)); return StatusCode(500, new { success = false, diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs index a5c7d99..c309ee4 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -919,6 +920,19 @@ namespace YunDa.Server.ISMSTcp.Domain var result = ExtractDataFromAbpResponse>(response); + //List ids = new List(); + //foreach(var item in result) + //{ + // ids.AddRange(item.VirtualPointCodes); + // ids.AddRange(item.LinkageDatas); + // ids.AddRange(item.LogicalExpressions); + //} + + // var ids2 = ids.Where(id => id.Contains("YXB")).ToList().Distinct().ToList(); + + //Debug.WriteLine(string.Join("#", ids2)); + + return result; } } @@ -945,6 +959,18 @@ namespace YunDa.Server.ISMSTcp.Domain var result = ExtractDataFromAbpResponse>(response); + //List ids = new List(); + //foreach (var item in result) + //{ + // ids.AddRange(item.VirtualPointCodes); + // ids.AddRange(item.LinkageDatas); + // ids.AddRange(item.LogicalExpressions); + //} + + //var ids2 = ids.Where(id => id.Contains("YXB")).ToList().Distinct().ToList(); + + //Debug.WriteLine(string.Join("#", ids2)); + return result; } } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs index b0b5c43..23dd30d 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs @@ -133,7 +133,7 @@ namespace YunDa.Server.ISMSTcp.Services public string SecondaryCircuitInspectionItemId { get; set; } = string.Empty; public string InspectionPlanId { get; set; } = string.Empty; - public DateTime ExecutionTime { get; set; } = DateTime.Now; + public string ExecutionTime { get; set; } = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); public long ExecutionDurationMs { get; set; } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs index b0a834d..2e0ad24 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs @@ -140,6 +140,7 @@ namespace YunDa.Server.ISMSTcp.Services // 这里使用模型中的地址信息 string haskey = $"{model.DeviceAddress}_0_{model.DispatcherAddress}_0"; + if (_yxIdToHashKeyMapping.TryAdd(model.ismsbaseYXId, haskey)) { mappingCount++; diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs index 876cb0a..3767c79 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs @@ -805,6 +805,13 @@ namespace YunDa.Server.ISMSTcp.Services /******************网线、光纤、光缆*****************/ + private static bool IsYxValueAlarm(string valStr) + { + string[] err = { "分", "未同步", "告警", "异常", "断", "未就绪", "无效", "异常", "未复归", "动作", "检修", "未储能", "跳闸", "失步", "分位" }; + + return err.Contains(valStr); + } + //更新网线配置 private async Task UpdateNetworkCableConfig() { @@ -863,7 +870,7 @@ namespace YunDa.Server.ISMSTcp.Services alertData.Parse( configItem.TwinId, 2, - item.ResultValue == 1, + IsYxValueAlarm(item.ResultValueStr), $"{configItem.P1DeviceName}{configItem.P2DeviceName}", "网线断线", item.ResultTime.ToString("yyyy-MM-dd HH:mm:ss") @@ -1020,7 +1027,7 @@ namespace YunDa.Server.ISMSTcp.Services alertData.Parse( configItem.TwinId, 2, - item.ResultValue == 1, + IsYxValueAlarm(item.ResultValueStr), $"{configItem.P1DeviceName}{configItem.P2DeviceName}", "光纤断线", item.ResultTime.ToString("yyyy-MM-dd HH:mm:ss") @@ -1188,7 +1195,7 @@ namespace YunDa.Server.ISMSTcp.Services alertData.Parse( configItem.TwinId, 2, - item.ResultValue == 1, + IsYxValueAlarm(item.ResultValueStr), $"{configItem.P1CabinetName}{configItem.P2CabinetName}", "光缆断线", item.ResultTime.ToString("yyyy-MM-dd HH:mm:ss") From 8587b149063bd5c6dc71bce7b791cc315d40aa0f Mon Sep 17 00:00:00 2001 From: qsp89 Date: Fri, 21 Nov 2025 20:04:39 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B7=A1=E6=A3=80?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E6=97=B6=EF=BC=8C=E6=B2=A1=E6=9C=89deviceNam?= =?UTF-8?q?e=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/SecondaryCircuitInspectionPlanService.cs | 6 ++---- .../YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs index 23dd30d..4961452 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs @@ -525,8 +525,8 @@ namespace YunDa.Server.ISMSTcp.Services private async Task ExecutePlan(SecondaryCircuitInspectionItemOutputEx itemEx) { - string func2 = ""; - string data2 = ""; + //string func2 = ""; + //string data2 = ""; try { var item = itemEx.Item; @@ -554,7 +554,6 @@ namespace YunDa.Server.ISMSTcp.Services var engine = new Jint.Engine(); engine.Execute(item.CalculationExpression); - func2 = item.CalculationExpression; ObjectInstance? saveObj = null; @@ -632,7 +631,6 @@ namespace YunDa.Server.ISMSTcp.Services var js = $"JSON.parse('{json.Replace("'", "\\'")}')"; - data2 = json; var jsObj = engine.Evaluate(js).ToObject(); diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs index 1cce302..85b676e 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs @@ -97,6 +97,7 @@ namespace YunDa.Server.ISMSTcp.Services { public string Id { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; + public string DeviceName { get; set; } = string.Empty; public int? DispatcherAddress { get; set; } = null; public double Value { get; set; } public string ValueStr { get; set; } = string.Empty; From 487fa3def3d54050981d732f06e4d5ee42a155fd Mon Sep 17 00:00:00 2001 From: qsp89 Date: Wed, 26 Nov 2025 14:08:37 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=8E=A8=E9=80=81=E4=B8=8D=E5=85=A8=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20=E9=81=A5=E6=B5=8B=E6=95=B0=E6=8D=AE=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E4=B8=BA0=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YunDa.SOMS.MongoDB.Application.xml | 6 -- .../ApiEndpointsConfiguration.cs | 3 + .../Domain/ApiEndpoints.cs | 6 ++ .../Domain/WebApiRequest.cs | 23 ++++++ .../YunDa.Server.ISMSTcp/Helpers/ChannelEx.cs | 69 +++++++++++++++++ .../Services/GwErrorRatioService.cs | 2 +- .../SecondaryCircuitInspectionPlanService.cs | 75 +++++++++++++------ .../Services/TelemeteringHandle.cs | 36 +++++++-- .../Services/TelesignalisationHandle.cs | 2 +- .../Services/ThingService.cs | 36 ++++----- .../Services/VirtualTerminalHandler.cs | 2 +- .../Services/ZzDataCacheContainer.cs | 69 +++++++++++++++-- 12 files changed, 263 insertions(+), 66 deletions(-) create mode 100644 src/YunDa.Server/YunDa.Server.ISMSTcp/Helpers/ChannelEx.cs diff --git a/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml b/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml index 007af48..d7807cb 100644 --- a/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml +++ b/src/YunDa.Application/YunDa.SOMS.MongoDB.Application/YunDa.SOMS.MongoDB.Application.xml @@ -1236,12 +1236,6 @@ - - - 测试报警api - - - 获取报警信息 diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Configuration/ApiEndpointsConfiguration.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Configuration/ApiEndpointsConfiguration.cs index 2ebf3bb..db78372 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Configuration/ApiEndpointsConfiguration.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Configuration/ApiEndpointsConfiguration.cs @@ -167,6 +167,9 @@ namespace YunDa.Server.ISMSTcp.Configuration //获取网关信息 public string GetGateWayBaseInfoUri => $"{BaseUrl.TrimEnd('/')}/api/services/SOMS/SecondaryCircuitInspectionItem/GetGateWayBaseInfo"; + //获取没有调用ai的巡检结果记录 + public string GetFailedAiInspectionListUri => $"{BaseUrl.TrimEnd('/')}/api/services/SOMS/SecondaryCircuitInspectionItem/GetGateWayBaseInfo"; + } } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/ApiEndpoints.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/ApiEndpoints.cs index ab00ff0..1145ef5 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/ApiEndpoints.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/ApiEndpoints.cs @@ -125,6 +125,9 @@ namespace YunDa.Server.ISMSTcp.Domain //获取网关信息 string GetGateWayBaseInfoUri { get; } + //获取没有调用ai的巡检结果记录 + string GetFailedAiInspectionListUri { get; } + } /// @@ -265,5 +268,8 @@ namespace YunDa.Server.ISMSTcp.Domain //获取网关信息 public string GetGateWayBaseInfoUri => _config.GetGateWayBaseInfoUri; + //获取没有调用ai的巡检结果记录 + public string GetFailedAiInspectionListUri => _config.GetFailedAiInspectionListUri; + } } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs index c309ee4..ae08df9 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Domain/WebApiRequest.cs @@ -1118,5 +1118,28 @@ namespace YunDa.Server.ISMSTcp.Domain return null; } + + //获取没有调用ai的巡检结果记录 + public async Task> GetFailedAiInspectionListAsync() + { + try + { + var response = await Task.Run(() => ToolLibrary.HttpHelper.HttpGetRequest(_apiEndpoints.GetFailedAiInspectionListUri)); + + if (response != null) + { + + var result = ExtractDataFromAbpResponse>(response); + + return result; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error Call GetOpticalCableConfigAsync Api"); + } + + return null; + } } } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Helpers/ChannelEx.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Helpers/ChannelEx.cs new file mode 100644 index 0000000..cb1908d --- /dev/null +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Helpers/ChannelEx.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; + +namespace YunDa.Server.ISMSTcp.Helpers +{ + public class ChannelEx where TKey : notnull + { + private readonly Channel _channel; + private readonly ConcurrentDictionary _exists = new ConcurrentDictionary(); + private readonly Func _keySelector; + + public ChannelEx(Func keySelector) + { + _channel = Channel.CreateUnbounded(); + _keySelector = keySelector ?? throw new ArgumentNullException(nameof(keySelector)); + } + + // 判断是否有内容 + public bool HasItems => !_exists.IsEmpty; + + // 判断某条记录是否存在 + public bool Contains(T item) => _exists.ContainsKey(_keySelector(item)); + + // 异步添加 + public async ValueTask WriteAsync(T item) + { + if (!TryAdd(item)) + return false; + + await _channel.Writer.WriteAsync(item); + return true; + } + + // 消费单个元素 + public async ValueTask ReadAsync() + { + var item = await _channel.Reader.ReadAsync(); + _exists.TryRemove(_keySelector(item), out _); + return item; + } + + // 封装成 IAsyncEnumerable,可直接 await foreach + public async IAsyncEnumerable ReadAllAsync([System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default) + { + while (await _channel.Reader.WaitToReadAsync(cancellationToken)) + { + while (_channel.Reader.TryRead(out var item)) + { + _exists.TryRemove(_keySelector(item), out _); + yield return item; + } + } + } + + + // 内部去重逻辑 + private bool TryAdd(T item) + { + var key = _keySelector(item); + return _exists.TryAdd(key, true); + } + } + + +} diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/GwErrorRatioService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/GwErrorRatioService.cs index f5a5ebd..758d8ca 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/GwErrorRatioService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/GwErrorRatioService.cs @@ -24,7 +24,7 @@ namespace YunDa.Server.ISMSTcp.Services //数据缓冲队列 - private ZzDataCacheContainer _cacheContainer = new ZzDataCacheContainer(2 * 60 + 1);//保留2小时的数据,多1分钟,兼容发送送数据发送延迟情况(每1小时发送一次) + private ZzDataCacheContainer _cacheContainer = new ZzDataCacheContainer(ZzDataCacheContainerDataType.eGW, 2 * 60 + 1);//保留2小时的数据,多1分钟,兼容发送送数据发送延迟情况(每1小时发送一次) public GwErrorRatioService(ILogger logger, ZzDataCacheContainerInit zzDataCacheContainerInit) { diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs index 4961452..43f8f11 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs @@ -31,6 +31,8 @@ using YunDa.SOMS.DataTransferObject.DataMonitoring.SecondaryCircuitInspection; using YunDa.SOMS.DataTransferObject.DataMonitoring.SecondaryCircuitInspection.Configurations; using YunDa.SOMS.DataTransferObject.MaintenanceAndOperations.SecondaryEquipment; using YunDa.SOMS.Entities.DataMonitoring.SecondaryCircuitInspection; +using YunDa.Server.ISMSTcp.Helpers; +using Abp.AutoMapper; namespace YunDa.Server.ISMSTcp.Services { @@ -155,8 +157,14 @@ namespace YunDa.Server.ISMSTcp.Services public class SecondaryCircuitInspectionAiParamModel { public string InspectionResultId { get; set; } = string.Empty; - public string PlanName { get; set; } = string.Empty; - public SecondaryCircuitInspectionResultSaveModel SaveModel { get; set; } + public string InspectionName { get; set; } = string.Empty; + public string InspectionDescription { get; set; } = string.Empty; + public string PlanName => string.Concat(InspectionName, " ", InspectionDescription); + public string Status { get; set; } = string.Empty; //"异常|正常|故障", + public string InspectionResult { get; set; } = string.Empty; //巡检结果 inspectionResult不能超过15个字符 + public string CalculationProcess { get; set; } = string.Empty; //计算过程 + public string VerificationResult { get; set; } = string.Empty; //校验结果 + } public class SecondaryCircuitInspectionAiSaveModel @@ -184,7 +192,7 @@ namespace YunDa.Server.ISMSTcp.Services private int _planCheckDay = 0; private readonly Channel _singlePlanChannel; //巡检计划 - private readonly Channel _aiChannel; //Ai调用 + private readonly ChannelEx _aiChannel; //Ai调用 //巡检事件 private Queue _eventPlanList; @@ -208,7 +216,7 @@ namespace YunDa.Server.ISMSTcp.Services _singlePlanChannel = Channel.CreateUnbounded(); - _aiChannel = Channel.CreateUnbounded(); + _aiChannel = new ChannelEx( item => item.InspectionResultId); _eventPlanList = new Queue(); @@ -226,11 +234,13 @@ namespace YunDa.Server.ISMSTcp.Services { while (true) {//每30秒更新一下配置 - + await UpdatePlans(); await UpdateEventPlans(); + //await CheckAiChannel(); + await Task.Delay(30000); } }); @@ -302,7 +312,7 @@ namespace YunDa.Server.ISMSTcp.Services var rand = new Random(Guid.NewGuid().GetHashCode()); - await foreach (var item in _aiChannel.Reader.ReadAllAsync()) + await foreach (var item in _aiChannel.ReadAllAsync()) { // 让每个线程在执行之间有不同的节奏 await Task.Delay(rand.Next(0, 300)); @@ -683,11 +693,18 @@ namespace YunDa.Server.ISMSTcp.Services if (!string.IsNullOrWhiteSpace(inspectionResultId) && saveData.Status != "正常") { SecondaryCircuitInspectionAiParamModel aiParamModel = new SecondaryCircuitInspectionAiParamModel(); - aiParamModel.InspectionResultId = inspectionResultId; - aiParamModel.PlanName = $"{itemEx.Item.Name} {itemEx.Item.Description}"; - aiParamModel.SaveModel = saveData; - _aiChannel.Writer.WriteAsync(aiParamModel); + aiParamModel.InspectionResultId = inspectionResultId; + + aiParamModel.InspectionName = item.Name; + aiParamModel.InspectionDescription = item.Description; + + aiParamModel.Status = saveData.Status; + aiParamModel.InspectionResult = saveData.InspectionResult; + aiParamModel.CalculationProcess = saveData.CalculationProcess; + aiParamModel.VerificationResult = saveData.VerificationResult; + + _aiChannel.WriteAsync(aiParamModel); } } @@ -700,6 +717,20 @@ namespace YunDa.Server.ISMSTcp.Services } } + //获取没有调用Ai接口或调用失败的巡检记录结果 + private async Task CheckAiChannel() + { + if (!_aiChannel.HasItems) + { + var list = await _webApiRequest.GetFailedAiInspectionListAsync(); + if (list != null) + { + foreach (var item in list) + await _aiChannel.WriteAsync(item); + } + } + } + private async Task CallAiAndSave(SecondaryCircuitInspectionAiParamModel aiParamModel) { try @@ -765,10 +796,10 @@ namespace YunDa.Server.ISMSTcp.Services sb.AppendLine(aiParamModel.PlanName); sb.AppendLine(); sb.AppendLine("巡检结果为:"); - sb.AppendLine($"巡检状态: {aiParamModel.SaveModel.Status}"); - sb.AppendLine($"计算过程: {aiParamModel.SaveModel.CalculationProcess}"); - sb.AppendLine($"巡检结果: {aiParamModel.SaveModel.InspectionResult}"); - sb.AppendLine($"校验结果: {aiParamModel.SaveModel.VerificationResult}"); + sb.AppendLine($"巡检状态: {aiParamModel.Status}"); + sb.AppendLine($"计算过程: {aiParamModel.CalculationProcess}"); + sb.AppendLine($"巡检结果: {aiParamModel.InspectionResult}"); + sb.AppendLine($"校验结果: {aiParamModel.VerificationResult}"); sb.AppendLine(); sb.AppendLine(); @@ -797,10 +828,10 @@ namespace YunDa.Server.ISMSTcp.Services // 巡检结果 sb.AppendLine("巡检结果为:"); - sb.AppendLine($"巡检状态: {aiParamModel.SaveModel.Status}"); - sb.AppendLine($"计算过程: {aiParamModel.SaveModel.CalculationProcess}"); - sb.AppendLine($"巡检结果: {aiParamModel.SaveModel.InspectionResult}"); - sb.AppendLine($"校验结果: {aiParamModel.SaveModel.VerificationResult}"); + sb.AppendLine($"巡检状态: {aiParamModel.Status}"); + sb.AppendLine($"计算过程: {aiParamModel.CalculationProcess}"); + sb.AppendLine($"巡检结果: {aiParamModel.InspectionResult}"); + sb.AppendLine($"校验结果: {aiParamModel.VerificationResult}"); sb.AppendLine(); sb.AppendLine(); @@ -1004,10 +1035,10 @@ namespace YunDa.Server.ISMSTcp.Services } - + ////获取遥测数据 - //public async Task> CallYCByDataIdAsync(CallYCByDataIdRequest request, CancellationToken cancellationToken = default) + //public async Task> CallYCByDataIdAsync(ZzDataRequestModel request, CancellationToken cancellationToken = default) //{ // try // { @@ -1023,13 +1054,13 @@ namespace YunDa.Server.ISMSTcp.Services // JArray jArray = obj.Value("data"); // if (jArray != null) // { - // List list = jArray.ToObject>(); + // List list = jArray.ToObject>(); // return list; // } // } // } - // catch(Exception ex) + // catch (Exception ex) // { // _logger.LogError(ex, "SecondaryCircuitInspectionPlanService - CallYCByDataIdAsync:发生错误"); // } diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelemeteringHandle.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelemeteringHandle.cs index 1b44521..15be887 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelemeteringHandle.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelemeteringHandle.cs @@ -67,7 +67,7 @@ namespace YunDa.Server.ISMSTcp.Services //private readonly Timer _cleanupTimer; //private const int CLEANUP_INTERVAL_MS = 60000; // 1分钟清理一次 //private const int DATA_EXPIRATION_MINUTES = 5; // 数据保留5分钟 - private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(3); // 数据保留3分钟 + private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(ZzDataCacheContainerDataType.eYC, 3); // 数据保留3分钟 // 初始化状态 public volatile bool _isInitialized = false; @@ -101,6 +101,8 @@ namespace YunDa.Server.ISMSTcp.Services // 🔧 新增:初始化数据清理定时器 //_cleanupTimer = new Timer(CleanupExpiredData, null, CLEANUP_INTERVAL_MS, CLEANUP_INTERVAL_MS); + + _zzDataCacheContainer.SetTelemeteringHandle(this); } /// @@ -420,11 +422,6 @@ namespace YunDa.Server.ISMSTcp.Services // 保存到Redis await _telemeteringModelListRedis.HashSetUpdateOneAsync(redisKey, haskey, telemeteringModel); - //if(ycDataModel.YC_ID == "YCB001101001") - //{ - // Debug.WriteLine("YCB001101001 : ", ycDataModel.V.ToString(), telemeteringModel.ResultValue.ToString(), telemeteringModel.Coefficient.ToString()); - //} - //保存到缓存 _zzDataCacheContainer.Write(ycDataModel.YC_ID, (float)ycDataModel.V, telemeteringModel.ResultTime, telemeteringModel.Name, $"{(float)ycDataModel.V} {telemeteringModel.Unit}", telemeteringModel.DispatcherAddress); @@ -461,6 +458,10 @@ namespace YunDa.Server.ISMSTcp.Services // 简化的批量推送处理 CollectTelemeteringDataForBatchPush(batchTelemeteringModels); + + + //将状态推送到孪生体 + _thingService.UpdateThingYCStatus(batchTelemeteringModels); } // 等待所有数据变位信号API调用完成(不阻塞主流程) @@ -673,7 +674,28 @@ namespace YunDa.Server.ISMSTcp.Services return result; } - + public async Task GetDataFromRedis(string ycId) + { + string redisKey = $"{_telemeteringModelListRediskey}_Zongzi"; + + if (!_ycIdToHashKeysMapping.TryGetValue(ycId, out List haskeys)) + { + return null; + } + + if (haskeys.Count >= 0) + { + string haskey = haskeys.First(); + + var telemeteringModel = await _telemeteringModelListRedis.HashSetGetOneAsync(redisKey, haskey); + + return telemeteringModel; + } + + return null; + } + + /// /// 🔧 新增:释放资源 diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs index 2e0ad24..62d6cf0 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/TelesignalisationHandle.cs @@ -53,7 +53,7 @@ namespace YunDa.Server.ISMSTcp.Services private readonly object _expressionInitLock = new object(); //遥信数据缓冲队列 - private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(30); //只保留5分钟的数据 + private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(ZzDataCacheContainerDataType.eYX, 30); //只保留5分钟的数据 diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs index 3767c79..b0162a7 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ThingService.cs @@ -632,6 +632,7 @@ namespace YunDa.Server.ISMSTcp.Services await UpdateOpticalCableAlarmStatus(null, telesignalisationModels); } + //推送全体性能数据 private int _updateAllSimDatasCnt = 0; @@ -682,11 +683,6 @@ namespace YunDa.Server.ISMSTcp.Services { if (_simDatasConfig.TryGetValue(equipmentInfoId, out var bindingItem)) { - //if (bindingItem.TwinId == "2F-kzs-024") - //{ - // int k = 0; - //} - if (bindingItem.IsActive) { var status = new ThingDeviceStatusModel { TwinID = bindingItem.TwinId.Trim(), Metric = item.Name.Trim(), Val = $"{item.ResultValue} {item.Unit}" }; @@ -860,8 +856,8 @@ namespace YunDa.Server.ISMSTcp.Services { if (!string.IsNullOrWhiteSpace(item.ismsbaseYXId)) { - var configItem = _networkCableConfig.FirstOrDefault(e => e.LogicalExpressions.Contains(item.ismsbaseYXId)); - if (configItem != null) + var configItems = _networkCableConfig.Where(e => e.LogicalExpressions.Contains(item.ismsbaseYXId)); + foreach (var configItem in configItems) { if (configItem.IsActive) { @@ -956,8 +952,8 @@ namespace YunDa.Server.ISMSTcp.Services { if (!string.IsNullOrWhiteSpace(item.VA_ID)) { - var configItem = configs.FirstOrDefault(e => e.VirtualPointCodes.Contains(item.VA_ID)); - if (configItem != null) + var configItems = configs.Where(e => e.VirtualPointCodes.Contains(item.VA_ID)); + foreach (var configItem in configItems) { if (configItem.IsActive) { @@ -997,10 +993,10 @@ namespace YunDa.Server.ISMSTcp.Services if (!string.IsNullOrWhiteSpace(item.ismsbaseYCId)) { //性能数据 - var configItem = configs.FirstOrDefault(e => e.LinkageDatas.Contains(item.ismsbaseYCId)); - if (configItem != null) + var configItems = configs.Where(e => e.LinkageDatas.Contains(item.ismsbaseYCId)); + foreach (var configItem in configItems) { - if(configItem.IsActive) + if (configItem.IsActive) { var status = new ThingDeviceStatusModel { TwinID = configItem.TwinId.Trim(), Metric = item.Name.Trim(), Val = $"{item.ResultValue} {item.Unit}" }; @@ -1017,8 +1013,8 @@ namespace YunDa.Server.ISMSTcp.Services foreach (var item in telesignalisationModels) { //报警 - var configItem = configs.FirstOrDefault(e => e.VirtualPointCodes.Contains(item.ismsbaseYXId)); - if (configItem != null) + var configItems = configs.Where(e => e.VirtualPointCodes.Contains(item.ismsbaseYXId)); + foreach (var configItem in configItems) { if (configItem.IsActive) { @@ -1038,8 +1034,8 @@ namespace YunDa.Server.ISMSTcp.Services } //性能数据 - configItem = configs.FirstOrDefault(e => e.LinkageDatas.Contains(item.ismsbaseYXId)); - if (configItem != null) + configItems = configs.Where(e => e.LinkageDatas.Contains(item.ismsbaseYXId)); + foreach (var configItem in configItems) { if (configItem.IsActive) { @@ -1143,8 +1139,8 @@ namespace YunDa.Server.ISMSTcp.Services { if (!string.IsNullOrWhiteSpace(item.VA_ID)) { - var configItem = configs.FirstOrDefault(e => e.LogicalExpressions.Contains(item.VA_ID)); - if (configItem != null) + var configItems = configs.Where(e => e.LogicalExpressions.Contains(item.VA_ID)); + foreach (var configItem in configItems) { if (configItem.IsActive) { @@ -1185,8 +1181,8 @@ namespace YunDa.Server.ISMSTcp.Services if (!string.IsNullOrWhiteSpace(item.ismsbaseYXId)) { //报警 - var configItem = configs.FirstOrDefault(e => e.LogicalExpressions.Contains(item.ismsbaseYXId)); - if (configItem != null) + var configItems = configs.Where(e => e.LogicalExpressions.Contains(item.ismsbaseYXId)); + foreach (var configItem in configItems) { if (configItem.IsActive) { diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs index 2949424..5d1d3fc 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/VirtualTerminalHandler.cs @@ -34,7 +34,7 @@ namespace YunDa.Server.ISMSTcp.Services //数据缓冲队列 - private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(5); + private ZzDataCacheContainer _zzDataCacheContainer = new ZzDataCacheContainer(ZzDataCacheContainerDataType.eVA, 5); public VirtualTerminalHandler(ILogger logger, WebApiRequest webApiRequest, ZzDataCacheContainerInit zzDataCacheContainerInit) diff --git a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs index 85b676e..fd400d6 100644 --- a/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs +++ b/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/ZzDataCacheContainer.cs @@ -1,8 +1,11 @@ -using Microsoft.Extensions.Logging; +using Google.Protobuf.WellKnownTypes; +using Microsoft.Extensions.Logging; +using Microsoft.Identity.Client; using Org.BouncyCastle.Utilities; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; using System.Threading; @@ -37,11 +40,14 @@ namespace YunDa.Server.ISMSTcp.Services public double Value { get; set; } public string ValueStr { get; set; } = string.Empty; public DateTime TimeStamp { get; set; } + public uint ValCount { get; set; } = 0; + public DateTime StartTimeStamp { get; set; } = DateTime.MinValue; ///////////////////////////////////////////////////////////////////////////////////// private readonly ConcurrentQueue<(DateTime time, ZzDataPoint point)> _queue = new ConcurrentQueue<(DateTime time, ZzDataPoint point)>(); + public ConcurrentQueue<(DateTime time, ZzDataPoint point)> Datas => _queue; public ZzData(int minutes, string id, string name, int dispatcherAddress) @@ -57,7 +63,7 @@ namespace YunDa.Server.ISMSTcp.Services { DateTime now = DateTime.Now; - point.TimeStamp = now; //2025-11-18 用当前时间(临时修改) + point.TimeStamp = now; //2025-11-18 用当前时间 _queue.Enqueue((now, point)); @@ -65,6 +71,13 @@ namespace YunDa.Server.ISMSTcp.Services Value = point.Value; ValueStr = point.ValueStr; + ////////////////////////////// + ValCount++; + if(StartTimeStamp == DateTime.MinValue) + StartTimeStamp = now; + + + CleanupOldData(); } @@ -125,17 +138,35 @@ namespace YunDa.Server.ISMSTcp.Services public string Id { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; } + + public enum ZzDataCacheContainerDataType + { + eYC = 0, //遥测 + eYX, //遥信 + eVA, //虚点 + eGW //网关 + } public class ZzDataCacheContainer { private readonly ConcurrentDictionary _datas = new ConcurrentDictionary(); private readonly int _cleanupMinutes = 5; - public ZzDataCacheContainer(int cleanupMinutes) + private ZzDataCacheContainerDataType _dataType = ZzDataCacheContainerDataType.eYC; + + private TelemeteringHandle? _telemeteringHandle = null; + + public ZzDataCacheContainer(ZzDataCacheContainerDataType dataType, int cleanupMinutes) { + _dataType = dataType; _cleanupMinutes = cleanupMinutes; } + public void SetTelemeteringHandle(TelemeteringHandle handle) + { + _telemeteringHandle = handle; + } + public void Write(string id, double val, DateTime time, string name) { var data = _datas.GetOrAdd(id, _ => new ZzData(_cleanupMinutes, id, name, 0)); @@ -161,7 +192,7 @@ namespace YunDa.Server.ISMSTcp.Services data.AddData(new ZzDataPoint(time, val, valStr)); } - public Dictionary Read(List ids, DateTime start, DateTime end) + public async Task> Read(List ids, DateTime start, DateTime end) { var result = new Dictionary(); @@ -178,13 +209,35 @@ namespace YunDa.Server.ISMSTcp.Services ZzDataResultModel data = new ZzDataResultModel(channel); data.Data = channel.GetData(start, end); - if(data.Data.Count == 0 && data.TimeStamp != DateTime.MinValue) + bool isFind = data.Data.Count > 0; + + if (data.Data.Count == 0 && data.TimeStamp != DateTime.MinValue) { - ZzDataPoint zzDataPoint = new ZzDataPoint(DateTime.Now, data.Value, data.ValueStr); + ZzDataPoint zzDataPoint = new ZzDataPoint(DateTime.Now, data.Value, data.ValueStr.Replace(" ", "")); data.Data.Add(zzDataPoint); } + if (_telemeteringHandle != null &&_dataType == ZzDataCacheContainerDataType.eYC && id == "YCB001103003") + { + if (data.Data.Where(e => Math.Abs(e.Value) < 0.0001).Count() == data.Data.Count) + { + string time = DateTime.Now.ToString("yyy/MM/dd HH:mm:ss"); + System.Console.WriteLine($"【{time}】: {id}所有值为0[{data.Data.Count}]:状态:{isFind}, Cache长度:{channel.Datas.Count}, Cache时间:{channel.StartTimeStamp.ToString("yyy/MM/dd HH:mm:ss")} ~ {channel.TimeStamp.ToString("yyy/MM/dd HH:mm:ss")}, 最后一个值:{channel.ValueStr}"); + + var redisData = await _telemeteringHandle.GetDataFromRedis(id); + if (redisData != null) + { + System.Console.WriteLine($"【{time}】: {id}在Redis中的值为:{redisData.ResultValue} - {redisData.ResultTime }"); + } + else + { + System.Console.WriteLine($"【{time}】: {id}在Redis中没有找到"); + } + + } + } + result[id] = data; } @@ -206,7 +259,7 @@ namespace YunDa.Server.ISMSTcp.Services if (timeWindowType == 0 || timeWindowType == 2) { - matched1 = Read(ids, now.AddSeconds(-seconds), now); + matched1 = await Read(ids, now.AddSeconds(-seconds), now); } if (timeWindowType == 1 || timeWindowType == 2) @@ -215,7 +268,7 @@ namespace YunDa.Server.ISMSTcp.Services if(span > 0) await Task.Delay(span, cancellationToken); - matched2 = Read(ids, now, DateTime.Now); + matched2 = await Read(ids, now, DateTime.Now); } foreach (var kv in matched2)