From 831f342b2cbe4a8f7d1a1b84adc19bd19a4878f8 Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Fri, 5 Sep 2025 07:03:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E5=8F=98?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interfaces/IDataCenterService.cs | 9 ++++ DMS.Application/Services/DataCenterService.cs | 18 ++++++++ .../Models/VariableValueChangedEventArgs.cs | 45 +++++++++++++++++++ .../Extensions/OpcUaServiceExtensions.cs | 14 +++++- .../Services/OpcUaServiceManager.cs | 22 ++++++++- DMS.WPF/Services/DataServices.cs | 39 ++++++++++++++-- 6 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 DMS.Core/Models/VariableValueChangedEventArgs.cs diff --git a/DMS.Application/Interfaces/IDataCenterService.cs b/DMS.Application/Interfaces/IDataCenterService.cs index 6727e98..cd0a8e8 100644 --- a/DMS.Application/Interfaces/IDataCenterService.cs +++ b/DMS.Application/Interfaces/IDataCenterService.cs @@ -1,6 +1,7 @@ using System.Collections.Concurrent; using DMS.Application.DTOs; using DMS.Application.DTOs.Events; +using DMS.Core.Models; namespace DMS.Application.Interfaces; @@ -305,5 +306,13 @@ public interface IDataCenterService /// event EventHandler DataChanged; + /// + /// 当变量值发生变化时触发 + /// + event EventHandler VariableValueChanged; + + void OnVariableValueChanged(VariableValueChangedEventArgs e); + + #endregion } \ No newline at end of file diff --git a/DMS.Application/Services/DataCenterService.cs b/DMS.Application/Services/DataCenterService.cs index 99dc74e..f57f4df 100644 --- a/DMS.Application/Services/DataCenterService.cs +++ b/DMS.Application/Services/DataCenterService.cs @@ -1,6 +1,7 @@ using AutoMapper; using DMS.Application.DTOs; using DMS.Application.DTOs.Events; +using DMS.Core.Models; using DMS.Application.Interfaces; using DMS.Core.Interfaces; using DMS.Core.Models; @@ -83,6 +84,11 @@ public class DataCenterService : IDataCenterService /// public event EventHandler DataChanged; + /// + /// 当变量值发生变化时触发 + /// + public event EventHandler VariableValueChanged; + #endregion /// @@ -823,4 +829,16 @@ public class DataCenterService : IDataCenterService } #endregion + + #region 事件触发方法 + + /// + /// 触发变量值变更事件 + /// + public virtual void OnVariableValueChanged(VariableValueChangedEventArgs e) + { + VariableValueChanged?.Invoke(this, e); + } + + #endregion } \ No newline at end of file diff --git a/DMS.Core/Models/VariableValueChangedEventArgs.cs b/DMS.Core/Models/VariableValueChangedEventArgs.cs new file mode 100644 index 0000000..76f8376 --- /dev/null +++ b/DMS.Core/Models/VariableValueChangedEventArgs.cs @@ -0,0 +1,45 @@ +namespace DMS.Core.Models +{ + /// + /// 变量值变更事件参数 + /// + public class VariableValueChangedEventArgs : EventArgs + { + /// + /// 变量ID + /// + public int VariableId { get; set; } + + /// + /// 变量名称 + /// + public string VariableName { get; set; } + + /// + /// 旧值 + /// + public string OldValue { get; set; } + + /// + /// 新值 + /// + public string NewValue { get; set; } + + /// + /// 更新时间 + /// + public DateTime UpdateTime { get; set; } + + /// + /// 构造函数 + /// + public VariableValueChangedEventArgs(int variableId, string variableName, string oldValue, string newValue, DateTime updateTime) + { + VariableId = variableId; + VariableName = variableName; + OldValue = oldValue; + NewValue = newValue; + UpdateTime = updateTime; + } + } +} \ No newline at end of file diff --git a/DMS.Infrastructure/Extensions/OpcUaServiceExtensions.cs b/DMS.Infrastructure/Extensions/OpcUaServiceExtensions.cs index e495d91..d42a867 100644 --- a/DMS.Infrastructure/Extensions/OpcUaServiceExtensions.cs +++ b/DMS.Infrastructure/Extensions/OpcUaServiceExtensions.cs @@ -1,3 +1,4 @@ +using DMS.Application.Interfaces; using DMS.Infrastructure.Configuration; using DMS.Infrastructure.Interfaces.Services; using DMS.Infrastructure.Services; @@ -15,7 +16,18 @@ namespace DMS.Infrastructure.Extensions /// public static IServiceCollection AddOpcUaServices(this IServiceCollection services) { - + // 注册配置选项 + services.Configure( + options => { + // 可以从配置文件或其他来源加载配置 + }); + + // 注册服务 + services.AddSingleton(); + + // 注册后台服务 + services.AddHostedService(); + return services; } } diff --git a/DMS.Infrastructure/Services/OpcUaServiceManager.cs b/DMS.Infrastructure/Services/OpcUaServiceManager.cs index 2728883..1cb3f44 100644 --- a/DMS.Infrastructure/Services/OpcUaServiceManager.cs +++ b/DMS.Infrastructure/Services/OpcUaServiceManager.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using DMS.Application.DTOs; using DMS.Application.Interfaces; using DMS.Core.Enums; +using DMS.Core.Models; using DMS.Infrastructure.Configuration; using DMS.Infrastructure.Interfaces.Services; using DMS.Infrastructure.Models; @@ -18,6 +19,7 @@ namespace DMS.Infrastructure.Services { private readonly ILogger _logger; private readonly IDataProcessingService _dataProcessingService; + private readonly IDataCenterService _dataCenterService; private readonly OpcUaServiceOptions _options; private readonly ConcurrentDictionary _deviceContexts; private readonly SemaphoreSlim _semaphore; @@ -26,10 +28,12 @@ namespace DMS.Infrastructure.Services public OpcUaServiceManager( ILogger logger, IDataProcessingService dataProcessingService, + IDataCenterService dataCenterService, IOptions options) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _dataProcessingService = dataProcessingService ?? throw new ArgumentNullException(nameof(dataProcessingService)); + _dataCenterService = dataCenterService ?? throw new ArgumentNullException(nameof(dataCenterService)); _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); _deviceContexts = new ConcurrentDictionary(); _semaphore = new SemaphoreSlim(_options.MaxConcurrentConnections, _options.MaxConcurrentConnections); @@ -287,11 +291,25 @@ namespace DMS.Infrastructure.Services { if (context.Variables.TryGetValue(opcUaNode.NodeId.ToString(), out var variable)) { + // 保存旧值 + var oldValue = variable.DataValue; + var newValue = opcUaNode.Value.ToString(); + // 更新变量值 - variable.DataValue = opcUaNode.Value.ToString(); - variable.DisplayValue = opcUaNode.Value.ToString(); + variable.DataValue = newValue; + variable.DisplayValue = newValue; variable.UpdatedAt = DateTime.Now; + // 触发变量值变更事件 + var eventArgs = new VariableValueChangedEventArgs( + variable.Id, + variable.Name, + oldValue, + newValue, + variable.UpdatedAt); + + _dataCenterService.OnVariableValueChanged( eventArgs); + // 推送到数据处理队列 await _dataProcessingService.EnqueueAsync(variable); break; diff --git a/DMS.WPF/Services/DataServices.cs b/DMS.WPF/Services/DataServices.cs index 7cea523..57f54ce 100644 --- a/DMS.WPF/Services/DataServices.cs +++ b/DMS.WPF/Services/DataServices.cs @@ -1,7 +1,9 @@ using System.Collections.ObjectModel; +using System.Windows; using AutoMapper; using CommunityToolkit.Mvvm.ComponentModel; using DMS.Application.DTOs; +using DMS.Core.Models; using DMS.Application.Interfaces; using DMS.Core.Enums; using DMS.Core.Models; @@ -13,7 +15,7 @@ namespace DMS.WPF.Services; /// 数据服务类,负责从数据库加载和管理各种数据,并提供数据变更通知。 /// 继承自ObservableRecipient,可以接收消息;实现IRecipient,处理加载消息。 /// -public partial class DataServices : ObservableObject +public partial class DataServices : ObservableObject, IDisposable { private readonly IMapper _mapper; private readonly IDataCenterService _dataCenterService; @@ -53,8 +55,24 @@ public partial class DataServices : ObservableObject // MQTT列表变更事件,当MQTT配置数据更新时触发。 // public event Action> OnMqttListChanged; - // 设备IsActive状态变更事件,当单个设备的IsActive状态改变时触发。 - public event Action OnDeviceIsActiveChanged; + /// + /// 处理变量值变更事件 + /// + private void OnVariableValueChanged(object sender, VariableValueChangedEventArgs e) + { + // 在UI线程上更新变量值 + App.Current.Dispatcher.BeginInvoke(new Action(() => + { + // 查找并更新对应的变量 + var variableToUpdate = Variables.FirstOrDefault(v => v.Id == e.VariableId); + if (variableToUpdate != null) + { + variableToUpdate.DataValue = e.NewValue; + variableToUpdate.DisplayValue = e.NewValue; + variableToUpdate.UpdatedAt = e.UpdateTime; + } + })); + } /// @@ -73,6 +91,9 @@ public partial class DataServices : ObservableObject Menus = new ObservableCollection(); MenuTrees = new ObservableCollection(); // AllVariables = new ConcurrentDictionary(); + + // 监听变量值变更事件 + _dataCenterService.VariableValueChanged += OnVariableValueChanged; } @@ -358,4 +379,16 @@ public partial class DataServices : ObservableObject Variables.Remove(variableItem); } + + /// + /// 释放资源 + /// + public void Dispose() + { + // 取消事件订阅 + if (_dataCenterService != null) + { + _dataCenterService.VariableValueChanged -= OnVariableValueChanged; + } + } } \ No newline at end of file