[2]open62541添加枚举类型
本文介绍在open62541中创建自定义枚举类型以及创建枚举变量。
1.效果
枚举变量每一个值有其对应的名字,便于理解枚举值的含义


2.整体代码
1 #include <signal.h> 2 #include <stdio.h> 3 #include <open62541/server.h> 4 #include <open62541/server_config.h> 5 #include <open62541/server_config_default.h> 6 #include <open62541/plugin/log_stdout.h> 7 #include <assert.h> 8 9 UA_StatusCode addEnumType(UA_Server *server, UA_NodeId *typeId, const char *typeName, uint32_t nValues, char **valuesName, int *values) 10 { 11 //add type 12 { 13 UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; 14 attr.description = UA_LOCALIZEDTEXT("en", typeName); 15 attr.displayName = UA_LOCALIZEDTEXT("en", typeName); 16 17 auto ret = UA_Server_addDataTypeNode(server, *typeId, 18 UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION), 19 UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), 20 UA_QUALIFIEDNAME(1, typeName), attr, NULL, typeId); 21 if (UA_STATUSCODE_GOOD != ret) 22 return ret; 23 } 24 25 //add type child value 26 { 27 UA_VariableAttributes attr = UA_VariableAttributes_default; 28 attr.valueRank = UA_VALUERANK_ONE_DIMENSION; 29 attr.arrayDimensionsSize = 1; 30 attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMVALUETYPE); 31 attr.displayName = UA_LOCALIZEDTEXT("en", "EnumValues"); 32 attr.description = UA_LOCALIZEDTEXT("en", "EnumValues"); 33 attr.arrayDimensions = UA_malloc(sizeof(uint32_t)); 34 *attr.arrayDimensions = nValues; 35 36 UA_EnumValueType *uaValues = (nValues > 0) ? UA_malloc(sizeof(UA_EnumValueType) * nValues) : NULL; 37 for (size_t i = 0; i < nValues; i++) 38 { 39 UA_init(&uaValues[i], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); 40 uaValues[i].value = values[i]; 41 uaValues[i].description = UA_LOCALIZEDTEXT("en", valuesName[i]); 42 uaValues[i].displayName = UA_LOCALIZEDTEXT("en", valuesName[i]); 43 } 44 45 UA_Variant_setArray(&attr.value, uaValues, nValues, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); 46 47 UA_NodeId enumValuesId; 48 auto ret = UA_Server_addVariableNode(server, UA_NODEID_NULL, *typeId, 49 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), 50 UA_QUALIFIEDNAME(0, "EnumValues"), 51 UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), 52 attr, NULL, &enumValuesId); 53 if (UA_STATUSCODE_GOOD != ret) 54 return ret; 55 56 return UA_Server_addReference(server, enumValuesId, 57 UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE), 58 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), 59 true); 60 } 61 } 62 63 UA_StatusCode addEnumVariable(UA_Server *server, UA_NodeId *id, const UA_NodeId typeId, const char *name) 64 { 65 UA_VariableAttributes vattr = UA_VariableAttributes_default; 66 67 vattr.description = UA_LOCALIZEDTEXT("en", name); 68 vattr.displayName = UA_LOCALIZEDTEXT("en", name); 69 vattr.dataType = typeId; 70 vattr.valueRank = -1; 71 vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; 72 UA_Int32 val = 1;//A 73 UA_Variant_setScalar(&vattr.value, &val, &UA_TYPES[UA_TYPES_INT32]); 74 75 return UA_Server_addVariableNode(server, 76 *id, 77 UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), 78 UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), 79 UA_QUALIFIEDNAME(1, name), 80 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), 81 vattr, 82 NULL, 83 id); 84 } 85 86 UA_Boolean running = true; 87 static void stopHandler(int sig) 88 { 89 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c"); 90 running = false; 91 } 92 93 int main(void) 94 { 95 signal(SIGINT, stopHandler); 96 signal(SIGTERM, stopHandler); 97 98 UA_Server *server = UA_Server_new(); 99 UA_ServerConfig_setDefault(UA_Server_getConfig(server)); 100 101 UA_NodeId typeId = UA_NODEID_NUMERIC(1, 5050); 102 UA_NodeId varId = UA_NODEID_NUMERIC(1, 5060); 103 104 uint32_t valArray[] = {1, 2, 3}; 105 char *nameArray[] = {"A", "B", "C"}; 106 addEnumType(server, &typeId, "testEnumType", 3, nameArray, valArray); 107 addEnumVariable(server, &varId, typeId, "testEnum"); 108 109 UA_Variant val; 110 UA_Variant_init(&val); 111 UA_Variant_setScalar(&val, &valArray[2], &UA_TYPES[UA_TYPES_INT32]); 112 UA_Server_writeValue(server, varId, val); //set value to C 113 114 UA_StatusCode retval = UA_Server_run(server, &running); 115 UA_Server_delete(server); 116 return (int)retval; 117 }
2.1添加枚举类型
自定义枚举类型要继承自基本类型中的枚举类型(Types/DataTypes/BaseDataType/Enumeration)
UA_Server_addDataTypeNode(server, *typeId, UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, typeName), attr, NULL, typeId);
然后为枚举类型添加枚举值
attr.arrayDimensionsSize = 1; 枚举值以一维数组表示
attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMVALUETYPE); 枚举值类型(通过id指定)
attr.arrayDimensions = nValues; 数组元素的个数即枚举值的数量
为枚举值填充实际的数值和名字:
UA_EnumValueType *uaValues = (nValues > 0) ? UA_malloc(sizeof(UA_EnumValueType) * nValues) : NULL; for (size_t i = 0; i < nValues; i++) { UA_init(&uaValues[i], &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); uaValues[i].value = values[i]; uaValues[i].description = UA_LOCALIZEDTEXT("en", valuesName[i]); uaValues[i].displayName = UA_LOCALIZEDTEXT("en", valuesName[i]); } UA_Variant_setArray(&attr.value, uaValues, nValues, &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
最后将枚举值作为枚举类型的属性添加到枚举类型节点下:
UA_Server_addVariableNode(server, UA_NODEID_NULL, *typeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(0, "EnumValues"), UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), attr, NULL, &enumValuesId);
2.2创建枚举变量
使用以上创建的枚举类型创建变量:
UA_VariableAttributes vattr = UA_VariableAttributes_default; vattr.description = UA_LOCALIZEDTEXT("en", name); vattr.displayName = UA_LOCALIZEDTEXT("en", name); vattr.dataType = typeId; vattr.valueRank = -1; vattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; UA_Int32 val = 1; UA_Variant_setScalar(&vattr.value, &val, &UA_TYPES[UA_TYPES_INT32]); return UA_Server_addVariableNode(server, *id, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, name), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vattr, NULL, id);
实际运行显示如下:

3.问题
设置枚举变量值时使用的类型是int32?暂时未找到对此的详细说明
4.补充
以上程序参考QUaServer

本文介绍在open62541中创建自定义枚举类型以及创建枚举变量
浙公网安备 33010602011771号