当前位置:网站首页>学习open62541 --- [67] 添加自定义Enum并显示名字
学习open62541 --- [67] 添加自定义Enum并显示名字
2022-07-07 16:49:00 【爱就是恒久忍耐】
Enum类型的变量有点特殊,在base data type里,可以看到enum不能直接实例化,
其属性如下,是抽象类型,
对于自定义enum,需要经过3个步骤来操作,
- 先定义对应的DataType
- 然后再定义对应的变量类型
- 最后使用这个变量类型来创建enum变量
本文讲述如何添加自定义Enum,并创建对应的变量
一 代码
代码如下,
#include "open62541.h"
static bool running = true;
static void stopHandler(int sig) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
running = false;
}
UA_UInt16 LocalServerNSIndex = 1;
typedef enum {
AA = 0,
BB = 1,
CC = 2,
DD = 3,
__MY_ENUM_FORCE32BIT = 0x7fffffff
} MyEnum;
// 定义DataType
static UA_DataType MyEnumDataType =
{
UA_TYPENAME("MyEnum") /* .typeName */
{
LocalServerNSIndex, UA_NODEIDTYPE_NUMERIC, {
0}}, /* .typeId */
{
LocalServerNSIndex, UA_NODEIDTYPE_NUMERIC, {
0}}, /* .binaryEncodingId */
sizeof(MyEnum), /* .memSize */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
1, /* .overlayable */
0, /* .membersSize */
NULL /* .members */
};
// 把enum的datatype添加到namespace里
UA_StatusCode addMyEnumDataType(UA_Server* server)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Data Type");
ret = UA_Server_addDataTypeNode(
server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My.Enum"), attr, NULL, &MyEnumDataType.typeId);
return ret;
}
// 把enum对应的变量类型添加到namespace里
UA_StatusCode addMyEnumVariableType(UA_Server *server, UA_NodeId& myEnumVarTypeId)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes dattr = UA_VariableTypeAttributes_default;
dattr.description = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var type");
dattr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var type");
dattr.dataType = MyEnumDataType.typeId;
dattr.valueRank = UA_VALUERANK_SCALAR;
MyEnum p = AA;
UA_Variant_setScalar(&dattr.value, &p, &MyEnumDataType);
ret = UA_Server_addVariableTypeNode(server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My Enum Var type"),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
dattr, NULL, &myEnumVarTypeId);
return ret;
}
// 创建enum变量,并添加到namespace里
UA_StatusCode addMyEnumVariable(UA_Server *server, UA_NodeId myEnumVarTypeId)
{
MyEnum p = CC;
UA_VariableAttributes vattr = UA_VariableAttributes_default;
vattr.description = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var");
vattr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var");
vattr.dataType = MyEnumDataType.typeId;
vattr.valueRank = UA_VALUERANK_SCALAR;
UA_Variant_setScalar(&vattr.value, &p, &);
UA_StatusCode ret = UA_STATUSCODE_GOOD;
ret = UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My Enum Var"),
myEnumVarTypeId, vattr, NULL, NULL);
return ret;
}
int main(void)
{
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server);
UA_ServerConfig_setDefault(config);
UA_StatusCode ret = addMyEnumDataType(server);
if (UA_StatusCode_isGood(ret))
{
UA_NodeId myEnumVarTypeId;
ret = addMyEnumVariableType(server, myEnumVarTypeId);
if (UA_StatusCode_isGood(ret))
{
ret = addMyEnumVariable(server, myEnumVarTypeId);
}
}
if (UA_StatusCode_isBad(ret))
{
printf("Error\n");
UA_Server_delete(server);
return 0;
}
UA_Server_run(server, &running);
UA_Server_delete(server);
return 0;
}
编译成功后运行,可以看到变量添加成功,
其值为2,因为CC对应的值就是2
添加的自定义DataType也在namespace里,
二 添加enum名字
从上面的代码可以看到虽然enum变量添加了,似乎和一个int类型的数据没区别,最好能体现出其名字,这里讲下如何给enum类型添加对应的名称,
这里定义一个函数addEnumString,用于给enum的DataType添加名称,如下,
UA_StatusCode addEnumString(UA_Server *server)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
attr.valueRank = 1;
attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
attr.dataType = UA_NODEID_NUMERIC(0, 21LU);
UA_LocalizedText my_enum_variant_DataContents[4];
my_enum_variant_DataContents[0] = UA_LOCALIZEDTEXT((char*)"", (char*)"AA");
my_enum_variant_DataContents[1] = UA_LOCALIZEDTEXT((char*)"", (char*)"BB");
my_enum_variant_DataContents[2] = UA_LOCALIZEDTEXT((char*)"", (char*)"CC");
my_enum_variant_DataContents[3] = UA_LOCALIZEDTEXT((char*)"", (char*)"DD");
UA_Variant_setArray(&attr.value, &my_enum_variant_DataContents, (UA_Int32) 4, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
attr.displayName = UA_LOCALIZEDTEXT((char*)"", (char*)"EnumStrings");
UA_NodeId enumStringNodeId;
ret = UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
MyEnumDataType.typeId,
UA_NODEID_NUMERIC(0, 46LU),
UA_QUALIFIEDNAME(0, (char*)"EnumStrings"),
UA_NODEID_NUMERIC(0, 68LU),
(const UA_NodeAttributes*)&attr,
&UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, &enumStringNodeId);
if (UA_StatusCode_isGood(ret))
{
ret = UA_Server_addNode_finish(server, enumStringNodeId);
}
return ret;
}
有4个元素就添加4个名称,注意enum的值必须从0开始,后面都是顺序加1,否则就无法显示名称。在函数addMyEnumDataType里调用addEnumString,如下,
UA_StatusCode addMyEnumDataType(UA_Server* server)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Data Type");
ret = UA_Server_addDataTypeNode(
server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My.Enum"), attr, NULL, &MyEnumDataType.typeId);
if (UA_StatusCode_isGood(ret))
{
ret = addEnumString(server);
}
return ret;
}
重新编译运行,可以看到变量值后面加了其对应的名称,
在DataType里,也可以看到有EnumStrings,
查看EnumStrings的值,如下,是个数组,
这样就实现了我们的期望
完整代码如下,
#include "open62541.h"
static bool running = true;
static void stopHandler(int sig) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
running = false;
}
const UA_UInt16 LocalServerNSIndex = 1;
typedef enum {
AA = 0,
BB = 1,
CC = 2,
DD = 3,
__MY_ENUM_FORCE32BIT = 0x7fffffff
} MyEnum;
static UA_DataType MyEnumDataType =
{
UA_TYPENAME("MyEnum") /* .typeName */
{
LocalServerNSIndex, UA_NODEIDTYPE_NUMERIC, {
0}}, /* .typeId */
{
LocalServerNSIndex, UA_NODEIDTYPE_NUMERIC, {
0}}, /* .binaryEncodingId */
sizeof(MyEnum), /* .memSize */
UA_DATATYPEKIND_ENUM, /* .typeKind */
true, /* .pointerFree */
1, /* .overlayable */
0, /* .membersSize */
NULL /* .members */
};
UA_StatusCode addEnumString(UA_Server *server)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.minimumSamplingInterval = 0.000000;
attr.userAccessLevel = 1;
attr.accessLevel = 1;
attr.valueRank = 1;
attr.arrayDimensionsSize = 1;
UA_UInt32 arrayDimensions[1];
arrayDimensions[0] = 0;
attr.arrayDimensions = &arrayDimensions[0];
attr.dataType = UA_NODEID_NUMERIC(0, 21LU);
UA_LocalizedText my_enum_variant_DataContents[4];
my_enum_variant_DataContents[0] = UA_LOCALIZEDTEXT((char*)"", (char*)"AA");
my_enum_variant_DataContents[1] = UA_LOCALIZEDTEXT((char*)"", (char*)"BB");
my_enum_variant_DataContents[2] = UA_LOCALIZEDTEXT((char*)"", (char*)"CC");
my_enum_variant_DataContents[3] = UA_LOCALIZEDTEXT((char*)"", (char*)"DD");
UA_Variant_setArray(&attr.value, &my_enum_variant_DataContents, (UA_Int32) 4, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
attr.displayName = UA_LOCALIZEDTEXT((char*)"", (char*)"EnumStrings");
UA_NodeId enumStringNodeId;
ret = UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
MyEnumDataType.typeId,
UA_NODEID_NUMERIC(0, 46LU),
UA_QUALIFIEDNAME(0, (char*)"EnumStrings"),
UA_NODEID_NUMERIC(0, 68LU),
(const UA_NodeAttributes*)&attr,
&UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, &enumStringNodeId);
if (UA_StatusCode_isGood(ret))
{
ret = UA_Server_addNode_finish(server, enumStringNodeId);
}
return ret;
}
UA_StatusCode addMyEnumDataType(UA_Server* server)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Data Type");
ret = UA_Server_addDataTypeNode(
server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My.Enum"), attr, NULL, &MyEnumDataType.typeId);
if (UA_StatusCode_isGood(ret))
{
ret = addEnumString(server);
}
return ret;
}
UA_StatusCode addMyEnumVariableType(UA_Server *server, UA_NodeId& myEnumVarTypeId)
{
UA_StatusCode ret = UA_STATUSCODE_GOOD;
UA_VariableTypeAttributes dattr = UA_VariableTypeAttributes_default;
dattr.description = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var type");
dattr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var type");
dattr.dataType = MyEnumDataType.typeId;
dattr.valueRank = UA_VALUERANK_SCALAR;
MyEnum p = AA;
UA_Variant_setScalar(&dattr.value, &p, &MyEnumDataType);
ret = UA_Server_addVariableTypeNode(server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My Enum Var type"),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
dattr, NULL, &myEnumVarTypeId);
return ret;
}
UA_StatusCode addMyEnumVariable(UA_Server *server, UA_NodeId myEnumVarTypeId)
{
MyEnum p = CC;
UA_VariableAttributes vattr = UA_VariableAttributes_default;
vattr.description = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var");
vattr.displayName = UA_LOCALIZEDTEXT((char*)"en-US", (char*)"My Enum Var");
vattr.dataType = MyEnumDataType.typeId;
vattr.valueRank = UA_VALUERANK_SCALAR;
UA_Variant_setScalar(&vattr.value, &p, &UA_TYPES[UA_TYPES_INT32]);
UA_StatusCode ret = UA_STATUSCODE_GOOD;
ret = UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(LocalServerNSIndex, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(LocalServerNSIndex, (char*)"My Enum Var"),
myEnumVarTypeId, vattr, NULL, NULL);
return ret;
}
int main(void)
{
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server);
UA_ServerConfig_setDefault(config);
UA_StatusCode ret = addMyEnumDataType(server);
if (UA_StatusCode_isGood(ret))
{
UA_NodeId myEnumVarTypeId;
ret = addMyEnumVariableType(server, myEnumVarTypeId);
if (UA_StatusCode_isGood(ret))
{
ret = addMyEnumVariable(server, myEnumVarTypeId);
}
}
if (UA_StatusCode_isBad(ret))
{
printf("Error\n");
UA_Server_delete(server);
return 0;
}
UA_Server_run(server, &running);
UA_Server_delete(server);
return 0;
}
三 小结
本文讲述了如何添加自定义enum,并创建对应的变量,读者可以照葫芦画瓢,添加自己需要的enum。有个点需要注意,最后在创建enum变量时,使用的类型是int32,只需要在变量属性里指定好data type的id就行了。
边栏推荐
- 高考填志愿规则
- [trusted computing] Lesson 11: TPM password resource management (III) NV index and PCR
- 现货白银分析中的一些要点
- Introduction de l'API commune de programmation de socket et mise en œuvre de socket, select, Poll et epoll
- [principle and technology of network attack and Defense] Chapter 7: password attack technology Chapter 8: network monitoring technology
- 4种常见的缓存模式,你都知道吗?
- 云景网络科技面试题【杭州多测师】【杭州多测师_王sir】
- C语言中匿名的最高境界
- Tips of the week 136: unordered containers
- 单臂路由和三层交换的简单配置
猜你喜欢

持续测试(CT)实战经验分享

Yearning-SQL审核平台

Kirk Borne的本周学习资源精选【点击标题直接下载】

CVPR 2022丨学习用于小样本语义分割的非目标知识

NAT地址转换

DataSimba推出微信小程序,DataNuza接受全场景考验? | StartDT Hackathon

Simple configuration of single arm routing and layer 3 switching

Classification of regression tests

Tsinghua, Cambridge and UIC jointly launched the first Chinese fact verification data set: evidence-based, covering many fields such as medical society

清华、剑桥、UIC联合推出首个中文事实核查数据集:基于证据、涵盖医疗社会等多个领域
随机推荐
Tips for this week 131: special member functions and ` = Default`
【C语言】字符串函数
Industry case | digital operation base helps the transformation of life insurance industry
[principle and technology of network attack and Defense] Chapter 1: Introduction
The performance and efficiency of the model that can do three segmentation tasks at the same time is better than maskformer! Meta & UIUC proposes a general segmentation model with better performance t
Unlike the relatively short-lived industrial chain of consumer Internet, the industrial chain of industrial Internet is quite long
[论文分享] Where’s Crypto?
debian10系统问题总结
嵌入式C语言程序调试和宏使用的技巧
Yearning-SQL审核平台
[trusted computing] Lesson 12: TPM authorization and conversation
[principles and technologies of network attack and Defense] Chapter 5: denial of service attack
卖空、加印、保库存,东方甄选居然一个月在抖音卖了266万单书
强化学习-学习笔记8 | Q-learning
行业案例|数字化经营底座助力寿险行业转型
Yunjing network technology interview question [Hangzhou multi tester] [Hangzhou multi tester _ Wang Sir]
sqlite sql 异常 near “with“: syntax error
Nunjuks template engine
nest. Database for getting started with JS
[C language] string function