Get value data type conveniently when using UA_Client_Service_browse

544 views
Skip to first unread message

sebastian....@gmail.com

unread,
Sep 14, 2016, 5:58:14 AM9/14/16
to open62541
Hi,

my scenario is: Get all variable children of a node with their node ID, browse name and the value data type.

I have solved it so far but I do not like the way I get the value data type. It looks to me that there has to be a more clever way of doing it. Is there? Do I really have to fetch the value?

    UA_BrowseRequest request;
    UA_BrowseRequest_init(&request);
    request.requestedMaxReferencesPerNode = 0;
    request.nodesToBrowse = UA_BrowseDescription_new();
    request.nodesToBrowseSize = 1;
    request.nodesToBrowse[0].nodeId = /* MY NODE */;
    request.nodesToBrowse[0].resultMask =
        UA_BROWSERESULTMASK_NODECLASS | UA_BROWSERESULTMASK_BROWSENAME;

    UA_BrowseResponse response = UA_Client_Service_browse(client, request);
    for (size_t resultsIndex = 0, total = response.resultsSize; resultsIndex < total;
         ++resultsIndex) {
        for (size_t referencesIndex = 0, total = response.results[resultsIndex].referencesSize;
             referencesIndex < total; ++referencesIndex) {
            const UA_ReferenceDescription &reference =
                response.results[resultsIndex].references[referencesIndex];

            if (reference.nodeClass == UA_NODECLASS_VARIABLE) {
                // The node id is:  reference.nodeId.nodeId
                // Browse name:     reference.browseName.name
                // Value Data type: ???
                // Is there a better way than:
                UA_Variant value;
                UA_Variant_init(&value);
                const UA_StatusCode status =
                    UA_Client_readValueAttribute(client, reference.nodeId.nodeId, &value);
                if (status == UA_STATUSCODE_GOOD) {
                    if (value.type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
                        // It's a boolean! Test for other types...
                    }
                }
                UA_Variant_deleteMembers(&value);
            }
        }
    }

    UA_BrowseResponse_deleteMembers(&response);
    UA_BrowseRequest_deleteMembers(&request);



Thanks for any input or general comments.

Cheers
Sebastian




f.palm

unread,
Sep 14, 2016, 6:36:18 AM9/14/16
to open62541, sebastian....@gmail.com
Hi Sebastian,

if you look into part 6 of IEC 62541 at Table A.1 you can find the identifier for the attributes of a node. Identifier=14 is the datatype.Thus, you only need to read the datatype attribute. You can use the function
"UA_Client_readDataTypeAttribute" to do that.

regards,
Florian

sebastian....@gmail.com

unread,
Sep 14, 2016, 7:33:45 AM9/14/16
to open62541, sebastian....@gmail.com
Hi Florian,

thanks for your answer. I've had already played with UA_Client_readDataTypeAttribute but refused to use it since I didn't know what to do with the returned node ID :)

After a second look one has to do this in order to get the underlying type:

UA_NodeId xx;
UA_Client_readDataTypeAttribute(client, reference.nodeId.nodeId, &xx); // test for success...
for (int i = 0; i < UA_TYPES_COUNT; ++i) {
    if (UA_NodeId_equal(&UA_TYPES[i].typeId, &xx)) {
        if (i == UA_TYPES_BOOLEAN)
            // Yeah, it's a boolean.
        break;
    }
}


Of course this should be cached and and so on.

Right, or do I miss the obvious again?

Thanks for your help!
Sebastian

Julius Pfrommer

unread,
Sep 14, 2016, 7:54:36 AM9/14/16
to open62541, sebastian....@gmail.com
Hey Florian,

there is a difference between the node-datatype and the datatype of the value you are reading.

The node-datatype may be an abstract type "Number" in the datatype hierarchy.
And the actual value has a type derived from that, e.g. "UInt32".

Checking that these contraints hold and better documentation for this will land soon.
(We need it to pass the conformance tests.)

So you can both do a readDataTypeAttribute **and** do a readValueAttribute.
The returned value will be inside a variant. There, you don't have to compare NodeIds.
Instead, you can compare pointers, such as

if(variant->type == &UA_TYPES[UA_TYPES_BOOLEAN) {
...

Best regards,
Julius


Reply all
Reply to author
Forward
0 new messages