当前位置:网站首页>学习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就行了。
边栏推荐
- Chapter 3 business function development (to remember account and password)
- socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现
- AI defeated mankind and designed a better economic mechanism
- 能同时做三个分割任务的模型,性能和效率优于MaskFormer!Meta&UIUC提出通用分割模型,性能优于任务特定模型!开源!...
- C语言中匿名的最高境界
- Wireshark分析抓包数据*.cap
- PHP面试题 foreach($arr as &$value)与foreach($arr as $value)的用法
- 直播软件搭建,canvas文字加粗
- 【demo】循环队列及条件锁实现goroutine间的通信
- Chapter 1 Introduction to CRM core business
猜你喜欢

AI 击败了人类,设计了更好的经济机制

卖空、加印、保库存,东方甄选居然一个月在抖音卖了266万单书

Summary of evaluation indicators and important knowledge points of regression problems

标准ACL与扩展ACL

socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现

Performance test process and plan

【C语言】字符串函数

【蓝桥杯集训100题】scratch从小到大排序 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第17题
![[principle and technology of network attack and Defense] Chapter 6: Trojan horse](/img/2f/bd35ca141fad5c85f78fd6340ada1d.png)
[principle and technology of network attack and Defense] Chapter 6: Trojan horse

线程池和单例模式以及文件操作
随机推荐
2022年理财有哪些产品?哪些适合新手?
数学分析_笔记_第11章:Fourier级数
idea彻底卸载安装及配置笔记
Kubernetes DevOps CD工具对比选型
Industry case | digital operation base helps the transformation of life insurance industry
Tear the Nacos source code by hand (tear the client source code first)
[paddleseg source code reading] add boundary IOU calculation in paddleseg validation (1) -- val.py file details tips
Five network IO models
String type, constant type and container type of go language
Backup Alibaba cloud instance OSS browser
What is the general yield of financial products in 2022?
现货白银分析中的一些要点
Disk storage chain B-tree and b+ tree
回归问题的评价指标和重要知识点总结
[principles and technologies of network attack and Defense] Chapter 3: network reconnaissance technology
Introduction of common API for socket programming and code implementation of socket, select, poll, epoll high concurrency server model
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
Idea completely uninstalls installation and configuration notes
AntiSamy:防 XSS 攻击的一种解决方案使用教程
低代码助力企业数字化转型会让程序员失业?