How to write single structure element on client side

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

Moderator: uasdkcpp

Post Reply
webmat81
Jr. Member
Jr. Member
Posts: 2
Joined: 28 Mar 2022, 06:41

How to write single structure element on client side

Post by webmat81 »

Hello,

I have a question about the ExtensionObjects that are not known at compile time on the client side.

I already know how to read the elements of an ExtensionObject thanks to the example code with the "printGenericStructureValue" function in "callback.h" file. I also know how to write the standard data types like Byte, Float, etc. as shown in the "write" function in "client_cpp_sdk.cpp" file. But I found no example on how to write values of an ExtensionObject, especially only parts of the whole structure. Is there any example code for that available, maybe I have just missed it.

For example, in the UaCPPServer, there is the "Person1" structure with "Name", "Height" and so on elements and I want to change only the value of the "Name" element. How can I do that?

My approach would be, that once I know the structure of that data type by reading the node from the server and getting the structure definition with the "structureDefinition" function, I have to rebuild that structure with all elements in it and put it to my write function to write the node on the server. But when I want to change only one value, can I just ignore the other elements in the structure? Like in the example with the "Person1", I would only build an extension object with the "Name" element in it and put that to my write function. Would that work?

Best Regards,

Matthias

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

Re: How to write single structure element on client side

Post by Support Team »

Hello,

Your approach is absolutely correct. It is possible to write a value to a single field of the structure, However, other field’s values will be set to default.
After getting the structure definition, the client has no knowledge about the field's value, only knows the fields.

If you would like to keep the same old values, what you should do is read the value of a structure first, then set the "Name" field with a new value (Ex: "SuperMan"), keep the old values that you read,
else
Set all the fields with new values.

We don't have any documentation explaining how to write extensionobjects. Hopefully, we will include them in the next major release of the C++ SDK V1.8.

I have created an example code (using the structure variable "Person1") for you based on the C++ example client (client_cpp_sdk).

Code: Select all

    OpcUa_UInt32      i;
    OpcUa_UInt32      count;
    UaStatus          status;
    UaVariant         tempValue;
    UaWriteValues     nodesToWrite;
    UaStatusCodeArray results;
    UaDiagnosticInfos diagnosticInfos;
    ServiceSettings   serviceSettings;
    UaReadValueIds    nodesToRead;
    UaDataValues      values;

    count = 1;
    UaNodeId variableNodeId("Person1", 2);
    nodesToRead.create(count);

    // Read the value of Person1
    variableNodeId.copyTo(&nodesToRead[0].NodeId);
    nodesToRead[0].AttributeId = OpcUa_Attributes_Value;
    /*********************************************************************
     Call read service
    **********************************************************************/
    status = g_pUaSession->read(
        serviceSettings,                // Use default settings
        0,                              // Max age
        OpcUa_TimestampsToReturn_Both,  // Time stapmps to return
        nodesToRead,                    // Array of nodes to read
        values,                         // Returns an array of values
        diagnosticInfos);               // Returns an array of diagnostic info
    /*********************************************************************/

    UaVariant varTemp(values[0].Value);
    UaExtensionObject extensionObject;
    varTemp.toExtensionObject(extensionObject);

    UaNodeId personDT(543210, 2);
    UaStructureDefinition structDef = g_pUaSession->structureDefinition(personDT);
    UaGenericStructureValue genericValue;
    genericValue.setGenericValue(extensionObject, structDef);


    // Only set the field "Name" and keep the old values for remaining fields
    genericValue.setField(0, UaString("SuperMan")); // Name
    // genericValue has old field (Height, Weight, Gender) values

    nodesToWrite.create(count);
    variableNodeId.copyTo(&nodesToWrite[0].NodeId);
    nodesToWrite[0].AttributeId = OpcUa_Attributes_Value;
    genericValue.toDataValue(nodesToWrite[0].Value, OpcUa_False);

    /*********************************************************************
     Call write service
    **********************************************************************/
    status = g_pUaSession->write(
        serviceSettings,                // Use default settings
        nodesToWrite,                   // Array of nodes to write
        results,                        // Returns an array of status codes
        diagnosticInfos);               // Returns an array of diagnostic info
Best regards
Unified Automation Support Team

webmat81
Jr. Member
Jr. Member
Posts: 2
Joined: 28 Mar 2022, 06:41

Re: How to write single structure element on client side

Post by webmat81 »

Hello Support Team,

thank you for the information and the example code.

It seems that some PLC, which can act like OPC UA Servers, serve structures as ExtensionObjects (where I can use the example read/write code) but also serve every element of that structure as a separate node, which you can get if you browse the node of the ExtensionObject itself. Now I can read / write every element of that structure using the node of that element.

But how can I detect that behaviour without trying to browse the node with the ExtensionObject? I think in the UaCPPServer application, there is the node "Demo.WorkOrder.WorkOrderVariable" which shows the same behaviour. I can also browse the elements of that structure like "AssetID" and do not have to care about the other elements. Is there a flag in the ExtensionObject that says something like "my elements are reachable as nodes too"?

Best Regards,

Matthias

Post Reply