云计算百科
云计算领域专业知识百科平台

使用OpcUaHelper在C# WinForms中连接OPC UA服务器并读取数据

使用OpcUaHelper在C# WinForms中连接OPC UA服务器并读取数据

下面是一个完整的示例,展示如何使用OpcUaHelper库在C# WinForms应用程序中连接OPC UA服务器并读取数据。

1. 准备工作

首先,确保你已经安装了OpcUaHelper NuGet包。可以通过NuGet包管理器控制台安装:

Install-Package OpcUaHelper

2. 创建WinForms应用程序

2.1 设计界面

创建一个简单的WinForms窗体,包含以下控件:

  • 文本框:用于输入服务器URL
  • 连接/断开按钮
  • 节点ID文本框
  • 读取按钮
  • 数据显示区域(如DataGridView或ListBox)

2.2 完整代码示例

using OpcUaHelper;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace OpcUaWinFormsClient
{
public partial class MainForm : Form
{
private OpcUaClient opcUaClient = new OpcUaClient();
private bool isConnected = false;

public MainForm()
{
InitializeComponent();
UpdateUiState();
}

private void btnConnect_Click(object sender, EventArgs e)
{
if (!isConnected)
{
ConnectToServer();
}
else
{
DisconnectFromServer();
}
}

private async void ConnectToServer()
{
string serverUrl = txtServerUrl.Text.Trim();

if (string.IsNullOrEmpty(serverUrl))
{
MessageBox.Show("请输入有效的服务器URL");
return;
}

try
{
btnConnect.Enabled = false;
lblStatus.Text = "正在连接…";

// 连接到服务器
await opcUaClient.ConnectServerAsync(serverUrl);

isConnected = true;
lblStatus.Text = "已连接";
MessageBox.Show("连接成功!");
}
catch (Exception ex)
{
lblStatus.Text = "连接失败";
MessageBox.Show($"连接失败: {ex.Message}");
}
finally
{
btnConnect.Enabled = true;
UpdateUiState();
}
}

private void DisconnectFromServer()
{
try
{
opcUaClient.Disconnect();
isConnected = false;
lblStatus.Text = "已断开";
}
catch (Exception ex)
{
MessageBox.Show($"断开连接时出错: {ex.Message}");
}
finally
{
UpdateUiState();
}
}

private void UpdateUiState()
{
btnConnect.Text = isConnected ? "断开连接" : "连接";
btnRead.Enabled = isConnected;
txtNodeId.Enabled = isConnected;
}

private async void btnRead_Click(object sender, EventArgs e)
{
string nodeId = txtNodeId.Text.Trim();

if (string.IsNullOrEmpty(nodeId))
{
MessageBox.Show("请输入节点ID");
return;
}

try
{
btnRead.Enabled = false;

// 读取单个节点值
var value = await opcUaClient.ReadNodeAsync(nodeId);

// 显示读取结果
lstResults.Items.Add($"节点: {nodeId}, 值: {value}, 类型: {value?.GetType()}");
lstResults.TopIndex = lstResults.Items.Count 1;
}
catch (Exception ex)
{
MessageBox.Show($"读取数据时出错: {ex.Message}");
}
finally
{
btnRead.Enabled = true;
}
}

private async void btnBrowse_Click(object sender, EventArgs e)
{
try
{
treeNodes.Nodes.Clear();
var rootNode = treeNodes.Nodes.Add("Root");

// 浏览服务器节点
await BrowseNodeAsync("i=84", rootNode); // Objects文件夹通常是i=84
}
catch (Exception ex)
{
MessageBox.Show($"浏览节点时出错: {ex.Message}");
}
}

private async Task BrowseNodeAsync(string nodeId, TreeNode parentTreeNode)
{
var references = await opcUaClient.BrowseNodeReferenceAsync(nodeId);

foreach (var reference in references)
{
var childNode = parentTreeNode.Nodes.Add($"{reference.DisplayName} ({reference.NodeId})");

// 如果是文件夹/对象类型,添加一个虚拟子节点以便展开
if (reference.NodeClass == Opc.Ua.NodeClass.Object ||
reference.NodeClass == Opc.Ua.NodeClass.Variable)
{
childNode.Nodes.Add("加载中…");
}
}
}

private async void treeNodes_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
var node = e.Node;

// 如果只有一个"加载中…"子节点,则实际加载子节点
if (node.Nodes.Count == 1 && node.Nodes[0].Text == "加载中…")
{
try
{
node.Nodes.Clear();

// 从节点文本中提取NodeId
var nodeId = ExtractNodeIdFromTreeNode(node);

if (!string.IsNullOrEmpty(nodeId))
{
await BrowseNodeAsync(nodeId, node);
}
}
catch (Exception ex)
{
MessageBox.Show($"加载子节点时出错: {ex.Message}");
node.Nodes.Add($"错误: {ex.Message}");
}
}
}

private string ExtractNodeIdFromTreeNode(TreeNode node)
{
// 从类似 "DisplayName (ns=2;s=MyVariable)" 的文本中提取 "ns=2;s=MyVariable"
var text = node.Text;
var start = text.IndexOf('(') + 1;
var end = text.IndexOf(')');

if (start > 0 && end > start)
{
return text.Substring(start, end start);
}

return null;
}

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (isConnected)
{
DisconnectFromServer();
}
}
}
}

3. 功能说明

  • 连接/断开服务器:

    • 使用ConnectServerAsync方法异步连接
    • 使用Disconnect方法断开连接
  • 读取节点数据:

    • 使用ReadNodeAsync方法读取单个节点值
    • 支持所有OPC UA数据类型
  • 浏览服务器节点:

    • 使用BrowseNodeReferenceAsync方法浏览节点引用
    • 实现树形视图的延迟加载
  • 错误处理:

    • 对所有OPC UA操作进行适当的错误处理
  • 4. 扩展功能

    你可以根据需要扩展此示例,添加以下功能:

  • 写入数据:

    await opcUaClient.WriteNodeAsync(nodeId, value);

  • 订阅数据变化:

    // 创建订阅
    var subscription = new OpcUaHelper.Subscription(opcUaClient);

    // 添加监控项
    subscription.AddItem(nodeId);

    // 数据变化事件
    subscription.DataChangeReceived += (s, e) =>
    {
    // 处理数据变化
    };

    // 启动订阅
    await subscription.ApplyAsync();

  • 调用方法:

    var results = await opcUaClient.CallMethodByNodeIdAsync(objectNodeId, methodNodeId, inputArguments);

  • 5. 注意事项

  • 异步编程:所有OPC UA操作都应使用异步方法,避免阻塞UI线程。

  • 错误处理:网络操作容易出错,确保有适当的错误处理和用户反馈。

  • 安全性:生产环境中可能需要配置安全策略和用户凭据。

  • 资源清理:确保在应用程序退出时正确断开连接。

  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 使用OpcUaHelper在C# WinForms中连接OPC UA服务器并读取数据
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!