发布于2021-05-30 20:07 阅读(1304) 评论(0) 点赞(10) 收藏(3)
目录
②注意:OPC UA服务器环境可以使用虚拟机搭建,如果从本机访问OPC UA服务器连接不上或超时,请先关闭OPC UA服务器的防火墙,或者在防火墙打开对应的端口即可。
①打开OPC UA服务器连接面板代码如下:
- using (FormBrowseServer form = new FormBrowseServer())
- {
- form.ShowDialog();
- }
②执行该代码后即可弹窗输入OPC UA服务器URL,连接服务器
③查看服务器的节点
- //实例化操作
-
- OpcUaClient m_OpcUaClient = new OpcUaClient();
-
- //设置匿名连接
-
- m_OpcUaClient.UserIdentity = new UserIdentity( new AnonymousIdentityToken( ) );
-
- //设置用户名连接
-
- m_OpcUaClient.UserIdentity = new UserIdentity( "user", "password" );
-
- //使用证书连接
-
- X509Certificate2 certificate = new X509Certificate2( "[证书的路径]", "[密钥]", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable );
- m_OpcUaClient.UserIdentity = new UserIdentity( certificate );
- //设置完连接的权限之后,就可以真正的启动连接操作了,连接的操作必须要放到try...catch...之前,必须使用async标记方法
-
- private async void button1_Click( object sender, EventArgs e )
- {
- // 这是一个连接服务器的示例
- try
- {
- await m_OpcUaClient.ConnectServer( "opc.tcp://192.168.146.137:49321/Kepware.KEPServerEX.V6" );
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( "连接失败!!!", ex );
- }
- }
①如果我们想要读取上图节点浏览器的温度数据,节点字符串为:
ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4
②同步方式读取节点信息【1-单节点数据读取 ;2-多节点批量读取】
- //1-同步单节点数据读取,类型为Int32, 所以我们使用下面的方法读取
- try
- {
- Int32 value = m_OpcUaClient.ReadNode<Int32>( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4" );
- }
- catch(Exception ex)
- {
- ClientUtils.HandleException( “读取失败!!!”, ex );
- }
-
-
-
- //2-同步批量节点数据读取的操作,分为类型不一致和类型一致两种操作,下面都做个示例
- try
- {
- // 添加所有的读取的节点,此处的示例是类型不一致的情况
- List<NodeId> nodeIds = new List<NodeId>( );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord1" ) );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Float1" ) );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong4" ) );
- );
-
- // dataValues按顺序定义的值,每个值里面需要重新判断类型
- List<DataValue> dataValues = m_OpcUaClient.ReadNodes( nodeIds.ToArray() );
-
-
- // 如果你批量读取的值的类型都是一样的,比如float,那么有简便的方式
- List<string> tags = new List<string>( );
- tags.Add( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Float1" );
- tags.Add( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Float2" );
- tags.Add( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Float3" );
-
- // 按照顺序定义的值
- List<float> values = m_OpcUaClient.ReadNodes<float>( tags.ToArray() );
-
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( this.Text, ex );
- }
③异步方式读取节点信息【1-单节点数据读取 ;2-多节点批量读取】
- //1-异步单节点数据读取,类型为Int32, 所以我们使用下面的方法读取
- try
- {
- Int32 value =await m_OpcUaClient.ReadNodeAsync<Int32>( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4" );
- }
- catch(Exception ex)
- {
- ClientUtils.HandleException( “读取失败!!!”, ex );
- }
-
-
-
- //2-异步批量节点数据读取的操作,分为类型不一致和类型一致两种操作,下面都做个示例
- try
- {
- // 添加所有的读取的节点,此处的示例是类型不一致的情况
- List<NodeId> nodeIds = new List<NodeId>( );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord1" ) );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Float1" ) );
- nodeIds.Add( new NodeId( "ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong4" ) );
- );
-
- // dataValues按顺序定义的值,每个值里面需要重新判断类型
- List<DataValue> dataValues =await m_OpcUaClient.ReadNodesAsync( nodeIds.ToArray() );
-
-
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( this.Text, ex );
- }
④订阅方式读取节点信息【1、单节点数据读取;2-多节点批量读取】
- //1-单节点数据订阅
- m_OpcUaClient.AddSubscription( "A", "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4", SubCallback );
-
- //1-单节点数据订阅的回调函数
- private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args )
- {
- if (InvokeRequired)
- {
- Invoke( new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>( SubCallback ), key, monitoredItem, args );
- return;
- }
-
- if (key == "A")
- {
- // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
- MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- if (notification != null)
- {
- textBox3.Text = notification.Value.WrappedValue.Value.ToString( );
- }
- }
- }
-
- //1-取消单节点数据订阅
- m_OpcUaClient.RemoveSubscription( "A" );
-
-
-
- //2-多节点批量数据订阅
-
- private string[] MonitorNodeTags = null;
-
- private void button5_Click( object sender, EventArgs e )
- {
- // 多个节点的订阅
- MonitorNodeTags = new string[]
- {
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord1",
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong4",
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4",
- };
- m_OpcUaClient.AddSubscription( "B", MonitorNodeTags, SubCallback );
- }
-
- //2-多节点批量数据订阅回调函数
- private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args )
- {
- if (InvokeRequired)
- {
- Invoke( new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>( SubCallback ), key, monitoredItem, args );
- return;
- }
-
- if (key == "A")
- {
- // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
- MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- if (notification != null)
- {
- textBox3.Text = notification.Value.WrappedValue.Value.ToString( );
- }
- }
- else if(key == "B")
- {
- // 需要区分出来每个不同的节点信息
- MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
- if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[0])
- {
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord1" = notification.Value.WrappedValue.Value.ToString( );
- }
- else if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[1])
- {
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong4" = notification.Value.WrappedValue.Value.ToString( );
- }
- else if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[2])
- {
- "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4" = notification.Value.WrappedValue.Value.ToString( );
- }
- }
- }
-
- //2-取消所有节点订阅
- m_OpcUaClient.RemoveAllSubscription();
-
⑤读取单节点的历史数据
- try
- {
- // 此处演示读取历史数据的操作,读取8月18日12点到13点的数据,如果想要读取成功,该节点是支持历史记录的
- List<float> values = m_OpcUaClient.ReadHistoryRawDataValues<float>( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4",
- new DateTime( 2021, 5, 1, 12, 0, 0 ), new DateTime( 2021, 2, 25, 13, 0, 0 ) ).ToList( );
- // 列表数据可用于显示曲线之类的操作
-
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( this.Text, ex );
- }
①读取一个节点的关联节点,包含了几个简单的基本信息
- try
- {
- ReferenceDescription[] references = m_OpcUaClient.BrowseNodeReference( "ns=2;s=数据类型示例.16 位设备.R 寄存器" );
- foreach (var item in references)
- {
- str = string.Format("节点:{0},节点类型:{1},节点名称:{2},节点显示名称:{3}",
- item.NodeId, item.NodeClass, item.BrowseName, item.DisplayName);
- }
-
- ;
-
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( this.Text, ex );
- }
-
-
- //执行结果
- 节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Boolean1,节点类型:Variable,节点名称:2:Boolean1,节点显示名称:Boolean1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Boolean2,节点类型:Variable,节点名称:2:Boolean2,节点显示名称:Boolean2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Boolean3,节点类型:Variable,节点名称:2:Boolean3,节点显示名称:Boolean3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Boolean4,节点类型:Variable,节点名称:2:Boolean4,节点显示名称:Boolean4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Double1,节点类型:Variable,节点名称:2:Double1,节点显示名称:Double1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Double2,节点类型:Variable,节点名称:2:Double2,节点显示名称:Double2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Double3,节点类型:Variable,节点名称:2:Double3,节点显示名称:Double3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Double4,节点类型:Variable,节点名称:2:Double4,节点显示名称:Double4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DoubleArray,节点类型:Variable,节点名称:2:DoubleArray,节点显示名称:DoubleArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord1,节点类型:Variable,节点名称:2:DWord1,节点显示名称:DWord1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord2,节点类型:Variable,节点名称:2:DWord2,节点显示名称:DWord2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord3,节点类型:Variable,节点名称:2:DWord3,节点显示名称:DWord3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DWord4,节点类型:Variable,节点名称:2:DWord4,节点显示名称:DWord4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.DWordArray,节点类型:Variable,节点名称:2:DWordArray,节点显示名称:DWordArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Float1,节点类型:Variable,节点名称:2:Float1,节点显示名称:Float1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Float2,节点类型:Variable,节点名称:2:Float2,节点显示名称:Float2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Float3,节点类型:Variable,节点名称:2:Float3,节点显示名称:Float3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Float4,节点类型:Variable,节点名称:2:Float4,节点显示名称:Float4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.FloatArray,节点类型:Variable,节点名称:2:FloatArray,节点显示名称:FloatArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong1,节点类型:Variable,节点名称:2:LLong1,节点显示名称:LLong1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong2,节点类型:Variable,节点名称:2:LLong2,节点显示名称:LLong2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong3,节点类型:Variable,节点名称:2:LLong3,节点显示名称:LLong3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LLong4,节点类型:Variable,节点名称:2:LLong4,节点显示名称:LLong4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LLongArray,节点类型:Variable,节点名称:2:LLongArray,节点显示名称:LLongArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Long1,节点类型:Variable,节点名称:2:Long1,节点显示名称:Long1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Long2,节点类型:Variable,节点名称:2:Long2,节点显示名称:Long2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Long3,节点类型:Variable,节点名称:2:Long3,节点显示名称:Long3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4,节点类型:Variable,节点名称:2:Long4,节点显示名称:Long4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.LongArray,节点类型:Variable,节点名称:2:LongArray,节点显示名称:LongArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.QWord1,节点类型:Variable,节点名称:2:QWord1,节点显示名称:QWord1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.QWord2,节点类型:Variable,节点名称:2:QWord2,节点显示名称:QWord2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.QWord3,节点类型:Variable,节点名称:2:QWord3,节点显示名称:QWord3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.QWord4,节点类型:Variable,节点名称:2:QWord4,节点显示名称:QWord4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.QWordArray,节点类型:Variable,节点名称:2:QWordArray,节点显示名称:QWordArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Short1,节点类型:Variable,节点名称:2:Short1,节点显示名称:Short1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Short2,节点类型:Variable,节点名称:2:Short2,节点显示名称:Short2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Short3,节点类型:Variable,节点名称:2:Short3,节点显示名称:Short3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Short4,节点类型:Variable,节点名称:2:Short4,节点显示名称:Short4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.ShortArray,节点类型:Variable,节点名称:2:ShortArray,节点显示名称:ShortArray节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Word1,节点类型:Variable,节点名称:2:Word1,节点显示名称:Word1节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Word2,节点类型:Variable,节点名称:2:Word2,节点显示名称:Word2节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Word3,节点类型:Variable,节点名称:2:Word3,节点显示名称:Word3节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.Word4,节点类型:Variable,节点名称:2:Word4,节点显示名称:Word4节点:ns=2;s=数据类型示例.16 位设备.R 寄存器.WordArray,节点类型:Variable,节点名称:2:WordArray,节点显示名称:WordArray
②读取一个节点的相关的所有的属性,主要包含了值,描述,名称,权限等级,等等操作
- string str=null;
- try
- {
- OpcNodeAttribute[] nodeAttributes = m_OpcUaClient.ReadNoteAttributes( "ns=2;s=数据类型示例.16 位设备.R 寄存器.Long4" );
- foreach (var item in nodeAttributes)
- {
- str += string.Format("属性名称:{0},属性类型:{1},属性状态:{2},属性值:{3}",
- item.Name, item.Type, item.StatusCode, item.Value);
- }
-
-
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException( this.Text, ex );
- }
-
-
- //执行结果
- 属性名称:NodeClass,属性类型:Int32,属性状态:Good,属性值:2属性名称:BrowseName,属性类型:QualifiedName,属性状态:Good,属性值:2:Long4属性名称:DisplayName,属性类型:LocalizedText,属性状态:Good,属性值:Long4属性名称:Description,属性类型:LocalizedText,属性状态:Good,属性值:属性名称:WriteMask,属性类型:UInt32,属性状态:Good,属性值:0属性名称:UserWriteMask,属性类型:UInt32,属性状态:Good,属性值:0属性名称:Value,属性类型:Int32,属性状态:Good,属性值:85747属性名称:DataType,属性类型:NodeId,属性状态:Good,属性值:i=6属性名称:ValueRank,属性类型:Int32,属性状态:Good,属性值:-1属性名称:AccessLevel,属性类型:Byte,属性状态:Good,属性值:3属性名称:UserAccessLevel,属性类型:Byte,属性状态:Good,属性值:3属性名称:MinimumSamplingInterval,属性类型:UInt32,属性状态:Good,属性值:10属性名称:Historizing,属性类型:Boolean,属性状态:Good,属性值:False
- /***
- * Title:"数据采集" 项目
- * 主题:OPCUA与kepserver通讯帮助类
- * Description:
- * 功能:
- * 1、打开连接【匿名方式】、【账号方式】、【证书方式】
- * 2、关闭连接
- * 3、获取到当前节点的值【同步读取】
- * 4、获取到当前节点数据【同步读取】
- * 5、获取到批量节点数据【同步读取】
- * 6、获取到当前节点的值【异步读取】
- * 7、获取到批量节点数据【异步读取】
- * 8、获取到当前节点的关联节点
- * 9、获取到当前节点的所有属性
- * 10、写入单个节点【同步方式】
- * 11、批量写入节点【同步方式】
- * 12、写入单个节点【异步方式】
- * 13、读取单个节点的历史数据记录
- * 14、读取单个节点的历史数据记录
- * 15、单节点数据订阅
- * 16、取消单节点数据订阅
- * 17、批量节点数据订阅
- * 18、取消所有节点的数据订阅
- *
- * Date:2021
- * Version:0.1版本
- * Author:Coffee
- * Modify Recoder:
- */
-
- using Opc.Ua;
- using Opc.Ua.Client;
- using OpcUaHelper;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Security.Cryptography.X509Certificates;
- using System.Threading.Tasks;
-
- namespace Utils
- {
- public class OPCUAHelper
- {
- #region 基础参数
- //OPCUA客户端
- private OpcUaClient opcUaClient;
-
-
- #endregion
-
- /// <summary>
- /// 构造函数
- /// </summary>
- public OPCUAHelper()
- {
- opcUaClient = new OpcUaClient();
- }
-
- /// <summary>
- /// 连接状态
- /// </summary>
- public bool ConnectStatus
- {
- get { return opcUaClient.Connected; }
- }
-
-
-
- #region 公有方法
-
-
- /// <summary>
- /// 打开连接【匿名方式】
- /// </summary>
- /// <param name="serverUrl">服务器URL【格式:opc.tcp://服务器IP地址/服务名称】</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">服务器URL【格式:opc.tcp://服务器IP地址/服务名称】</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">服务器URL【格式:opc.tcp://服务器IP地址/服务名称】</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>
- /// 关闭连接
- /// </summary>
- public void CloseConnect()
- {
- if (opcUaClient!=null)
- {
- try
- {
- opcUaClient.Disconnect();
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException("关闭连接失败!!!", ex);
- }
-
- }
- }
-
-
- /// <summary>
- /// 获取到当前节点的值【同步读取】
- /// </summary>
- /// <typeparam name="T">节点对应的数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <returns>返回当前节点的值</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>
- /// 获取到当前节点数据【同步读取】
- /// </summary>
- /// <typeparam name="T">节点对应的数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <returns>返回当前节点的值</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>
- /// 获取到批量节点数据【同步读取】
- /// </summary>
- /// <param name="nodeIds">节点列表</param>
- /// <returns>返回节点数据字典</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>
- /// 获取到当前节点的值【异步读取】
- /// </summary>
- /// <typeparam name="T">节点对应的数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <returns>返回当前节点的值</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>
- /// 获取到批量节点数据【异步读取】
- /// </summary>
- /// <param name="nodeIds">节点列表</param>
- /// <returns>返回节点数据字典</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>
- /// 获取到当前节点的关联节点
- /// </summary>
- /// <param name="nodeId">当前节点</param>
- /// <returns>返回当前节点的关联节点</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+" 节点的相关节点失败!!!";
- ClientUtils.HandleException(str, ex);
- }
- }
-
- return referenceDescriptions;
- }
-
-
- /// <summary>
- /// 获取到当前节点的所有属性
- /// </summary>
- /// <param name="nodeId">当前节点</param>
- /// <returns>返回当前节点对应的所有属性</returns>
- public OpcNodeAttribute[] GetCurrentNodeAttributes(string nodeId)
- {
- OpcNodeAttribute[] opcNodeAttributes=null;
- if (!string.IsNullOrEmpty(nodeId) && ConnectStatus)
- {
- try
- {
- opcNodeAttributes = opcUaClient.ReadNoteAttributes(nodeId);
- }
- catch (Exception ex)
- {
- string str = "读取节点;" + nodeId + " 的所有属性失败!!!";
- ClientUtils.HandleException(str, ex);
- }
- }
-
- return opcNodeAttributes;
- }
-
- /// <summary>
- /// 写入单个节点【同步方式】
- /// </summary>
- /// <typeparam name="T">写入节点值得数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <param name="value">节点对应的数据值(比如:(short)123))</param>
- /// <returns>返回写入结果(true:表示写入成功)</returns>
- public bool WriteSingleNodeIdOfSync<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 = "当前节点:" + nodeId + " 写入失败";
- ClientUtils.HandleException(str, ex);
- }
- }
-
- }
-
- return success;
- }
-
- /// <summary>
- /// 批量写入节点
- /// </summary>
- /// <param name="nodeIdArray">节点数组</param>
- /// <param name="nodeIdValueArray">节点对应数据数组</param>
- /// <returns>返回写入结果(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("批量写入节点失败!!!", ex);
- }
- }
- return success;
- }
-
- /// <summary>
- /// 写入单个节点【异步方式】
- /// </summary>
- /// <typeparam name="T">写入节点值得数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <param name="value">节点对应的数据值</param>
- /// <returns>返回写入结果(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 = "当前节点:"+nodeId+" 写入失败";
- ClientUtils.HandleException(str, ex);
- }
- }
-
- }
-
- return success;
- }
-
-
- /// <summary>
- /// 读取单个节点的历史数据记录
- /// </summary>
- /// <typeparam name="T">节点的数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <param name="startTime">开始时间</param>
- /// <param name="endTime">结束时间</param>
- /// <returns>返回该节点对应的历史数据记录</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>
- /// 读取单个节点的历史数据记录
- /// </summary>
- /// <typeparam name="T">节点的数据类型</typeparam>
- /// <param name="nodeId">节点</param>
- /// <param name="startTime">开始时间</param>
- /// <param name="endTime">结束时间</param>
- /// <returns>返回该节点对应的历史数据记录</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>
- /// 单节点数据订阅
- /// </summary>
- /// <param name="key">订阅的关键字(必须唯一)</param>
- /// <param name="nodeId">节点</param>
- /// <param name="callback">数据订阅的回调方法</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 = "订阅节点:" + nodeId + " 数据失败!!!";
- ClientUtils.HandleException(str, ex);
- }
- }
- }
-
- /// <summary>
- /// 取消单节点数据订阅
- /// </summary>
- /// <param name="key">订阅的关键字</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>
- /// 批量节点数据订阅
- /// </summary>
- /// <param name="key">订阅的关键字(必须唯一)</param>
- /// <param name="nodeIds">节点数组</param>
- /// <param name="callback">数据订阅的回调方法</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 = "批量订阅节点数据失败!!!";
- ClientUtils.HandleException(str, ex);
- }
- }
- }
-
- }
-
- /// <summary>
- /// 取消所有节点的数据订阅
- /// </summary>
- /// <returns></returns>
- public bool CancelAllNodeIdDatasSubscription()
- {
- bool success = false;
-
- if (ConnectStatus)
- {
- try
- {
- opcUaClient.RemoveAllSubscription();
- success = true;
- }
- catch (Exception ex)
- {
- ClientUtils.HandleException("取消所有的节点数据订阅失败!!!", ex);
- }
-
- }
-
- return success;
- }
-
- #endregion
-
-
-
- #region 私有方法
-
- /// <summary>
- /// 添加数据到字典中(相同键的则采用最后一个键对应的值)
- /// </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
-
- }
C#使用OpcUaHelper开源库开发的客户端实现读取、订阅OPC UA服务器节点项目工程下载
原文链接:https://blog.csdn.net/xiaochenXIHUA/article/details/117254108
作者:来呀来呀开心吧
链接:http://www.phpheidong.com/blog/article/86772/ea30ae2fcf77b44a4e74/
来源:php黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 php黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-4
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!