C# 如何使用OpcUaHelper讀寫OPC服務(wù)器
更新時間:2023年12月01日 11:56:17 作者:羅迪尼亞的熔巖
這篇文章給大家介紹C# 如何使用OpcUaHelper讀寫OPC服務(wù)器,本文通過圖文實例代碼相結(jié)合給大家介紹的非常詳細,需要的朋友參考下吧
nuget包
幫助類:
using Opc.Ua.Client; using Opc.Ua; using OpcUaHelper; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading.Tasks; namespace MyOPCUATest { public class OPCUAHelper { #region 基礎(chǔ)參數(shù) //OPCUA客戶端 private OpcUaClient opcUaClient; #endregion /// <summary> /// 構(gòu)造函數(shù) /// </summary> public OPCUAHelper() { opcUaClient = new OpcUaClient(); } /// <summary> /// 連接狀態(tài) /// </summary> public bool ConnectStatus { get { return opcUaClient.Connected; } } #region 公有方法 /// <summary> /// 打開連接【匿名方式】 /// </summary> /// <param name="serverUrl">服務(wù)器URL【格式:opc.tcp://服務(wù)器IP地址/服務(wù)名稱】</param> public async void OpenConnectOfAnonymous(string serverUrl) { if (!string.IsNullOrEmpty(serverUrl)) { try { opcUaClient.UserIdentity = new UserIdentity(new AnonymousIdentityToken()); await opcUaClient.ConnectServer(serverUrl); } catch (Exception ex) { ClientUtils.HandleException("連接失?。。?!", ex); } } } /// <summary> /// 打開連接【賬號方式】 /// </summary> /// <param name="serverUrl">服務(wù)器URL【格式:opc.tcp://服務(wù)器IP地址/服務(wù)名稱】</param> /// <param name="userName">用戶名稱</param> /// <param name="userPwd">用戶密碼</param> public async void OpenConnectOfAccount(string serverUrl, string userName, string userPwd) { if (!string.IsNullOrEmpty(serverUrl) && !string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(userPwd)) { try { opcUaClient.UserIdentity = new UserIdentity(userName, userPwd); await opcUaClient.ConnectServer(serverUrl); } catch (Exception ex) { ClientUtils.HandleException("連接失敗?。。?, ex); } } } /// <summary> /// 打開連接【證書方式】 /// </summary> /// <param name="serverUrl">服務(wù)器URL【格式:opc.tcp://服務(wù)器IP地址/服務(wù)名稱】</param> /// <param name="certificatePath">證書路徑</param> /// <param name="secreKey">密鑰</param> public async void OpenConnectOfCertificate(string serverUrl, string certificatePath, string secreKey) { if (!string.IsNullOrEmpty(serverUrl) && !string.IsNullOrEmpty(certificatePath) && !string.IsNullOrEmpty(secreKey)) { try { X509Certificate2 certificate = new X509Certificate2(certificatePath, secreKey, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); opcUaClient.UserIdentity = new UserIdentity(certificate); await opcUaClient.ConnectServer(serverUrl); } catch (Exception ex) { ClientUtils.HandleException("連接失?。。?!", ex); } } } /// <summary> /// 關(guān)閉連接 /// </summary> public void CloseConnect() { if (opcUaClient != null) { try { opcUaClient.Disconnect(); } catch (Exception ex) { ClientUtils.HandleException("關(guān)閉連接失?。。。?, ex); } } } /// <summary> /// 獲取到當前節(jié)點的值【同步讀取】 /// </summary> /// <typeparam name="T">節(jié)點對應(yīng)的數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <returns>返回當前節(jié)點的值</returns> public T GetCurrentNodeValue<T>(string nodeId) { T value = default(T); if (!string.IsNullOrEmpty(nodeId) && ConnectStatus) { try { value = opcUaClient.ReadNode<T>(nodeId); } catch (Exception ex) { ClientUtils.HandleException("讀取失?。。?!", ex); } } return value; } /// <summary> /// 獲取到當前節(jié)點數(shù)據(jù)【同步讀取】 /// </summary> /// <typeparam name="T">節(jié)點對應(yīng)的數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <returns>返回當前節(jié)點的值</returns> public DataValue GetCurrentNodeValue(string nodeId) { DataValue dataValue = null; if (!string.IsNullOrEmpty(nodeId) && ConnectStatus) { try { dataValue = opcUaClient.ReadNode(nodeId); } catch (Exception ex) { ClientUtils.HandleException("讀取失?。。?!", ex); } } return dataValue; } /// <summary> /// 獲取到批量節(jié)點數(shù)據(jù)【同步讀取】 /// </summary> /// <param name="nodeIds">節(jié)點列表</param> /// <returns>返回節(jié)點數(shù)據(jù)字典</returns> public Dictionary<string, DataValue> GetBatchNodeDatasOfSync(List<NodeId> nodeIdList) { Dictionary<string, DataValue> dicNodeInfo = new Dictionary<string, DataValue>(); if (nodeIdList != null && nodeIdList.Count > 0 && ConnectStatus) { try { List<DataValue> dataValues = opcUaClient.ReadNodes(nodeIdList.ToArray()); int count = nodeIdList.Count; for (int i = 0; i < count; i++) { AddInfoToDic(dicNodeInfo, nodeIdList[i].ToString(), dataValues[i]); } } catch (Exception ex) { ClientUtils.HandleException("讀取失敗?。?!", ex); } } return dicNodeInfo; } /// <summary> /// 獲取到當前節(jié)點的值【異步讀取】 /// </summary> /// <typeparam name="T">節(jié)點對應(yīng)的數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <returns>返回當前節(jié)點的值</returns> public async Task<T> GetCurrentNodeValueOfAsync<T>(string nodeId) { T value = default(T); if (!string.IsNullOrEmpty(nodeId) && ConnectStatus) { try { value = await opcUaClient.ReadNodeAsync<T>(nodeId); } catch (Exception ex) { ClientUtils.HandleException("讀取失敗?。?!", ex); } } return value; } /// <summary> /// 獲取到批量節(jié)點數(shù)據(jù)【異步讀取】 /// </summary> /// <param name="nodeIds">節(jié)點列表</param> /// <returns>返回節(jié)點數(shù)據(jù)字典</returns> public async Task<Dictionary<string, DataValue>> GetBatchNodeDatasOfAsync(List<NodeId> nodeIdList) { Dictionary<string, DataValue> dicNodeInfo = new Dictionary<string, DataValue>(); if (nodeIdList != null && nodeIdList.Count > 0 && ConnectStatus) { try { List<DataValue> dataValues = await opcUaClient.ReadNodesAsync(nodeIdList.ToArray()); int count = nodeIdList.Count; for (int i = 0; i < count; i++) { AddInfoToDic(dicNodeInfo, nodeIdList[i].ToString(), dataValues[i]); } } catch (Exception ex) { ClientUtils.HandleException("讀取失?。。。?, ex); } } return dicNodeInfo; } /// <summary> /// 獲取到當前節(jié)點的關(guān)聯(lián)節(jié)點 /// </summary> /// <param name="nodeId">當前節(jié)點</param> /// <returns>返回當前節(jié)點的關(guān)聯(lián)節(jié)點</returns> public ReferenceDescription[] GetAllRelationNodeOfNodeId(string nodeId) { ReferenceDescription[] referenceDescriptions = null; if (!string.IsNullOrEmpty(nodeId) && ConnectStatus) { try { referenceDescriptions = opcUaClient.BrowseNodeReference(nodeId); } catch (Exception ex) { string str = "獲取當前: " + nodeId + " 節(jié)點的相關(guān)節(jié)點失?。。?!"; ClientUtils.HandleException(str, ex); } } return referenceDescriptions; } /// <summary> /// 獲取到當前節(jié)點的所有屬性 /// </summary> /// <param name="nodeId">當前節(jié)點</param> /// <returns>返回當前節(jié)點對應(yīng)的所有屬性</returns> public OpcNodeAttribute[] GetCurrentNodeAttributes(string nodeId) { OpcNodeAttribute[] opcNodeAttributes = null; if (!string.IsNullOrEmpty(nodeId) && ConnectStatus) { try { opcNodeAttributes = opcUaClient.ReadNoteAttributes(nodeId); } catch (Exception ex) { string str = "讀取節(jié)點;" + nodeId + " 的所有屬性失?。。。?; ClientUtils.HandleException(str, ex); } } return opcNodeAttributes; } /// <summary> /// 寫入單個節(jié)點【同步方式】 /// </summary> /// <typeparam name="T">寫入節(jié)點值得數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <param name="value">節(jié)點對應(yīng)的數(shù)據(jù)值(比如:(short)123))</param> /// <returns>返回寫入結(jié)果(true:表示寫入成功)</returns> public bool WriteSingleNodeId<T>(string nodeId, T value) { bool success = false; if (opcUaClient != null && ConnectStatus) { if (!string.IsNullOrEmpty(nodeId)) { try { success = opcUaClient.WriteNode(nodeId, value); } catch (Exception ex) { string str = "當前節(jié)點:" + nodeId + " 寫入失敗"; ClientUtils.HandleException(str, ex); } } } return success; } /// <summary> /// 批量寫入節(jié)點 /// </summary> /// <param name="nodeIdArray">節(jié)點數(shù)組</param> /// <param name="nodeIdValueArray">節(jié)點對應(yīng)數(shù)據(jù)數(shù)組</param> /// <returns>返回寫入結(jié)果(true:表示寫入成功)</returns> public bool BatchWriteNodeIds(string[] nodeIdArray, object[] nodeIdValueArray) { bool success = false; if (nodeIdArray != null && nodeIdArray.Length > 0 && nodeIdValueArray != null && nodeIdValueArray.Length > 0) { try { success = opcUaClient.WriteNodes(nodeIdArray, nodeIdValueArray); } catch (Exception ex) { ClientUtils.HandleException("批量寫入節(jié)點失?。。?!", ex); } } return success; } /// <summary> /// 寫入單個節(jié)點【異步方式】 /// </summary> /// <typeparam name="T">寫入節(jié)點值得數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <param name="value">節(jié)點對應(yīng)的數(shù)據(jù)值</param> /// <returns>返回寫入結(jié)果(true:表示寫入成功)</returns> public async Task<bool> WriteSingleNodeIdOfAsync<T>(string nodeId, T value) { bool success = false; if (opcUaClient != null && ConnectStatus) { if (!string.IsNullOrEmpty(nodeId)) { try { success = await opcUaClient.WriteNodeAsync(nodeId, value); } catch (Exception ex) { string str = "當前節(jié)點:" + nodeId + " 寫入失敗"; ClientUtils.HandleException(str, ex); } } } return success; } /// <summary> /// 讀取單個節(jié)點的歷史數(shù)據(jù)記錄 /// </summary> /// <typeparam name="T">節(jié)點的數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <param name="startTime">開始時間</param> /// <param name="endTime">結(jié)束時間</param> /// <returns>返回該節(jié)點對應(yīng)的歷史數(shù)據(jù)記錄</returns> public List<T> ReadSingleNodeIdHistoryDatas<T>(string nodeId, DateTime startTime, DateTime endTime) { List<T> nodeIdDatas = null; if (!string.IsNullOrEmpty(nodeId) && startTime != null && endTime != null && endTime > startTime) { try { nodeIdDatas = opcUaClient.ReadHistoryRawDataValues<T>(nodeId, startTime, endTime).ToList(); } catch (Exception ex) { ClientUtils.HandleException("讀取失敗", ex); } } return nodeIdDatas; } /// <summary> /// 讀取單個節(jié)點的歷史數(shù)據(jù)記錄 /// </summary> /// <typeparam name="T">節(jié)點的數(shù)據(jù)類型</typeparam> /// <param name="nodeId">節(jié)點</param> /// <param name="startTime">開始時間</param> /// <param name="endTime">結(jié)束時間</param> /// <returns>返回該節(jié)點對應(yīng)的歷史數(shù)據(jù)記錄</returns> public List<DataValue> ReadSingleNodeIdHistoryDatas(string nodeId, DateTime startTime, DateTime endTime) { List<DataValue> nodeIdDatas = null; if (!string.IsNullOrEmpty(nodeId) && startTime != null && endTime != null && endTime > startTime) { if (ConnectStatus) { try { nodeIdDatas = opcUaClient.ReadHistoryRawDataValues(nodeId, startTime, endTime).ToList(); } catch (Exception ex) { ClientUtils.HandleException("讀取失敗", ex); } } } return nodeIdDatas; } /// <summary> /// 單節(jié)點數(shù)據(jù)訂閱 /// </summary> /// <param name="key">訂閱的關(guān)鍵字(必須唯一)</param> /// <param name="nodeId">節(jié)點</param> /// <param name="callback">數(shù)據(jù)訂閱的回調(diào)方法</param> public void SingleNodeIdDatasSubscription(string key, string nodeId, Action<string, MonitoredItem, MonitoredItemNotificationEventArgs> callback) { if (ConnectStatus) { try { opcUaClient.AddSubscription(key, nodeId, callback); } catch (Exception ex) { string str = "訂閱節(jié)點:" + nodeId + " 數(shù)據(jù)失?。。?!"; ClientUtils.HandleException(str, ex); } } } /// <summary> /// 取消單節(jié)點數(shù)據(jù)訂閱 /// </summary> /// <param name="key">訂閱的關(guān)鍵字</param> public bool CancelSingleNodeIdDatasSubscription(string key) { bool success = false; if (!string.IsNullOrEmpty(key)) { if (ConnectStatus) { try { opcUaClient.RemoveSubscription(key); success = true; } catch (Exception ex) { string str = "取消 " + key + " 的訂閱失敗"; ClientUtils.HandleException(str, ex); } } } return success; } /// <summary> /// 批量節(jié)點數(shù)據(jù)訂閱 /// </summary> /// <param name="key">訂閱的關(guān)鍵字(必須唯一)</param> /// <param name="nodeIds">節(jié)點數(shù)組</param> /// <param name="callback">數(shù)據(jù)訂閱的回調(diào)方法</param> public void BatchNodeIdDatasSubscription(string key, string[] nodeIds, Action<string, MonitoredItem, MonitoredItemNotificationEventArgs> callback) { if (!string.IsNullOrEmpty(key) && nodeIds != null && nodeIds.Length > 0) { if (ConnectStatus) { try { opcUaClient.AddSubscription(key, nodeIds, callback); } catch (Exception ex) { string str = "批量訂閱節(jié)點數(shù)據(jù)失?。。?!"; ClientUtils.HandleException(str, ex); } } } } /// <summary> /// 取消所有節(jié)點的數(shù)據(jù)訂閱 /// </summary> /// <returns></returns> public bool CancelAllNodeIdDatasSubscription() { bool success = false; if (ConnectStatus) { try { opcUaClient.RemoveAllSubscription(); success = true; } catch (Exception ex) { ClientUtils.HandleException("取消所有的節(jié)點數(shù)據(jù)訂閱失?。。?!", ex); } } return success; } /// <summary> /// 取消單節(jié)點的數(shù)據(jù)訂閱 /// </summary> /// <returns></returns> public bool CancelNodeIdDatasSubscription(string key) { bool success = false; if (ConnectStatus) { try { opcUaClient.RemoveSubscription(key); success = true; } catch (Exception ex) { ClientUtils.HandleException("取消節(jié)點數(shù)據(jù)訂閱失?。。?!", ex); } } return success; } #endregion #region 私有方法 /// <summary> /// 添加數(shù)據(jù)到字典中(相同鍵的則采用最后一個鍵對應(yīng)的值) /// </summary> /// <param name="dic">字典</param> /// <param name="key">鍵</param> /// <param name="dataValue">值</param> private void AddInfoToDic(Dictionary<string, DataValue> dic, string key, DataValue dataValue) { if (dic != null) { if (!dic.ContainsKey(key)) { dic.Add(key, dataValue); } else { dic[key] = dataValue; } } } #endregion }//Class_end }
Winform:
using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace MyOPCUATest { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private OPCUAHelper opcClient; private string[] MonitorNodeTags = null; Dictionary<string, object> myDic = new Dictionary<string, object>(); private void BtnConn_Click(object sender, EventArgs e) { string url = "opc.tcp://192.168.2.11:4840"; string userName = "Administrator"; string password = "123456"; opcClient = new OPCUAHelper(); //opcClient.OpenConnectOfAccount(url, userName, password); opcClient.OpenConnectOfAnonymous(url); MessageBox.Show(opcClient.ConnectStatus.ToString()); } private void BtnCurrentNode_Click(object sender, EventArgs e) { //string nodeId = "\"S7MesData\".\"S7Real\"[0]"; string nodeId = "ns=3;s=\"S7MesData\".\"S7Real\"[0]"; DataValue myValue= opcClient.GetCurrentNodeValue(nodeId); this.Txtbox.Text = myValue.ToString(); } private void BtnCertificate_Click(object sender, EventArgs e) { string url = "opc.tcp://192.168.2.11:4840"; string path = "D:\\zhengshu\\security\\zg-client.pfx"; string key = "123456"; opcClient = new OPCUAHelper(); opcClient.OpenConnectOfCertificate(url, path, key); MessageBox.Show(opcClient.ConnectStatus.ToString()); } private void BtnSigleScribe_Click(object sender, EventArgs e) { List<string> list = new List<string>(); list.Add("ns=3;s=\"S7MesData\".\"S7Real\"[0]"); list.Add("ns=3;s=\"S7MesData\".\"S7Real\"[1]"); MonitorNodeTags = list.ToArray(); opcClient.BatchNodeIdDatasSubscription("B", MonitorNodeTags, SubCallback); } private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args) { if (key == "B") { MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification; if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[0]) { textBox2.Invoke(new Action(() => { textBox2.Text = notification.Value.WrappedValue.Value.ToString(); })); } else if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[1]) { textBox3.Invoke(new Action(() => { textBox3.Text = notification.Value.WrappedValue.Value.ToString(); })); } if (myDic.ContainsKey(monitoredItem.StartNodeId.ToString())) { myDic[monitoredItem.StartNodeId.ToString()] = notification.Value.WrappedValue.Value; } else { myDic.Add(monitoredItem.StartNodeId.ToString(), notification.Value.WrappedValue.Value); } string str = ""; //foreach (var item in myDic) //{ // Console.WriteLine(item.Key); // Console.WriteLine(item.Value); //} } } private void btnWrite_Click(object sender, EventArgs e) { string myTxt = textBox4.Text.Trim(); string nodeId = "ns=3;s=\"S7MesData\".\"S7Real\"[0]"; opcClient.WriteSingleNodeId(nodeId, (float)Convert.ToDouble(myTxt)); } } }
KepServer 設(shè)置:
using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Generic; using System.Windows.Forms; namespace MyOPCUATest { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private OPCUAHelper opcClient; private string[] MonitorNodeTags = null; Dictionary<string, object> myDic = new Dictionary<string, object>(); private void BtnConn_Click(object sender, EventArgs e) { //string url = "opc.tcp://192.168.2.11:4840"; //PLC string url = "opc.tcp://192.168.2.125:49320"; //KepServer string userName = "Administrator"; string password = "123456"; opcClient = new OPCUAHelper(); opcClient.OpenConnectOfAccount(url, userName, password); //opcClient.OpenConnectOfAnonymous(url); MessageBox.Show(opcClient.ConnectStatus.ToString()); } private void BtnCurrentNode_Click(object sender, EventArgs e) { //string nodeId = "\"S7MesData\".\"S7Real\"[0]"; //string nodeId = "ns=3;s=\"S7MesData\".\"S7Real\"[0]"; //PLC string nodeId = "ns=2;s=KxOPC.KX1500.電壓1"; //Kep DataValue myValue = opcClient.GetCurrentNodeValue(nodeId); this.Txtbox.Text = myValue.ToString(); } private void BtnCertificate_Click(object sender, EventArgs e) { //string url = "opc.tcp://192.168.2.11:4840"; string url = "opc.tcp://192.168.2.125:49320"; //KepServer string path = @"D:\zhengshu\security\zg-client.pfx"; string key = "123456"; opcClient = new OPCUAHelper(); opcClient.OpenConnectOfCertificate(url, path, key); MessageBox.Show(opcClient.ConnectStatus.ToString()); } private void BtnSigleScribe_Click(object sender, EventArgs e) { List<string> list = new List<string>(); list.Add("ns=3;s=\"S7MesData\".\"S7Real\"[0]"); list.Add("ns=3;s=\"S7MesData\".\"S7Real\"[1]"); MonitorNodeTags = list.ToArray(); opcClient.BatchNodeIdDatasSubscription("B", MonitorNodeTags, SubCallback); } private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args) { if (key == "B") { MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification; if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[0]) { textBox2.Invoke(new Action(() => { textBox2.Text = notification.Value.WrappedValue.Value.ToString(); })); } else if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[1]) { textBox3.Invoke(new Action(() => { textBox3.Text = notification.Value.WrappedValue.Value.ToString(); })); } if (myDic.ContainsKey(monitoredItem.StartNodeId.ToString())) { myDic[monitoredItem.StartNodeId.ToString()] = notification.Value.WrappedValue.Value; } else { myDic.Add(monitoredItem.StartNodeId.ToString(), notification.Value.WrappedValue.Value); } string str = ""; //foreach (var item in myDic) //{ // Console.WriteLine(item.Key); // Console.WriteLine(item.Value); //} } } private void btnWrite_Click(object sender, EventArgs e) { string myTxt = textBox4.Text.Trim(); string nodeId = "ns=3;s=\"S7MesData\".\"S7Real\"[0]"; opcClient.WriteSingleNodeId(nodeId, (float)Convert.ToDouble(myTxt)); } } }
結(jié)果:
到此這篇關(guān)于C# 使用OpcUaHelper讀寫OPC服務(wù)器的文章就介紹到這了,更多相關(guān)C#讀寫OPC服務(wù)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
新手小白用C# winform 讀取Excel表的實現(xiàn)
這篇文章主要介紹了新手小白用C# winform 讀取Excel表的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01C#探秘系列(一)——ToDictionary,ToLookup
這個系列我們看看C#中有哪些我們知道,但是又不知道怎么用,又或者懶得去了解的東西,比如這篇我們要介紹的toDictionary和ToLookup。2014-05-05