2

I'm not a C# programmer, but for necessity I'm trying to create a client opc-ua using C#. Searching on the web i found some examples but I could not get the client to work. Can anyone expert help me out?

I attach the complete code below:

using System;
using Opc.UaFx;
using Opc.UaFx.Client;
using System.Collections.Generic;
// using System.IO.Compression; 
// using System.Linq;

namespace Client
{
    public class Program
    {
        static void Main(string[] args)
        {
            using (var client = new OpcClient("opc.tcp://127.0.0.1:62541/"))
            {
                try 
                {
                    client.Connect(); // connection
                }
                catch
                {
                    Console.WriteLine("I Can't Connect");
                }
                finally
                {
                    // node list
                string[] nodeIds = {
                    "ns=1;s=[Simulatore OPC Server]ST20543",
                    "ns=1;s=[Simulatore OPC Server]ST1",
                    "ns=1;s=[Simulatore OPC Server]ST2",
                    "ns=1;s=[Simulatore OPC Server]ST3",
                    "ns=1;s=[Simulatore OPC Server]ST4",
                    "ns=1;s=[Simulatore OPC Server]ST5",
                    "ns=1;s=[Simulatore OPC Server]ST6",
                    "ns=1;s=[Simulatore OPC Server]ST7",
                    "ns=1;s=[Simulatore OPC Server]ST8",
                    "ns=1;s=[Simulatore OPC Server]ST9",
                    "ns=1;s=[Simulatore OPC Server]ST10"
                };
            
                // Create an (empty) subscription to which we will addd OpcMonitoredItems.
                OpcSubscription subscription = client.SubscribeNodes();
            
                for (int index = 0; index < nodeIds.Length; index++) 
                {
                    // Monitored Items
                    var item = new OpcMonitoredItem(nodeIds[index], OpcAttribute.Value);
                    item.DataChangeReceived += HandleDataChanged;
            
                    item.Tag = index;
            
                    item.SamplingInterval = 200;
            
                    // Add element to subscription
                    subscription.AddMonitoredItem(item);
                    Console.WriteLine("{\"Timestamp\":", "\"", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffffK"), "\",\"", "Data Change from NodeId '{0}': {1}", item.DisplayName, item.LastDataChange);
                }
            
                // Apply Changes
                subscription.ApplyChanges();
                }

            }
        }
    // class BROWSE
    private void Browse(OpcNodeInfo node, int level = 0)
    {
        Console.WriteLine("{0}{1}({2})",
                new string('.', level * 4),
                node.Attribute(OpcAttribute.DisplayName).Value,
                node.NodeId);
    
        level++;
    
        foreach (var childNode in node.Children())
            Browse(childNode, level);
    }
    // class HANDLER
    private static void HandleDataChanged(object sender, OpcDataChangeReceivedEventArgs e)
    {
        // Code to be executed
        // 'sender' contains MonitoredItem
        OpcMonitoredItem item = (OpcMonitoredItem)sender;
    
        // Output
        Console.WriteLine("{\"Timestamp\":", "\"", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffffK"), "\",\"", "Data Change from NodeId '{0}': {1}", item.DisplayName, e.Item.Value);

    }
}

}

The goal is to create a client that subscribes to the server and prints an output (console.writeline) in the format specified in the Handler class at every nodes value change.

Luca
  • 49
  • 6
  • You should use the OPC Foundation .Net Core libraries. They have documentation and examples: https://github.com/OPCFoundation/UA-.NETStandard – eglease Nov 15 '21 at 21:56
  • 1
    I see that you are using Opc.UaFx, the OPC library from Traeger. Is there a reason to use it? Have you seen their documentation: https://docs.traeger.de/en/software/sdk/opc-ua/net/client.development.guide – eglease Nov 15 '21 at 22:00
  • Also, you should not have your `OpcSubscription` in the `finally` block since it will execute even if you cannot connect to the server. It needs to be after the `Connect` – eglease Nov 15 '21 at 22:00
  • Are you running an OPC UA Server at `opc.tcp://127.0.0.1:62541`? Are you able to connect to it with another OPC UA Client (try UaExpect)? Without more info, it is hard to see what is wrong. – eglease Nov 15 '21 at 22:02
  • @eglease I am using Opc.UaFx because I found the documentation easier to understand. I could not find an example of a Client to work on in the OPC Foundation repository. Help to orient myself in the documentation is also welcome. I already have a python client that can connect to the address so I'm sure it works. – Luca Nov 16 '21 at 08:30
  • Aside from the try-catch-finally issue, I can't tell what is wrong with your code. I never used this particular library. Maybe Traeger has a forum or a full working example. I used UnifiedAutomation and they have both. BTW, here are the samples from the OPC Foundation: https://github.com/OPCFoundation/UA-.NETStandard-Samples – eglease Nov 16 '21 at 14:17

1 Answers1

0

First of all, the try-catch structure is a bit off, you should move the logic under the try clause. Also now the catch clause will take catch all exceptions and just swallow them, normally you should only try to catch exceptions that you can actually do something about.

Then about the subscription. Using the using(...) statement will discard the client once the code between the curly brackets is executed, so there is no client to have any subscriptions on, so declaring a normal variable var client = new OpcClient("opc.tcp://127.0.0.1:62541/") will remedy that.

Next, the lifetime of your app is now the time it takes to run every line in the code, so it will exit once the subscriptions are made, again, there is nothing to monitor the subs, you can just add a while loop or any other mechanism that keeps your app running.

Lastly, make sure the nodeId's are correct and the node are of type variable the library might not have checks for these things.

Mkasakka
  • 1
  • 1