Files
DMS/DMS.WPF/ViewModels/Dialogs/ImportOpcUaDialogViewModel.cs
2025-08-25 21:26:18 +08:00

271 lines
9.1 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Core.Models;
using DMS.Helper;
using DMS.Infrastructure.Interfaces.Services;
using DMS.WPF.ViewModels.Items;
using Opc.Ua;
using Opc.Ua.Client;
using System.Collections.ObjectModel;
namespace DMS.WPF.ViewModels.Dialogs;
public partial class ImportOpcUaDialogViewModel : DialogViewModelBase<List<VariableItemViewModel>>
{
[ObservableProperty]
private string _endpointUrl = "opc.tcp://127.0.0.1:4855"; // 默认值
//[ObservableProperty]
//private ObservableCollection<OpcUaNode> _opcUaNodes;
[ObservableProperty]
private ObservableCollection<Variable> _selectedNodeVariables;
public List<Variable> SelectedVariables { get; set; } = new List<Variable>();
[ObservableProperty]
private bool _selectAllVariables;
[ObservableProperty]
private bool _isConnected;
[ObservableProperty]
private string _connectButtonText="连接服务器";
[ObservableProperty]
private bool _isConnectButtonEnabled = true;
private Session _session;
private readonly IOpcUaService _opcUaService;
private CancellationTokenSource _cancellationTokenSource;
public ImportOpcUaDialogViewModel(IOpcUaService opcUaService)
{
//OpcUaNodes = new ObservableCollection<OpcUaNode>();
SelectedNodeVariables = new ObservableCollection<Variable>();
this._opcUaService = opcUaService;
_cancellationTokenSource=new CancellationTokenSource();
}
[RelayCommand]
private async Task Connect()
{
try
{
// 断开现有连接
if (!_opcUaService.IsConnected())
{
await _opcUaService.ConnectAsync(EndpointUrl, _cancellationTokenSource.Token);
}
IsConnected= _opcUaService.IsConnected();
if (IsConnected)
{
ConnectButtonText = "已连接";
IsConnectButtonEnabled = false;
}
// 浏览根节点
var rootNodeId = new NodeId(ObjectIds.ObjectsFolder);
var list=_opcUaService.BrowseNodes(rootNodeId);
//await BrowseNodes(OpcUaNodes, ObjectIds.ObjectsFolder);
}
catch (Exception ex)
{
IsConnected = false;
IsConnectButtonEnabled = false;
ConnectButtonText = "连接服务器";
NotificationHelper.ShowError($"连接 OPC UA 服务器失败: {EndpointUrl} - {ex.Message}", ex);
}
}
/// <summary>
/// 处理来自服务器的数据变化通知
/// </summary>
private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
foreach (var value in item.DequeueValues())
{
Console.WriteLine(
$"[通知] {item.DisplayName}: {value.Value} | 时间戳: {value.SourceTimestamp.ToLocalTime()} | 状态: {value.StatusCode}");
}
}
//private async Task BrowseNodes(ObservableCollection<OpcUaNode> nodes, NodeId parentNodeId)
//{
// try
// {
// Opc.Ua.ReferenceDescriptionCollection references;
// byte[] continuationPoint = null;
// _session.Browse(
// null, // RequestHeader
// new ViewDescription(),
// parentNodeId,
// 0u,
// BrowseDirection.Forward,
// Opc.Ua.ReferenceTypeIds.HierarchicalReferences,
// true,
// (uint)Opc.Ua.NodeClass.Object | (uint)Opc.Ua.NodeClass.Variable,
// out continuationPoint,
// out references
// );
// foreach (var rd in references)
// {
// NodeType nodeType = NodeType.Folder; // 默认是文件夹
// if ((rd.NodeClass & NodeClass.Variable) != 0)
// {
// nodeType = NodeType.Variable;
// }
// else if ((rd.NodeClass & NodeClass.Object) != 0)
// {
// nodeType = NodeType.Object;
// }
// var opcUaNode = new OpcUaNode(rd.DisplayName.Text, (NodeId)rd.NodeId, nodeType);
// nodes.Add(opcUaNode);
// // 如果是文件夹或对象,添加一个虚拟子节点,用于懒加载
// if (nodeType == NodeType.Folder || nodeType == NodeType.Object)
// {
// opcUaNode.Children.Add(new OpcUaNode("Loading...", NodeId.Null, NodeType.Folder)); // 虚拟节点
// }
// }
// }
// catch (Exception ex)
// {
// NlogHelper.Error($"浏览 OPC UA 节点失败: {parentNodeId} - {ex.Message}", ex);
// NotificationHelper.ShowError($"浏览 OPC UA 节点失败: {parentNodeId} - {ex.Message}", ex);
// }
//}
//public async Task LoadNodeVariables(OpcUaNode node)
//{
//if (node.NodeType == NodeType.Variable)
//{
// // 如果是变量节点,直接显示它
// SelectedNodeVariables.Clear();
// SelectedNodeVariables.Add(new Variable
// {
// Name = node.DisplayName,
// NodeId = node.NodeId.ToString(),
// OpcUaNodeId = node.NodeId.ToString(),
// ProtocolType = ProtocolType.OpcUA,
// IsActive = true // 默认选中
// });
// return;
//}
//if (node.IsLoaded || node.IsLoading)
//{
// return; // 已经加载或正在加载
//}
//node.IsLoading = true;
//node.Children.Clear(); // 清除虚拟节点
//try
//{
// Opc.Ua.ReferenceDescriptionCollection references;
// byte[] continuationPoint = null;
// _session.Browse(
// null, // RequestHeader
// new ViewDescription(),
// node.NodeId,
// 0u,
// BrowseDirection.Forward,
// Opc.Ua.ReferenceTypeIds.HierarchicalReferences,
// true,
// (uint)Opc.Ua.NodeClass.Object | (uint)Opc.Ua.NodeClass.Variable,
// out continuationPoint,
// out references
// );
// foreach (var rd in references)
// {
// NodeType nodeType = NodeType.Folder;
// if ((rd.NodeClass & NodeClass.Variable) != 0)
// {
// nodeType = NodeType.Variable;
// }
// else if ((rd.NodeClass & NodeClass.Object) != 0)
// {
// nodeType = NodeType.Object;
// }
// var opcUaNode = new OpcUaNode(rd.DisplayName.Text, (NodeId)rd.NodeId, nodeType);
// node.Children.Add(opcUaNode);
// if (nodeType == NodeType.Folder || nodeType == NodeType.Object)
// {
// opcUaNode.Children.Add(new OpcUaNode("Loading...", NodeId.Null, NodeType.Folder)); // 虚拟节点
// }
// // 如果是变量,添加到右侧列表
// if (nodeType == NodeType.Variable)
// {
// // Read the DataType attribute
// ReadValueId readValueId = new ReadValueId
// {
// NodeId = opcUaNode.NodeId,
// AttributeId = Attributes.DataType,
// // You might need to specify IndexRange and DataEncoding if dealing with arrays or specific encodings
// };
// DataValueCollection results;
// DiagnosticInfoCollection diagnosticInfos;
// _session.Read(
// null, // RequestHeader
// 0, // MaxAge
// TimestampsToReturn.Source,
// new ReadValueIdCollection { readValueId },
// out results,
// out diagnosticInfos
// );
// string dataType = string.Empty;
// if (results != null && results.Count > 0 && results[0].Value != null)
// {
// // Convert the NodeId of the DataType to a readable string
// NodeId dataTypeNodeId = (NodeId)results[0].Value;
// dataType = _session.NodeCache.GetDisplayText(dataTypeNodeId);
// }
// SelectedNodeVariables.Add(new Variable
// {
// Name = opcUaNode.DisplayName,
// OpcUaNodeId = opcUaNode.NodeId.ToString(),
// ProtocolType = ProtocolType.OpcUA,
// IsActive = true, // Default selected
// DataType = dataType // Assign the read DataType
// });
// }
// }
// node.IsLoaded = true;
//}
//catch (Exception ex)
//{
// NlogHelper.Error($"加载 OPC UA 节点变量失败: {node.NodeId} - {ex.Message}", ex);
// NotificationHelper.ShowError($"加载 OPC UA 节点变量失败: {node.NodeId} - {ex.Message}", ex);
//}
//finally
//{
// node.IsLoading = false;
//}
//}
public ObservableCollection<Variable> GetSelectedVariables()
{
return new ObservableCollection<Variable>(SelectedVariables);
}
}