使用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();// 從節點文本中提取NodeIdvar 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線程。
-
錯誤處理:網絡操作容易出錯,確保有適當的錯誤處理和用戶反饋。
-
安全性:生產環境中可能需要配置安全策略和用戶憑據。
-
資源清理:確保在應用程序退出時正確斷開連接。