OPC UA : minimal code that browses the root node of a server
Asked Answered
H

1

14

I am using the OPC UA Foundation SDK to develop a small client. What would be the minimal C# code to:

  • Connect to a server
  • Browse the root node
  • Print the immediate children's BrowseNames
  • Quit?

I am given the server endpoint (no discovery), security None.

The code should make no use of config files, nor require a STA.

Any help on this would be more than appreciated.

Historic answered 1/6, 2015 at 12:38 Comment(2)
You mean the foundation stack, right? Which one (what language)?Electrolyte
c#. Editing the question.Historic
A
43

Edit 4/2018:

The OPC UA .Net Standard Library is going asynchronous. See the updated sample.

Edit 9/2016:

Everyone should see the new OPC UA .Net Standard Library.

You can develop apps that run on all common platforms available today, including Linux, iOS, Android (via Xamarin) and Windows.

And you can find many samples, including a sample inspired by this post. Look for the folder SampleApplications/Samples/NetCoreConsoleClient.

Original post:

Help with homework, perhaps?

using Opc.Ua;   // Install-Package OPCFoundation.NetStandard.Opc.Ua
using Opc.Ua.Client;
using Opc.Ua.Configuration;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;

namespace MyHomework
{
  class Program
  {
    static void Main(string[] args)
    {

        Console.WriteLine("Step 1 - Create application configuration and certificate.");
        var config = new ApplicationConfiguration()
        {
            ApplicationName = "MyHomework",
            ApplicationUri = Utils.Format(@"urn:{0}:MyHomework", System.Net.Dns.GetHostName()),
            ApplicationType = ApplicationType.Client,
            SecurityConfiguration = new SecurityConfiguration {
                ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName="MyHomework" },
                TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
                TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
                RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
                AutoAcceptUntrustedCertificates = true
            },
            TransportConfigurations = new TransportConfigurationCollection(),
            TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
            ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
            TraceConfiguration = new TraceConfiguration()
        };
        config.Validate(ApplicationType.Client).GetAwaiter().GetResult();
        if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
        {
            config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
        }

        var application = new ApplicationInstance
        {
            ApplicationName = "MyHomework",
            ApplicationType = ApplicationType.Client,
            ApplicationConfiguration = config
        };
        application.CheckApplicationInstanceCertificate(false, 2048).GetAwaiter().GetResult();

        var selectedEndpoint = CoreClientUtils.SelectEndpoint("opc.tcp://" + Dns.GetHostName() + ":48010", useSecurity: true, operationTimeout: 15000);

        Console.WriteLine($"Step 2 - Create a session with your server: {selectedEndpoint.EndpointUrl} ");
        using (var session = Session.Create(config, new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)), false, "", 60000, null, null).GetAwaiter().GetResult())
        {
            Console.WriteLine("Step 3 - Browse the server namespace.");
            ReferenceDescriptionCollection refs;
            Byte[] cp;
            session.Browse(null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out cp, out refs);
            Console.WriteLine("DisplayName: BrowseName, NodeClass");
            foreach (var rd in refs)
            {
                Console.WriteLine("{0}: {1}, {2}", rd.DisplayName, rd.BrowseName, rd.NodeClass);
                ReferenceDescriptionCollection nextRefs;
                byte[] nextCp;
                session.Browse(null, null, ExpandedNodeId.ToNodeId(rd.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs);
                foreach (var nextRd in nextRefs)
                {
                    Console.WriteLine("+ {0}: {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass);
                }
            }

            Console.WriteLine("Step 4 - Create a subscription. Set a faster publishing interval if you wish.");
            var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 };

            Console.WriteLine("Step 5 - Add a list of items you wish to monitor to the subscription.");
            var list = new List<MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } };
            list.ForEach(i => i.Notification += OnNotification);
            subscription.AddItems(list);

            Console.WriteLine("Step 6 - Add the subscription to the session.");
            session.AddSubscription(subscription);
            subscription.Create();

            Console.WriteLine("Press any key to remove subscription...");
            Console.ReadKey(true);
        }

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey(true);
    }

    private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
    {
        foreach (var value in item.DequeueValues())
        {
            Console.WriteLine("{0}: {1}, {2}, {3}", item.DisplayName, value.Value, value.SourceTimestamp, value.StatusCode);
        }
    }

  }
}
Apodictic answered 3/6, 2015 at 16:10 Comment(15)
Sounds like homework, but it's not. I am trying to untangle some dependency-ridden OPC UA code, and I had great trouble programmatically creating a minimal ApplicationConfiguration to write a unit test.Historic
Thank you so much! The sample code provided (sample client) was very poor.. your example helped me much!Pettifer
This is great. Thanks. The OPC UA SDK should really include a sample CLI application (like this) that demonstrates how to get a minimal application up and running from scratch.Eyeglass
Good example but i'm getting the following error: Task<Session> does not have any definition of browse method. Can anyone help? Thanks.Midbrain
The OPC UA .NETStandard Library is going asynchronous! Now you get a Task<Session> from Session.Create(). See an updated sample at github.com/OPCFoundation/UA-.NETStandardLibrary/tree/master/…Apodictic
Thanks andrewcullen!Midbrain
I retied this example, but now at config.Validate(ApplicationType.Client).GetAwaiter().GetResult(); gives a null reference... any thoughts?Pettifer
I foillowed this example but get the error ApllicationCertificate cannot be found. Any ideas?Retarder
I followed this application and get following error at start:System.IO.FileNotFoundException: 'Could not load file or assembly 'System.ServiceModel.Primitives, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.'Chessboard
Weirdly enough, an application certificate is given in the new version of the code (SecurityConfiguration), which was not present in the original answer. Now the answer does not seem to answer the question anymore (security = None), and the ApplicationConfiguration does not seem minimal enough to allow to write a simple UT anymore (you’re tied to certificate stores now) Maybe @andrewcullen could help on that one.Historic
If you prefer to turn off encryption, then set "useSecurity: false "Apodictic
If you prefer to not generate an application certificate then remove call to: "CheckApplicationInstanceCertificate"Apodictic
And if you want to not use the certificate directory store then: SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier(), AutoAcceptUntrustedCertificates = true, }Apodictic
@AndrewCullen: I'm getting the following error: "Certificate doesn't meet minimum key length requirement.". Do you know the reason?Option
The line to CheckApplicationInstanceCertificate may have found an older cert that did not have a PublicKey length of 2048. You may have to delete the "MyHomework" cert from C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs and run the program again. A new cert with the correct key length will be created.Apodictic

© 2022 - 2024 — McMap. All rights reserved.