Handling of translateBrowsePathsToNodeIds on arrays

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
ArthurS
Jr. Member
Jr. Member
Posts: 4
Joined: 12 Oct 2022, 14:40

Handling of translateBrowsePathsToNodeIds on arrays

Post by ArthurS »

I use translateBrowsePathsToNodeIds to get to the NodeId via the browse path.
If I have an array in the path I get the message BadNoMatch.
How do I have to supply UaBrowsePaths so that this also works with arrays?

One of the path elements has e.g. the name 0,1,2 ... etc.

For Example:

The string NodeId is this like

"DB_TPM_Counter"."TPM_Counter"."Daten"[0]."TPM_Counter"

I know the NodeId for "TPM_Counter"
My UaBrowsepath consits of
"Daten"
"0"
"TPM_Counter"

The browse names where checked by UAExpert...

Annother example:

"DB_TPM_Zaehler_ZLT_Transfer"."TPM_Zaehler"."Daten"[0]
I know the NodeId for "TPM_Zaehler"
My UaBrowsepath consits of
"Daten"
"0"

User avatar
Support Team
Hero Member
Hero Member
Posts: 3064
Joined: 18 Mar 2011, 15:09

Re: Handling of translateBrowsePathsToNodeIds on arrays

Post by Support Team »

Hello Arthur,

I did a quick test with the "model" you provided and it works fine.

Testcode in server - NodeManager derived from NodeManagerBase

Code: Select all

    UaVariant value;
    UaString sName;
    UaString sNodeId;
    UaStatus addResult;
    OpcUa::BaseDataVariableType* pVariable = NULL;
    OpcUa::BaseDataVariableType* pVariable2 = NULL;

    // "DB_TPM_Counter"."TPM_Counter".
    value.setUInt16(123);
    sName = "\"DB_TPM_Counter\".\"TPM_Counter\"";
    sNodeId = sName;
    pVariable = new OpcUa::BaseDataVariableType(
        UaNodeId(sNodeId, getNameSpaceIndex()),
        sName,
        getNameSpaceIndex(),
        value,
        OpcUa_AccessLevels_CurrentReadOrWrite,
        this,
        m_pSharedNodeMutex);
    addResult = addNodeAndReference(OpcUaId_ObjectsFolder, pVariable, OpcUaId_Organizes);
    if (addResult.isBad())
    {
        pVariable->deleteAllChildren(this);
        pVariable->releaseReference();
    }

    // "Daten"
    sName = "\"Daten\"";
    sNodeId = UaString("%1.%2").arg(sNodeId).arg(sName);
    pVariable2 = new OpcUa::BaseDataVariableType(
        UaNodeId(sNodeId, getNameSpaceIndex()),
        sName,
        getNameSpaceIndex(),
        value,
        OpcUa_AccessLevels_CurrentReadOrWrite,
        this,
        m_pSharedNodeMutex);
    addResult = addNodeAndReference(pVariable, pVariable2, OpcUaId_HasComponent);
    if (addResult.isBad())
    {
        pVariable2->deleteAllChildren(this);
        pVariable2->releaseReference();
    }
    pVariable = pVariable2;

    // [0]
    sName = "[0]";
    sNodeId = UaString("%1%2").arg(sNodeId).arg(sName);
    pVariable2 = new OpcUa::BaseDataVariableType(
        UaNodeId(sNodeId, getNameSpaceIndex()),
        sName,
        getNameSpaceIndex(),
        value,
        OpcUa_AccessLevels_CurrentReadOrWrite,
        this,
        m_pSharedNodeMutex);
    pVariable2->setBrowseName(UaQualifiedName("\"0\"", getNameSpaceIndex()));
    addResult = addNodeAndReference(pVariable, pVariable2, OpcUaId_HasComponent);
    if (addResult.isBad())
    {
        pVariable2->deleteAllChildren(this);
        pVariable2->releaseReference();
    }
    pVariable = pVariable2;

    // "TPM_Counter"
    sName = "\"TPM_Counter\"";
    sNodeId = UaString("%1.%2").arg(sNodeId).arg(sName);
    pVariable2 = new OpcUa::BaseDataVariableType(
        UaNodeId(sNodeId, getNameSpaceIndex()),
        sName,
        getNameSpaceIndex(),
        value,
        OpcUa_AccessLevels_CurrentReadOrWrite,
        this,
        m_pSharedNodeMutex);
    addResult = addNodeAndReference(pVariable, pVariable2, OpcUaId_HasComponent);
    if (addResult.isBad())
    {
        pVariable2->deleteAllChildren(this);
        pVariable2->releaseReference();
    }
    pVariable = pVariable2;
Best regards
Unified Automation Support Team

User avatar
Support Team
Hero Member
Hero Member
Posts: 3064
Joined: 18 Mar 2011, 15:09

Re: Handling of translateBrowsePathsToNodeIds on arrays

Post by Support Team »

testcode in client:

Code: Select all

    UaStatus                status;
    UaDiagnosticInfos       diagnosticInfos;
    ServiceSettings         serviceSettings;
    UaBrowsePaths           browsePaths;
    UaBrowsePathResults     browsePathResults;
    UaRelativePathElements  pathElements;
    OpcUa_UInt32            i;
    OpcUa_UInt32            itemCount;

    itemCount = 1;
    browsePaths.create(itemCount);

    // Set path
    OpcUa_UInt16 namespaceIndex = 2;    // set the correct namespaceIndex here
    UaString sNodeId = "\"DB_TPM_Counter\".\"TPM_Counter\"";
    UaNodeId startingNode(sNodeId, namespaceIndex);
    printf("**    Path[0] start \"DB_TPM_Counter\".\"TPM_Counter\"\n");
    startingNode.copyTo(&browsePaths[0].StartingNode);
    pathElements.create(3);

    // element "Daten"
    pathElements[0].IncludeSubtypes = OpcUa_True;
    pathElements[0].IsInverse       = OpcUa_False;
    pathElements[0].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
    OpcUa_String_AttachReadOnly(&pathElements[0].TargetName.Name, "\"Daten\"");
    pathElements[0].TargetName.NamespaceIndex = namespaceIndex;

    // element  "0"
    pathElements[1].IncludeSubtypes = OpcUa_True;
    pathElements[1].IsInverse       = OpcUa_False;
    pathElements[1].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
    OpcUa_String_AttachReadOnly(&pathElements[1].TargetName.Name, "\"0\"");
    pathElements[1].TargetName.NamespaceIndex = namespaceIndex;

    // element "TPM_Counter"
    pathElements[2].IncludeSubtypes = OpcUa_True;
    pathElements[2].IsInverse = OpcUa_False;
    pathElements[2].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
    OpcUa_String_AttachReadOnly(&pathElements[2].TargetName.Name, "\"TPM_Counter\"");
    pathElements[2].TargetName.NamespaceIndex = namespaceIndex;

    browsePaths[0].RelativePath.NoOfElements = pathElements.length();
    browsePaths[0].RelativePath.Elements = pathElements.detach();

    status = g_pUaSession->translateBrowsePathsToNodeIds(
        serviceSettings,
        browsePaths,
        browsePathResults,
        diagnosticInfos);
Did you check if you set the correct namespaceIndexes in the BrowsePathElements? Dependent on your model the namespaceIndex in the NodeId and the namespaceIndex in the BrowseName may be different.
Best regards
Unified Automation Support Team

ArthurS
Jr. Member
Jr. Member
Posts: 4
Joined: 12 Oct 2022, 14:40

Re: Handling of translateBrowsePathsToNodeIds on arrays

Post by ArthurS »

Thank you for the answer.

I have checked the namspaces again. They are ok.

There are also other nodes in the structure, which I can translate. It just always fails when an array comes into play.

I copied your code and called it as a test function. There I get also with the other nodes, which worked before, the error BadNoMatch. The difference to my code is the use of the apostrophe.

Can it be that here rather the server has a problem? It is a Siemens S7-1500.

Code: Select all

	
	// element "Daten"
	pathElements[0].IncludeSubtypes = OpcUa_True;
	pathElements[0].IsInverse = OpcUa_False;
	pathElements[0].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
	OpcUa_String_AttachReadOnly(&pathElements[0].TargetName.Name, "Daten");
//	OpcUa_String_AttachReadOnly(&pathElements[0].TargetName.Name, "Handshake");
	pathElements[0].TargetName.NamespaceIndex = namespaceIndex;

	// element  "0"
	pathElements[1].IncludeSubtypes = OpcUa_True;
	pathElements[1].IsInverse = OpcUa_False;
	pathElements[1].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
	OpcUa_String_AttachReadOnly(&pathElements[1].TargetName.Name, "0");
//	OpcUa_String_AttachReadOnly(&pathElements[1].TargetName.Name, "DatenAnGateway");
	pathElements[1].TargetName.NamespaceIndex = namespaceIndex;

	// element "TPM_Counter"
	pathElements[2].IncludeSubtypes = OpcUa_True;
	pathElements[2].IsInverse = OpcUa_False;
	pathElements[2].ReferenceTypeId.Identifier.Numeric = OpcUaId_HierarchicalReferences;
	OpcUa_String_AttachReadOnly(&pathElements[2].TargetName.Name, "TPM_Counter");
//	OpcUa_String_AttachReadOnly(&pathElements[2].TargetName.Name, "Daten_bereit");
	pathElements[2].TargetName.NamespaceIndex = namespaceIndex;
DB_TPM_Counter.TPM_Counter.Handshake.DatenAnGateway.Daten_bereit works
DB_TPM_Counter.TPM_Counter.Daten.0.TPM_Counter don't work

User avatar
Support Team
Hero Member
Hero Member
Posts: 3064
Joined: 18 Mar 2011, 15:09

Re: Handling of translateBrowsePathsToNodeIds on arrays

Post by Support Team »

Hello Arthur,

the NodeId you posted contains quotation marks. The question is if the BrowseNames also contain quotation marks or not.

Dependent on that you need to set the string also with or without quotation:

Code: Select all

OpcUa_String_AttachReadOnly(&pathElements[0].TargetName.Name, "\"Daten\"");
vs.
OpcUa_String_AttachReadOnly(&pathElements[0].TargetName.Name, "Daten");
In UaExpert the attribute widget puts a quotation around the string part of the BrowseName. So it will either display "Daten" or ""Daten"".

If that still does not help you need to contact the server vendor and find out if translate is supposed to work for arrays.
Best regards
Unified Automation Support Team

Post Reply