OpcUaHelper的基本使用

  • FromBrowseServer

使用此窗口服务可以查看服务器的节点状态。

 1 OpcUaHelper.Forms.FormBrowseServer formBrowseServer = new Forms.FormBrowseServer( );

2 formBrowseServer.ShowDialog( ); 

当然你可以固定住这个地址,传入地址即可,此处为示例:

 1 OpcUaHelper.Forms.FormBrowseServer formBrowseServer = new Forms.FormBrowseServer( "opc.tcp://127.0.0.1:62541/SharpNodeSettings/OpcUaServer" );

2 formBrowseServer.ShowDialog( ); 

  •  OPC UA Client

  • 实例化操作

 1 OpcUaClient m_OpcUaClient = new OpcUaClient(); 

  • 设置匿名连接

 1 m_OpcUaClient.UserIdentity = new UserIdentity( new AnonymousIdentityToken( ) ); 

  • 设置用户名连接

 1 m_OpcUaClient.UserIdentity = new UserIdentity( "user", "password" ); 

  • 使用证书连接

1 X509Certificate2 certificate = new X509Certificate2( "[证书的路径]", "[密钥]", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable );
2 m_OpcUaClient.UserIdentity = new UserIdentity( certificate );
  • 正式开始连接服务器,连接操作必须放在Try中,异步执行。

 1 private async void button1_Click( object sender, EventArgs e )
 2 {
 3     // connect to server, this is a sample
 4     try
 5     {
 6         await m_OpcUaClient.ConnectServer( "opc.tcp://127.0.0.1:62541/SharpNodeSettings/OpcUaServer" );
 7     }
 8     catch (Exception ex)
 9     {
10         ClientUtils.HandleException( "Connected Failed", ex );
11     }
12 }
  • Read/Write Node

  • 节点字符设为

 1 ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度 

  • 类型为int16,使用下面方法读取

1 try
2 {
3     short value = m_OpcUaClient.ReadNode<short>( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度" );
4 }
5 catch(Exception ex)
6 {
7     ClientUtils.HandleException( this.Text, ex );
8 }
  • 异步读取

1 try
2 {
3     short value = await m_OpcUaClient.ReadNodeAsync<short>( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度" );
4 }
5 catch (Exception ex)
6 {
7     ClientUtils.HandleException( this.Text, ex );
8 }
  • 写入节点

1 try
2 {
3     m_OpcUaClient.WriteNode( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度", (short)123 );
4 }
5 catch (Exception ex)
6 {
7     ClientUtils.HandleException( this.Text, ex );
8 }
  • 批量读取(类型一致)

 1 try
 2 {
 3     // 如果你批量读取的值的类型都是一样的,比如float,那么有简便的方式
 4     List<string> tags = new List<string>( );
 5     tags.Add( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/风俗" );
 6     tags.Add( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/转速" );
 7 
 8     // 按照顺序定义的值
 9     List<float> values = m_OpcUaClient.ReadNodes<float>( tags.ToArray() );
10 
11 }
12 catch (Exception ex)
13 {
14     ClientUtils.HandleException( this.Text, ex );
15 }
  • 批量读取(类型不一致)

 1 try
 2 {
 3     // 添加所有的读取的节点,此处的示例是类型不一致的情况
 4     List<NodeId> nodeIds = new List<NodeId>( );
 5     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度" ) );
 6     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/风俗" ) );
 7     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/转速" ) );
 8     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/机器人关节" ) );
 9     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/cvsdf" ) );
10     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/条码" ) );
11     nodeIds.Add( new NodeId( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/开关量" ) );
12 
13     // dataValues按顺序定义的值,每个值里面需要重新判断类型
14     List<DataValue> dataValues = m_OpcUaClient.ReadNodes( nodeIds.ToArray() );
15 
16 
17 }
18 catch (Exception ex)
19 {
20     ClientUtils.HandleException( this.Text, ex );
21 }
  • 批量写入

 1 try
 2 {
 3     // 此处演示写入一个short,2个float类型的数据批量写入操作
 4     bool success = m_OpcUaClient.WriteNodes( new string[] {
 5         "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度",
 6         "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/风俗",
 7         "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/转速"},
 8         new object[] {
 9             (short)1234,
10             123.456f,
11             123f
12         } );
13     if (success)
14     {
15         // 写入成功
16     }
17     else
18     {
19         // 写入失败,一个失败即为失败
20     }
21 }
22 catch (Exception ex)
23 {
24     ClientUtils.HandleException( this.Text, ex );
25 }
  • 读取Attrubute

 1 try
 2 {
 3     OpcNodeAttribute[] nodeAttributes = m_OpcUaClient.ReadNoteAttributes( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度" );
 4     foreach (var item in nodeAttributes)
 5     {
 6         Console.Write( string.Format( "{0,-30}", item.Name ) );
 7         Console.Write( string.Format( "{0,-20}", item.Type ) );
 8         Console.Write( string.Format( "{0,-20}", item.StatusCode ) );
 9         Console.WriteLine( string.Format( "{0,20}", item.Value ) );
10     }
11                 
12     // 输出如下
13     //  Name                          Type                StatusCode                         Vlaue
14 
15     //  NodeClass                     Int32               Good                                   2
16     //  BrowseName                    QualifiedName       Good                              2:温度
17     //  DisplayName                   LocalizedText       Good                                温度
18     //  Description                   LocalizedText       Good                                    
19     //  WriteMask                     UInt32              Good                                  96
20     //  UserWriteMask                 UInt32              Good                                  96
21     //  Value                         Int16               Good                              -11980
22     //  DataType                      NodeId              Good                                 i=4
23     //  ValueRank                     Int32               Good                                  -1
24     //  ArrayDimensions               Null                Good                                    
25     //  AccessLevel                   Byte                Good                                   3
26     //  UserAccessLevel               Byte                Good                                   3
27     //  MinimumSamplingInterval       Double              Good                                   0
28     //  Historizing                   Boolean             Good                               False
29 }
30 catch (Exception ex)
31 {
32     ClientUtils.HandleException( this.Text, ex );
33 }
  • 读取Reference

 1 try
 2 {
 3     ReferenceDescription[] references = m_OpcUaClient.BrowseNodeReference( "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端" );
 4     foreach (var item in references)
 5     {
 6         Console.Write( string.Format( "{0,-30}", item.NodeClass ) );
 7         Console.Write( string.Format( "{0,-30}", item.BrowseName ) );
 8         Console.Write( string.Format( "{0,-20}", item.DisplayName ) );
 9         Console.WriteLine( string.Format( "{0,-20}", item.NodeId.ToString( ) ) );
10     }
11 
12     ;
13     // 输出如下
14     //  NodeClass                     BrowseName                      DisplayName           NodeId
15 
16     //  Variable                      2:温度                          温度                  ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度
17     //  Variable                      2:风俗                          风俗                  ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/风俗
18     //  Variable                      2:转速                          转速                  ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/转速
19     //  Variable                      2:机器人关节                    机器人关节            ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/机器人关节
20     //  Variable                      2:cvsdf                         cvsdf                 ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/cvsdf
21     //  Variable                      2:条码                          条码                  ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/条码
22     //  Variable                      2:开关量                        开关量                ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/开关量
23 }
24 catch (Exception ex)
25 {
26     ClientUtils.HandleException( this.Text, ex );
27 }
  • 订阅(单节点订阅)

 1 m_OpcUaClient.AddSubscription( "A", "ns=2;s=Devices/分厂一/车间二/ModbusTcp客户端/温度", SubCallback ); 

关键字A是自定义的,方便回调判断或是取消订阅用的,方法SubCallback是一个回调方法:

 1 private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args )
 2 {
 3     if (InvokeRequired)
 4     {
 5         Invoke( new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>( SubCallback ), key, monitoredItem, args );
 6         return;
 7     }
 8 
 9     if (key == "A")
10     {
11         // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
12         MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
13         if (notification != null)
14         {
15             textBox3.Text = notification.Value.WrappedValue.Value.ToString( );
16         }
17     }
18 }

取消订阅代码如下:

 1 m_OpcUaClient.RemoveSubscription( "A" ); 

  • 订阅(批量订阅)

此处举例批量订阅3个点节点,按顺序在 textBox5 , textBox9 , textBox10 文本框按照顺序进行显示,此处比上面的操作需要麻烦一点, 需要缓存下批量订阅的节点信息

 1 // 缓存的批量订阅的节点
 2 private string[] MonitorNodeTags = null;
 3 
 4 private void button5_Click( object sender, EventArgs e )
 5 {
 6     // 多个节点的订阅
 7     MonitorNodeTags = new string[]
 8     {
 9         textBox6.Text,
10         textBox7.Text,
11         textBox8.Text,
12     };
13     m_OpcUaClient.AddSubscription( "B", MonitorNodeTags, SubCallback );
14 }

修改上述的回调方法如下:

 1 private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args )
 2 {
 3     if (InvokeRequired)
 4     {
 5         Invoke( new Action<string, MonitoredItem, MonitoredItemNotificationEventArgs>( SubCallback ), key, monitoredItem, args );
 6         return;
 7     }
 8 
 9     if (key == "A")
10     {
11         // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分
12         MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
13         if (notification != null)
14         {
15             textBox3.Text = notification.Value.WrappedValue.Value.ToString( );
16         }
17     }
18     else if(key == "B")
19     {
20         // 需要区分出来每个不同的节点信息
21         MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification;
22         if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[0])
23         {
24             textBox5.Text = notification.Value.WrappedValue.Value.ToString( );
25         }
26         else if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[1])
27         {
28             textBox9.Text = notification.Value.WrappedValue.Value.ToString( );
29         }
30         else if (monitoredItem.StartNodeId.ToString( ) == MonitorNodeTags[2])
31         {
32             textBox10.Text = notification.Value.WrappedValue.Value.ToString( );
33         }
34     }
35 }

 

posted on 2023-11-18 21:42  赵书记  阅读(1566)  评论(0编辑  收藏  举报