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);
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;
};
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);
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.