Search code examples
c#opcopc-da

How do I get a list of tags on a OPC server


I am trying to get the list of Tags from a OPC server, I am using the EasyDaClient from the QuickOPC. What I'm trying to do is this

try
{
    //create the OPC Client object
    OpcLabs.EasyOpc.DataAccess.EasyDAClient easyDAClient1 = new OpcLabs.EasyOpc.DataAccess.EasyDAClient();

    //ServerDescriptor Declration
        OpcLabs.EasyOpc.ServerDescriptor sd = new OpcLabs.EasyOpc.ServerDescriptor();
sd.MachineName = "W7VM";
sd.ServerClass = "OPC.Siemens.XML.1";

    OpcLabs.EasyOpc.DataAccess.DANodeElementCollection allTags = easyDAClient1.BrowseLeaves(sd);

    foreach (OpcLabs.EasyOpc.DataAccess.DANodeElement tag in allTags)
    {
        //if the value is a branch add it to the listbox.
        if (tag.IsLeaf)
        {
            //add the fully qualified item id
            listBox1.Items.Add(tag.ItemId.ToString());
        }
    }


}
catch (Exception ex)
{
    MessageBox.Show("Error: " + ex.Message.ToString());
}

I always get 0 elements from the BrowseLeaves method and I don't know what is my Channel_1.Device_1 so that I can use the other overload. I am new to this can someone explain me how the OPC tags can be listed?? FYI: I can read the values from the tags using the:

easyDAClient1.ReadItem(MachineNameTextBox.Text,serverClassTextBox.Text,itemIdTextBox.Text);

So its not a Conenction problem


Solution

  • You are browsing the leaves at the root level, and there none there, that's why you get an empty collection.

    What can you do? Several options there:

    1) If you want to start the browsing at the root and get to the leaf level, you need to consider the branches as well. Use BrowseBranches method, or (maybe even better) use BrowseNodes, which returns both the branches and the leaves. When you get a branch node (you can test it using .IsBranch), you may decide to browse further into it.

    2) If you want to get the leaves and know which branch they are at, you can pass in the branch name to the BrowseLeaves method as an additional parameter. However this is probably not your case, as I can guess form you saying "I don't know what is my Channel_1.Device_1 ", which is probably the branch ID that you do not "know" upfront.

    Here is a complete example with recursive browsing:

    // BrowseAndReadValues: Console application that recursively browses and displays the nodes in the OPC address space, and 
    // attempts to read and display values of all OPC items it finds.
    
    using System.Diagnostics;
    using JetBrains.Annotations;
    using OpcLabs.EasyOpc;
    using OpcLabs.EasyOpc.DataAccess;
    using System;
    
    namespace BrowseAndReadValues
    {
        class Program
        {
            const string ServerClass = "OPCLabs.KitServer.2";
    
            [NotNull]
            static readonly EasyDAClient Client = new EasyDAClient();
    
            static void BrowseAndReadFromNode([NotNull] string parentItemId)
            {
                // Obtain all node elements under parentItemId
                var nodeFilter = new DANodeFilter();    // no filtering whatsoever
                DANodeElementCollection nodeElementCollection = Client.BrowseNodes("", ServerClass, parentItemId, nodeFilter);
                // Remark: that BrowseNodes(...) may also throw OpcException; a production code should contain handling for it, here 
                // omitted for brevity.
    
                foreach (DANodeElement nodeElement in nodeElementCollection)
                {
                    Debug.Assert(nodeElement != null);
    
                    // If the node is a leaf, it might be possible to read from it
                    if (nodeElement.IsLeaf)
                    {
                        // Determine what the display - either the value read, or exception message in case of failure.
                        string display;
                        try
                        {
                            object value = Client.ReadItemValue("", ServerClass, nodeElement);
                            display = String.Format("{0}", value);
                        }
                        catch (OpcException exception)
                        {
                            display = String.Format("** {0} **", exception.GetBaseException().Message);
                        }
    
                        Console.WriteLine("{0} -> {1}", nodeElement.ItemId, display);
                    }
                    // If the node is not a leaf, just display its itemId
                    else
                        Console.WriteLine("{0}", nodeElement.ItemId);
    
                    // If the node is a branch, browse recursively into it.
                    if (nodeElement.IsBranch &&
                        (nodeElement.ItemId != "SimulateEvents") /* this branch is too big for the purpose of this example */)
                        BrowseAndReadFromNode(nodeElement);
                }
            }
    
            static void Main()
            {
                Console.WriteLine("Browsing and reading values...");
                // Set timeout to only wait 1 second - default would be 1 minute to wait for good quality that may never come.
                Client.InstanceParameters.Timeouts.ReadItem = 1000;
    
                // Do the actual browsing and reading, starting from root of OPC address space (denoted by empty string for itemId)
                BrowseAndReadFromNode("");
    
                Console.WriteLine("Press Enter to continue...");
                Console.ReadLine();
            }
        }
    }
    

    Tech support: http://www.opclabs.com/forum/index