convertersystems / opc-ua-samples

Sample HMIs using OPC Unified Architecture (OPC UA) and Visual Studio.
MIT License
107 stars 43 forks source link

Get the nodeid corresponding to Tag name and vice versa #37

Closed balamcsd closed 7 years ago

balamcsd commented 7 years ago

Sir, I am referring to the code in the below link : https://github.com/convertersystems/opc-ua-samples/blob/master/ConsoleApp/Program.cs I have Tagname 'Tag1' created in OPC server. (in real scenario someone will create) For monitoring this tag for data change notification i need to specify nodeid in the format (i=2256) Can you please post C# code to get the nodeid from tagname and vice versa Also suggest what is the SamplingInterval & QueueSize settings Thanks in advance for your help. Regards

new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2256"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }

awcullen commented 7 years ago

You can use software tools to browse the OPC Server namespace for 'Tag1'. One popular tool is 'UaExpert' by Unified Automation. With UaExpert you can find 'Tag1' (the DisplayName) and get additional information about the node, like NodeId and DataType.

balamcsd commented 7 years ago

I saw some service 'TranslateBrowsePathsToNodeIds() ' and i am not clear how to use it In my case input is Tagname. By using this service, i have to get the nodeid. Request to please post c# code for 'TranslateBrowsePathsToNodeIds() ' Thanks for helping

awcullen commented 7 years ago

I suggest you read the pdf Part 4- Services. You will find a lot of good information.

balamcsd commented 7 years ago

Sir, I have only the node name (tag name) in opc server that will be subscribed by opc client for data change notification. I have no idea about which path this node (tag) exists in the opc server. In this case how will get the complete node path (or) nodeid Please help Thanks

balamcsd commented 7 years ago

I got a solution for this by recursive method. Just posting the c# code so it will be useful for someone who is reading this post -

public class Tag
{
    public string TagName { get; set; }
    public string NodeId { get; set; }
}

private Dictionary<uint, Tag> TagDatabase = new Dictionary<uint, Tag>();

                Tag tag = new Tag();
                tag .TagName = "Tag1";
                TagDatabase.AddTag(tag );
                Tag tag = new Tag();
                tag .TagName = "Tag2";
                TagDatabase.AddTag(tag );

    private uint GetClientHandleByTag(string TagName)
    {
        uint tagKey = 0;

        tagKey = TagDatabase.FirstOrDefault(x => x.Value.TagName == TagName).Key;

        return tagKey;
    }

private static uint clientHandleId = 1;

    public void AddTag(C2Tag tag)
    {
            TagDatabase.Add(clientHandleId++, tag);
    }

    public void UpdateNodeByClientHandle(uint clientHandle, string nodeId)
    {
        TagDatabase[clientHandle].NodeId = nodeId;
    }

    private static async Task RecursivelyFindNode(UaTcpSessionChannel channel, NodeId nodeid)
    {
        BrowseRequest browseRequest = new BrowseRequest
        {
            NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = nodeid, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } },
        };

        BrowseResponse browseResponse = await channel.BrowseAsync(browseRequest);

        foreach (var rd1 in browseResponse.Results[0].References ?? new ReferenceDescription[0])
        {

            uint chid = TagDatabase.GetClientHandleByTag(rd1.DisplayName.ToString());

            if (chid > 0)
            {
                TagDatabase.UpdateNodeByClientHandle(chid, rd1.NodeId.ToString());
            }

            await RecursivelyFindNode(channel, ExpandedNodeId.ToNodeId(rd1.NodeId, channel.NamespaceUris));
        }
    }

To call recursive method -

await RecursivelyFindNode(channel, NodeId.Parse(ObjectIds.RootFolder));

balamcsd commented 7 years ago

Based on above solution closing the issue