From 745cd43513083cfa61aa26e1ad11ee38f60b7138 Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Thu, 2 Oct 2025 22:30:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4=E5=AF=B9?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=BF=9B=E8=A1=8C=E4=BA=86=E4=B8=A4=E9=A1=B9?= =?UTF-8?q?=E4=B8=BB=E8=A6=81=E7=9A=84=E9=87=8D=E6=9E=84=E5=92=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 重构数据处理链: * 移除了 CheckValueChangedProcessor 和 LoggingProcessor,简化了数据处理流程。 * 调整了 App.xaml.cs 中的处理器注册顺序,使处理链更加清晰。 2. 优化OPC UA变量变更处理: * 完全重构了 OpcUaServiceManager 中的 OnVariableChanged 事件处理方法。 * 新逻辑能够根据变量属性(IsActive, PollingInterval 等)的变化,进行精确的、针对单个节点的订阅和取消订阅操作,取代了之前重置整个设备订阅的低效方式。 * 实现了对已删除变量的订阅取消逻辑,确保了资源的正确释放。 这些变更显著提升了 OPC UA 订阅管理的效率和精确性。 --- .../Processors/CheckValueChangedProcessor.cs | 30 --------- .../Services/Processors/LoggingProcessor.cs | 22 ------- .../Processors/UpdateDbVariableProcessor.cs | 8 --- .../Services/OpcUa/OpcUaServiceManager.cs | 61 +++++++++++-------- DMS.WPF/App.xaml.cs | 6 +- 5 files changed, 35 insertions(+), 92 deletions(-) delete mode 100644 DMS.Application/Services/Processors/CheckValueChangedProcessor.cs delete mode 100644 DMS.Application/Services/Processors/LoggingProcessor.cs diff --git a/DMS.Application/Services/Processors/CheckValueChangedProcessor.cs b/DMS.Application/Services/Processors/CheckValueChangedProcessor.cs deleted file mode 100644 index 40aa75c..0000000 --- a/DMS.Application/Services/Processors/CheckValueChangedProcessor.cs +++ /dev/null @@ -1,30 +0,0 @@ -using DMS.Core.Models; -using DMS.Application.Interfaces; -using DMS.Application.Models; - -namespace DMS.Application.Services.Processors; - -public class CheckValueChangedProcessor : IVariableProcessor -{ - - - public Task ProcessAsync(VariableContext context) - { - // Variable newVariable = context.Data; - // if (!_dataServices.AllVariables.TryGetValue(newVariable.Id, out Variable oldVariable)) - // { - // NlogHelper.Warn($"检查变量值是否改变时在_dataServices.AllVariables中找不到Id:{newVariable.Id},Name:{newVariable.Name}的变量。"); - // context.IsHandled = true; - // return Task.CompletedTask; - // } - - // if (newVariable.DataValue == oldVariable.DataValue) - // { - // // 值没有变化,直接完成 - // context.IsHandled = true; - // } - // - // 在这里处理 context.Data - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/DMS.Application/Services/Processors/LoggingProcessor.cs b/DMS.Application/Services/Processors/LoggingProcessor.cs deleted file mode 100644 index c2c7725..0000000 --- a/DMS.Application/Services/Processors/LoggingProcessor.cs +++ /dev/null @@ -1,22 +0,0 @@ -using DMS.Application.Interfaces; -using DMS.Application.Models; - - -namespace DMS.Application.Services.Processors; - -/// -/// 一个简单的数据处理器实现,用于演示。 -/// 其主要功能是记录接收到的变量数据的名称和值。 -/// -public class LoggingProcessor : IVariableProcessor -{ - public LoggingProcessor() - { - } - - public Task ProcessAsync(VariableContext context) - { - // NlogHelper.Info($"处理数据: {context.Data.Name}, 值: {context.Data.DataValue}"); - return Task.CompletedTask; - } -} diff --git a/DMS.Application/Services/Processors/UpdateDbVariableProcessor.cs b/DMS.Application/Services/Processors/UpdateDbVariableProcessor.cs index d619b39..c620a60 100644 --- a/DMS.Application/Services/Processors/UpdateDbVariableProcessor.cs +++ b/DMS.Application/Services/Processors/UpdateDbVariableProcessor.cs @@ -37,14 +37,6 @@ public class UpdateDbVariableProcessor : IVariableProcessor, IDisposable public async Task ProcessAsync(VariableContext context) { - // 检查新值是否有效,以及是否与旧值不同 - if (context.NewValue == null || Equals(context.Data.DataValue, context.NewValue?.ToString())) - { - return; // 值未变或新值无效,跳过 - } - - // 用新值更新上下文中的数据,确保处理链的后续环节能看到最新值 - context.Data.DataValue = context.NewValue?.ToString(); _queue.Enqueue(context.Data); diff --git a/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs b/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs index 7571f46..9a14bff 100644 --- a/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs +++ b/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs @@ -488,7 +488,6 @@ namespace DMS.Infrastructure.Services.OpcUa try { - _logger.LogInformation("正在为设备 {DeviceName} 设置订阅,需要订阅的变量数: {VariableCount}", context.Device.Name, context.Variables.Count); @@ -508,8 +507,8 @@ namespace DMS.Infrastructure.Services.OpcUa context.Device.Name, pollingInterval, variables.Count); var opcUaNodeIds = variables - .Select(v => v.OpcUaNodeId) - .ToList(); + .Select(v => v.OpcUaNodeId) + .ToList(); context.OpcUaService.SubscribeToNode(opcUaNodeIds, HandleDataChanged, pollingInterval, pollingInterval); @@ -665,6 +664,11 @@ namespace DMS.Infrastructure.Services.OpcUa _logger.LogDebug("处理变量变更事件: 变量ID={VariableId}, 变更类型={ChangeType}, 变更属性={PropertyType}", e.Variable.Id, e.ChangeType, e.PropertyType); + if (!_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context)) + { + return; + } + // 根据变更类型和属性类型进行相应处理 switch (e.ChangeType) { @@ -675,41 +679,39 @@ namespace DMS.Infrastructure.Services.OpcUa case VariablePropertyType.OpcUaNodeId: case VariablePropertyType.OpcUaUpdateType: case VariablePropertyType.PollingInterval: - if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context)) + if (context.Variables.TryGetValue(e.Variable.OpcUaNodeId, out var variableDto)) { - if (context.Variables.TryGetValue(e.Variable.OpcUaNodeId,out var variableDto)) + if (variableDto.IsActive) { - if (variableDto.IsActive) - { - context.OpcUaService.UnsubscribeFromNode(e.Variable.OpcUaNodeId); - context.OpcUaService.SubscribeToNode(e.Variable.OpcUaNodeId,HandleDataChanged,e.Variable.PollingInterval,e.Variable.PollingInterval); - _logger.LogInformation($"OpcUa变量节点:{e.Variable.OpcUaNodeId},的轮询时间修改为:{e.Variable.PollingInterval}"); - } - + context.OpcUaService.UnsubscribeFromNode(e.Variable.OpcUaNodeId); + context.OpcUaService.SubscribeToNode( + e.Variable.OpcUaNodeId, HandleDataChanged, e.Variable.PollingInterval, + e.Variable.PollingInterval); + _logger.LogInformation( + $"OpcUa变量节点:{e.Variable.OpcUaNodeId},的轮询时间修改为:{e.Variable.PollingInterval}"); } - } + break; case VariablePropertyType.IsActive: // 变量激活状态变化 - if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context2)) + if (e.Variable.IsActive) { - if (e.Variable.IsActive) + // 添加变量到监控列表并重新订阅 + if (context.Variables.TryAdd(e.Variable.OpcUaNodeId, e.Variable)) { - // 添加变量到监控列表并重新订阅 - if (context2.Variables.TryAdd(e.Variable.OpcUaNodeId, e.Variable)) - { - context2.OpcUaService.SubscribeToNode(e.Variable.OpcUaNodeId,HandleDataChanged,e.Variable.PollingInterval,e.Variable.PollingInterval); - } + context.OpcUaService.SubscribeToNode( + e.Variable.OpcUaNodeId, HandleDataChanged, e.Variable.PollingInterval, + e.Variable.PollingInterval); } - else + } + else + { + // 从监控列表中移除变量并取消订阅 + if (context.Variables.TryRemove(e.Variable.OpcUaNodeId, out _)) { - // 从监控列表中移除变量并取消订阅 - if (context2.Variables.TryRemove(e.Variable.OpcUaNodeId, out _)) - { - context2.OpcUaService.UnsubscribeFromNode(e.Variable.OpcUaNodeId); - } + context.OpcUaService.UnsubscribeFromNode(e.Variable.OpcUaNodeId); } } @@ -720,7 +722,12 @@ namespace DMS.Infrastructure.Services.OpcUa case ActionChangeType.Deleted: // 变量被删除时,取消订阅并从设备上下文的变量列表中移除 - // await UnsubscribeVariableAsync(e.Variable); + // 从监控列表中移除变量并取消订阅 + if (context.Variables.TryRemove(e.Variable.OpcUaNodeId, out _)) + { + context.OpcUaService.UnsubscribeFromNode(e.Variable.OpcUaNodeId); + } + break; } } diff --git a/DMS.WPF/App.xaml.cs b/DMS.WPF/App.xaml.cs index 929c2c4..e5a335d 100644 --- a/DMS.WPF/App.xaml.cs +++ b/DMS.WPF/App.xaml.cs @@ -80,11 +80,9 @@ public partial class App : System.Windows.Application var dataProcessingService = Host.Services.GetRequiredService(); dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); - dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); - dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); - dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); + dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); // 添加报警处理器 dataProcessingService.AddProcessor(Host.Services.GetRequiredService()); // 添加触发器处理器 @@ -204,8 +202,6 @@ public partial class App : System.Windows.Application (DataProcessingService)provider.GetRequiredService()); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton();