I'm using the CPP server SDK and I've built a model with UA modeler, I can build my server and UA expert finds and discovers everything correctly.
I have 2 different node types:
- BaseDataType -> Enumeration -> MyEnumType which has an EnumString Property
- BaseDataType -> Number -> UInteger -> Byte -> MyBitFieldType which has an OptionSetValues Property
On my server I when I read the value of variables which are of MyEnumType and MyBitFieldType they appear to both just be enumerations. I can retrieve the values and the enum fields but I can't work out how to tell if it's a bit field or an enum. UA expert can tell the difference so I know it's possible.
How can I tell if a node has an EnumString Property or an OptionSetValues Property and is that the best way to tell the difference?
I can see that the UA modeler generated code has added a OpcUa::PropertyType ("OptionSetValues") reference to the type node.
Code: Select all
pOptionSetValues = new OpcUa::PropertyType(UaNodeId(myId_ButtonEnableType_OptionSetValues, getNameSpaceIndex()), "OptionSetValues", 0, defaultValue, 1, this);
defaultValue.clear();
// ButtonEnableType
pDataType = new UaGenericDataTypeEnum(
UaNodeId(myId_ButtonEnableType, getNameSpaceIndex()),
UaQualifiedName("ButtonEnableType", getNameSpaceIndex()),
UaLocalizedText("", "ButtonEnableType"),
UaLocalizedText("", ""),
OpcUa_False,
enumFields);
ret = addNodeAndReference(UaNodeId(OpcUaId_Byte), pDataType, OpcUaId_HasSubtype);
UA_ASSERT(ret.isGood());
ret = addNodeAndReference(pDataType, pOptionSetValues, OpcUaId_HasProperty);
UA_ASSERT(ret.isGood());
...
pEnumString = new OpcUa::PropertyType(UaNodeId(myId_DataStateType_EnumStrings, getNameSpaceIndex()), "EnumStrings", 0, defaultValue, 1, this);
defaultValue.clear();
// DataStateType
pDataType = new UaGenericDataTypeEnum(
UaNodeId(myId_DataStateType, getNameSpaceIndex()),
UaQualifiedName("DataStateType", getNameSpaceIndex()),
UaLocalizedText("", "DataStateType"),
UaLocalizedText("", ""),
OpcUa_False,
UaEnumDefinitionDataType(enumFields));
ret = addNodeAndReference(OpcUaId_Enumeration, pDataType, OpcUaId_HasSubtype);
UA_ASSERT(ret.isGood());
ret = addNodeAndReference(pDataType, pEnumString, OpcUaId_HasProperty);
UA_ASSERT(ret.isGood());
Code: Select all
void MyNodeManager::add_type_info_to_dict(Session *pSession, UaVariable *var, const UaDataValue &dataValue)
{
if (var->nodeClass() != OpcUa_NodeClass_Variable)
{
return;
}
OpcUa_UInt32 type_nod_id = var->dataType().identifierNumeric();
if (type_nod_id > 1000)
{
UaNode *type_node = getInstanceDeclarationNode(type_nod_id, OpcUa_NodeClass_DataType);
if (type_node)
{
UaDataType *data_type = (UaDataType*) type_node;
if (data_type->dataTypeDefinitionType() == UaDataType::DataTypeDefinitionType_Enum)
{
UaEnumFields fields;
data_type->enumDefinition().getFields(fields);
printf("Enum\n");
for (int i = 0; i < fields.length(); i++)
{
fields[i].Value;
fields[i].Name;
}
}
}
}
}