[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

posted @ 2021-09-03 23:37  黑不秋  阅读(539)  评论(0)    收藏  举报