C++ OPC UA Server: Dynamically creating complex strutures

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

Moderator: uasdkcpp

Post Reply
CP4TrumpfForum
Jr. Member
Jr. Member
Posts: 1
Joined: 24 Aug 2021, 10:30

C++ OPC UA Server: Dynamically creating complex strutures

Post by CP4TrumpfForum »

Hello,

we need to dynamically create nodes on an OPC UA server at runtime
as the types are not known at compile time. We use C++ OPC UA Server SDK.
Lessons learned so far from the DemoServer (see NodeManagerDemo::createTypeNodes()):

1) Dynamically create a struct type (making use of UaStructureDefinition):

Code: Select all

UaStructureDefinition personStructure;
personStructure.setName("Person");
personStructure.setDataTypeId(UaNodeId(Demo_PersonStruct, getNameSpaceIndex()));
personStructure.setBinaryEncodingId(UaNodeId(Demo_PersonStruct_DefaultBinary, getNameSpaceIndex()));
personStructure.setXmlEncodingId(UaNodeId(Demo_PersonStruct_DefaultXml, getNameSpaceIndex()));

UaStructureField personField;
personField.setName("Name");
personField.setDataTypeId(OpcUaId_String);
personField.setArrayType(UaStructureField::ArrayType_Scalar);
personStructure.addChild(personField);
personField.setName("Height");
personField.setDataTypeId(OpcUaId_UInt16);
personStructure.addChild(personField);

UaStatus addResult = addStructuredType(personStructure);
Corresponds to a struct like

Code: Select all

struct Person
{
  std::string Name;
  uint16_t Height;
};

2) Dynamically create a variable of that struct type (making use of UaGenericStructureValue):

Code: Select all

UaNode* pStructures = findNode(UaNodeId(DemoId_Demo_Static_Scalar_Structures, getNameSpaceIndex()));
if (pStructures)
{
  UaGenericStructureValue person = UaGenericStructureValue(structureDefinition(UaNodeId(Demo_PersonStruct, getNameSpaceIndex())));
  value.setString("Fat Boy");
  person.setField("Name", value, OpcUa_True);
  value.setUInt16(171);
  person.setField("Height", value, OpcUa_True);
  ...
}

Question:
How to implement steps 1) and 2) for a struct that contains another struct? E.g.

Code: Select all

struct PersonExt
{	
  uint16_t Id;
  Person Someone;
};
1) What worked so far:

Code: Select all

UaStructureDefinition personExtStructure;
personExtStructure.setName("PersonExt");
personExtStructure.setDataTypeId(UaNodeId(Demo_PersonExtStruct, getNameSpaceIndex()));
personExtStructure.setBinaryEncodingId(UaNodeId(Demo_PersonExtStruct_DefaultBinary, getNameSpaceIndex()));
personExtStructure.setXmlEncodingId(UaNodeId(Demo_PersonExtStruct_DefaultXml, getNameSpaceIndex()));

UaStructureField personExtField;
personExtField.setName("Id");
personExtField.setDataTypeId(OpcUaId_UInt16);
personExtStructure.addChild(personExtField);
personExtField.setName("Someone");
personExtField.setDataTypeId(Demo_PersonStruct);
personExtStructure.addChild(personExtField);

addResult = addStructuredType(personExtStructure);
2) Second step does not work for the "Person"-field in the "PersonExt"-variable when done as follows:

Code: Select all

UaGenericStructureValue personExt(structureDefinition(UaNodeId(Demo_PersonExtStruct, getNameSpaceIndex())));
value.setUInt16(171);
personExt.setField("Id", value, OpcUa_True);

UaGenericStructureValue personField = UaGenericStructureValue(structureDefinition(UaNodeId(Demo_PersonStruct, getNameSpaceIndex())));
value.setString("Fat Boy2");
personField.setField("Name", value, OpcUa_True);
value.setUInt16(1710);
personField.setField("Height", value, OpcUa_True);

res = personExt.setField("Someone", personField); // <= this does not work

It seems that this is not the correct way to add the "Person"-value to the "PersonExt"-field.
Some code snippets that do the job properly would be greatly appreciated - Thanks.

Post Reply