diff --git a/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs b/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs
index b4027a8..fba08dc 100644
--- a/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs
+++ b/DMS.Infrastructure/Services/OpcUa/OpcUaServiceManager.cs
@@ -48,6 +48,7 @@ namespace DMS.Infrastructure.Services.OpcUa
_eventService.OnDeviceStateChanged += OnDeviceStateChanged;
_eventService.OnDeviceChanged += OnDeviceChanged;
_eventService.OnBatchImportVariables += OnBatchImportVariables;
+ _eventService.OnVariableChanged += OnVariableChanged;
}
private async void OnDeviceStateChanged(object? sender, DeviceStateChangedEventArgs e)
@@ -232,6 +233,22 @@ namespace DMS.Infrastructure.Services.OpcUa
}
}
+ ///
+ /// 获取需要订阅的变量列表
+ ///
+ /// 设备上下文
+ /// 需要订阅的变量列表
+ private List GetSubscribableVariables(DeviceContext context)
+ {
+ if (context?.Variables == null)
+ return new List();
+
+ // 返回所有激活且OPC UA更新类型不是None的变量
+ return context.Variables.Values
+ .Where(v => v.IsActive )
+ .ToList();
+ }
+
///
/// 处理批量导入变量事件
///
@@ -471,16 +488,25 @@ namespace DMS.Infrastructure.Services.OpcUa
///
private async Task SetupSubscriptionsAsync(DeviceContext context, CancellationToken cancellationToken = default)
{
- if (!context.IsConnected || !context.Variables.Any())
+ if (!context.IsConnected)
return;
try
{
- _logger.LogInformation("正在为设备 {DeviceName} 设置订阅,变量数: {VariableCount}",
- context.Device.Name, context.Variables.Count);
+ // 获取需要订阅的变量
+ var subscribableVariables = GetSubscribableVariables(context);
+
+ if (!subscribableVariables.Any())
+ {
+ _logger.LogInformation("设备 {DeviceName} 没有需要订阅的变量", context.Device.Name);
+ return;
+ }
+
+ _logger.LogInformation("正在为设备 {DeviceName} 设置订阅,需要订阅的变量数: {VariableCount}",
+ context.Device.Name, subscribableVariables.Count);
// 按PollingInterval对变量进行分组
- var variablesByPollingInterval = context.Variables.Values
+ var variablesByPollingInterval = subscribableVariables
.GroupBy(v => v.PollingInterval)
.ToDictionary(g => g.Key, g => g.ToList());
@@ -494,7 +520,6 @@ namespace DMS.Infrastructure.Services.OpcUa
"为设备 {DeviceName} 设置PollingInterval {PollingInterval} 的订阅,变量数: {VariableCount}",
context.Device.Name, pollingInterval, variables.Count);
-
var opcUaNodes = variables
.Select(v => new OpcUaNode { NodeId = v.OpcUaNodeId })
.ToList();
@@ -512,29 +537,6 @@ namespace DMS.Infrastructure.Services.OpcUa
}
}
- ///
- /// 根据PollingInterval获取发布间隔(毫秒)
- ///
- private int GetPublishingIntervalFromPollLevel(int pollingInterval)
- {
- // 根据轮询间隔值映射到发布间隔
- return pollingInterval switch
- {
- 100 => 100, // HundredMilliseconds -> 100ms发布间隔
- 500 => 500, // FiveHundredMilliseconds -> 500ms发布间隔
- 1000 => 1000, // OneSecond -> 1000ms发布间隔
- 5000 => 5000, // FiveSeconds -> 5000ms发布间隔
- 10000 => 10000, // TenSeconds -> 10000ms发布间隔
- 20000 => 20000, // TwentySeconds -> 20000ms发布间隔
- 30000 => 30000, // ThirtySeconds -> 30000ms发布间隔
- 60000 => 60000, // OneMinute -> 60000ms发布间隔
- 300000 => 300000, // FiveMinutes -> 300000ms发布间隔
- 600000 => 600000, // TenMinutes -> 600000ms发布间隔
- 1800000 => 1800000, // ThirtyMinutes -> 1800000ms发布间隔
- 3600000 => 3600000, // OneHour -> 3600000ms发布间隔
- _ => _options.SubscriptionPublishingIntervalMs // 默认值
- };
- }
///
@@ -661,6 +663,80 @@ namespace DMS.Infrastructure.Services.OpcUa
_logger.LogInformation("OPC UA服务管理器资源已释放");
}
}
+
+ ///
+ /// 处理变量变更事件
+ ///
+ private void OnVariableChanged(object? sender, VariableChangedEventArgs e)
+ {
+ try
+ {
+ _logger.LogDebug("处理变量变更事件: 变量ID={VariableId}, 变更类型={ChangeType}, 变更属性={PropertyType}",
+ e.Variable.Id, e.ChangeType, e.PropertyType);
+
+ // 根据变更类型和属性类型进行相应处理
+ switch (e.ChangeType)
+ {
+ case ActionChangeType.Updated:
+ // 如果变量的OPC UA相关属性发生变化,需要重新设置订阅
+ switch (e.PropertyType)
+ {
+ case VariablePropertyType.OpcUaNodeId:
+ case VariablePropertyType.OpcUaUpdateType:
+ case VariablePropertyType.PollingInterval:
+ // 重新设置设备的订阅
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context))
+ {
+ _ = Task.Run(async () =>
+ {
+ try
+ {
+ await SetupSubscriptionsAsync(context, CancellationToken.None);
+ _logger.LogInformation("已更新设备 {DeviceId} 的订阅,因为变量 {VariableId} 的OPC UA属性发生了变化",
+ e.Variable.VariableTable.DeviceId, e.Variable.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "更新设备 {DeviceId} 订阅时发生错误", e.Variable.VariableTable.DeviceId);
+ }
+ });
+ }
+ break;
+
+ case VariablePropertyType.IsActive:
+ // 变量激活状态变化,更新变量列表
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context2))
+ {
+ if (e.Variable.IsActive)
+ {
+ // 添加变量到监控列表
+ context2.Variables.AddOrUpdate(e.Variable.OpcUaNodeId, e.Variable, (key, oldValue) => e.Variable);
+ }
+ else
+ {
+ // 从监控列表中移除变量
+ context2.Variables.Remove(e.Variable.OpcUaNodeId, out _);
+ }
+ }
+ break;
+ }
+ break;
+
+ case ActionChangeType.Deleted:
+ // 变量被删除时,从设备上下文的变量列表中移除
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context3))
+ {
+ context3.Variables.Remove(e.Variable.OpcUaNodeId, out _);
+ }
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "处理变量变更事件时发生错误: 变量ID={VariableId}, 变更类型={ChangeType}",
+ e.Variable.Id, e.ChangeType);
+ }
+ }
}
///
diff --git a/DMS.Infrastructure/Services/S7/S7ServiceManager.cs b/DMS.Infrastructure/Services/S7/S7ServiceManager.cs
index 98fb9e5..086d501 100644
--- a/DMS.Infrastructure/Services/S7/S7ServiceManager.cs
+++ b/DMS.Infrastructure/Services/S7/S7ServiceManager.cs
@@ -47,6 +47,7 @@ namespace DMS.Infrastructure.Services.S7
_eventService.OnVariableActiveChanged += OnVariableActiveChanged;
_eventService.OnBatchImportVariables += OnBatchImportVariables;
+ _eventService.OnVariableChanged += OnVariableChanged;
}
private void OnVariableActiveChanged(object? sender, VariablesActiveChangedEventArgs e)
@@ -407,6 +408,71 @@ namespace DMS.Infrastructure.Services.S7
_logger.LogError(ex, "处理批量导入变量事件时发生错误");
}
}
+
+ ///
+ /// 处理变量变更事件
+ ///
+ private void OnVariableChanged(object? sender, VariableChangedEventArgs e)
+ {
+ try
+ {
+ _logger.LogDebug("处理变量变更事件: 变量ID={VariableId}, 变更类型={ChangeType}, 变更属性={PropertyType}",
+ e.Variable.Id, e.ChangeType, e.PropertyType);
+
+ // 根据变更类型和属性类型进行相应处理
+ switch (e.ChangeType)
+ {
+ case ActionChangeType.Updated:
+ // 如果变量的S7相关属性发生变化
+ switch (e.PropertyType)
+ {
+ case VariablePropertyType.S7Address:
+ // S7地址变化,需要更新设备上下文中的变量映射
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context))
+ {
+ // 先移除旧地址的变量
+ context.Variables.Remove(e.Variable.S7Address, out _);
+ // 添加新地址的变量
+ context.Variables.AddOrUpdate(e.Variable.S7Address, e.Variable, (key, oldValue) => e.Variable);
+ _logger.LogInformation("已更新设备 {DeviceId} 中变量 {VariableId} 的S7地址映射",
+ e.Variable.VariableTable.DeviceId, e.Variable.Id);
+ }
+ break;
+
+ case VariablePropertyType.IsActive:
+ // 变量激活状态变化,更新变量列表
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context2))
+ {
+ if (e.Variable.IsActive)
+ {
+ // 添加变量到监控列表
+ context2.Variables.AddOrUpdate(e.Variable.S7Address, e.Variable, (key, oldValue) => e.Variable);
+ }
+ else
+ {
+ // 从监控列表中移除变量
+ context2.Variables.Remove(e.Variable.S7Address, out _);
+ }
+ }
+ break;
+ }
+ break;
+
+ case ActionChangeType.Deleted:
+ // 变量被删除时,从设备上下文的变量列表中移除
+ if (_deviceContexts.TryGetValue(e.Variable.VariableTable.DeviceId, out var context3))
+ {
+ context3.Variables.Remove(e.Variable.S7Address, out _);
+ }
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "处理变量变更事件时发生错误: 变量ID={VariableId}, 变更类型={ChangeType}",
+ e.Variable.Id, e.ChangeType);
+ }
+ }
}
///
diff --git a/DMS.WPF/ViewModels/VariableTableViewModel.cs b/DMS.WPF/ViewModels/VariableTableViewModel.cs
index f9c7d1d..cca154d 100644
--- a/DMS.WPF/ViewModels/VariableTableViewModel.cs
+++ b/DMS.WPF/ViewModels/VariableTableViewModel.cs
@@ -723,7 +723,7 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
if (result > 0)
{
- _eventService.RaiseVariableActiveChanged(this,new VariablesActiveChangedEventArgs(validVariables.Select(v=>v.Id).ToList(),CurrentVariableTable.DeviceId,newIsActive.Value));
+ // _eventService.RaiseVariableActiveChanged(this,new VariablesActiveChangedEventArgs(validVariables.Select(v=>v.Id).ToList(),CurrentVariableTable.DeviceId,newIsActive.Value));
// 显示成功通知
_notificationService.ShowSuccess($"已成功更新 {validVariables.Count} 个变量的启用状态");
}