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
How to write single structure element on client side
Moderator: uasdkcpp
-
- Jr. Member
- Posts: 2
- Joined: 28 Mar 2022, 06:41
- Support Team
- Hero Member
- Posts: 3072
- Joined: 18 Mar 2011, 15:09
Re: How to write single structure element on client side
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).
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
Unified Automation Support Team
-
- Jr. Member
- Posts: 2
- Joined: 28 Mar 2022, 06:41
Re: How to write single structure element on client side
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
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