结合open62541 R1.1.2文档,在Ubuntu上编写的服务程序

开发环境:

Linux ubuntu16 4.15.0-117
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609(编译源代码)
ccmake version 3.5.1(生成open62541.c/.h)
vscode version 1.49.1(开发工具)
UaExpert version 1.4.4.257(测试工具)
参照open62541文档,生成 open62541.c/.h 文件。
并没有实质性的内容,只是熟悉一下环境

创建基础服务

代码

#include <open62541.h>
#include <signal.h>
#include <stdlib.h>


static volatile UA_Boolean running = true;
static void stopHandler(int sig) {
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
	running = false;
}
int main(void) {
	signal(SIGINT, stopHandler);
	signal(SIGTERM, stopHandler);
	UA_Server *server = UA_Server_new();
	UA_ServerConfig_setDefault(UA_Server_getConfig(server));
	UA_StatusCode retval = UA_Server_run(server, &running);
	UA_Server_delete(server);
	return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

编译、运行
参数 -I…/opcua_c 指定 open62541.h 文件所在目录,我这编译的时候,就算是复制到当前目录也提示找不到这个文件,所以添加了 -I 参数

gcc DemoServer.c open62541.c -o ds01 -I../opcua_c

运行效果如下图
在这里插入图片描述
使用UaExpert连接(地址:opc.tcp://<服务IP>:4840/)成功

在这里插入图片描述
在这里插入图片描述

添加自定义节点

代码

#include <open62541.h>
#include <signal.h>
#include <stdlib.h>


static void addVariable(UA_Server *server);
static void addMatrixVariable(UA_Server *server);


static volatile UA_Boolean running = true;
static void stopHandler(int sig) {
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
	running = false;
}
int main(void) {
	signal(SIGINT, stopHandler);
	signal(SIGTERM, stopHandler);
	UA_Server *server = UA_Server_new();
	UA_ServerConfig_setDefault(UA_Server_getConfig(server));

	// 添加节点
	addVariable(server);
	addMatrixVariable(server);

	UA_StatusCode retval = UA_Server_run(server, &running);
	UA_Server_delete(server);
	return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

 
static void addVariable(UA_Server *server) {
	/* 定义整数变量节点的属性 */
	UA_VariableAttributes attr = UA_VariableAttributes_default;
	UA_Int32 myInteger = 42;
	UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
	attr.description = UA_LOCALIZEDTEXT("zh-CN","整数类型节点");
	attr.displayName = UA_LOCALIZEDTEXT("zh-CN","整数类型节点");
	attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
	attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
	/* 将变量节点添加到信息模型中 */
	UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "整数类型节点");
	UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "整数类型节点");
	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
	UA_Server_addVariableNode(
		server, 
		myIntegerNodeId, 
		parentNodeId,
		parentReferenceNodeId, 
		myIntegerName,
		UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), 
		attr, 
		NULL, 
		NULL);
}

static void addMatrixVariable(UA_Server *server) {
	UA_VariableAttributes attr = UA_VariableAttributes_default;
	attr.displayName = UA_LOCALIZEDTEXT("zh-CN", "双精度数组");
	attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
	/* 设置变量值约束 */
	attr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
	attr.valueRank = UA_VALUERANK_TWO_DIMENSIONS;
	UA_UInt32 arrayDims[2] = {2,2};
	attr.arrayDimensions = arrayDims;
	attr.arrayDimensionsSize = 2;
	/* 设置值。值的数组维度必须相同。 */
	UA_Double zero[4] = {0.0, 0.0, 0.0, 0.0};
	UA_Variant_setArray(&attr.value, zero, 4, &UA_TYPES[UA_TYPES_DOUBLE]);
	attr.value.arrayDimensions = arrayDims;
	attr.value.arrayDimensionsSize = 2;
	UA_NodeId myArrayNodeId = UA_NODEID_STRING(1, "双精度数组");
	UA_QualifiedName myArrayName = UA_QUALIFIEDNAME(1, "双精度数组");
	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
	UA_Server_addVariableNode(
		server, 
		myArrayNodeId, 
		parentNodeId,
		parentReferenceNodeId, 
		myArrayName,
		UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
		attr, 
		NULL, 
		NULL);
}

UaExpert查看(添加节点时使用的是中文,不知道有没有问题。尽量不要使用中文。)
在这里插入图片描述

修改节点的值

代码

#include <open62541.h>
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>


void *consoleThread(UA_Server *server);
static UA_NodeId addVariable(UA_Server *server,const UA_Int32 nsIndex, char *identifier,const UA_Int32 data);
static void writeVariable(UA_Server *server,const UA_NodeId nodeId,const UA_Int32 value);

void *consoleThread(UA_Server *server);

static volatile UA_Boolean running = true;
static void stopHandler(int sig) {
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
	running = false;
}
int main(void) {
	signal(SIGINT, stopHandler);
	signal(SIGTERM, stopHandler);
	UA_Server *server = UA_Server_new();
	UA_ServerConfig_setDefault(UA_Server_getConfig(server));

	int ret = 0;
    pthread_t id1;//声明线程ID
    ret = pthread_create(&id1 , NULL ,  (void *)consoleThread, (void *)server); //创建并执行线程id1
    if(ret == -1){
            printf("Create console thread error!\n");
            return 1;
    }
	UA_StatusCode retval = UA_Server_run(server, &running);
	UA_Server_delete(server);
	return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}



void showMenu(void){
	printf("\n");
	printf("*********(0)菜单**********************************\n");
	printf("*********(1)添加整数节点,默认值:0 **************\n");
	printf("*********(2)修改整数节点的值 *********************\n");
	printf("*********(3)退出 *********************************\n");
	printf("\n");
}



void *consoleThread(UA_Server *server)
{
	showMenu();
	while(running){
		int nsIndex,data;
		char identifier[128] = {0};
		int input =0;
		printf("输入你的选择:");
		scanf("%d",&input);
		switch(input){
			case 0:
				showMenu();
			break;
			case 1:
				printf("输入新增节点信息(如:1 No.1_Value_Opening 31):");
				scanf("%d%s%d",&nsIndex,identifier,&data);
				addVariable(server,nsIndex,identifier,data);
			break;
			case 2:
				printf("输入修改节点信息(如:1 No.1_Value_Opening 31):");
				scanf("%d%s%d",&nsIndex,identifier,&data);
				UA_NodeId nodeId = UA_NODEID_STRING(nsIndex,identifier);
				writeVariable(server,nodeId,data);
			break;
			case 3:
				running = false ;
			break;
		}
	}
}
 
static UA_NodeId addVariable(UA_Server *server,const UA_Int32 nsIndex, char *identifier,UA_Int32 data) {
	/* 定义整数变量节点的属性 */
	UA_VariableAttributes attr = UA_VariableAttributes_default;
	UA_Variant_setScalar(&attr.value, &data, &UA_TYPES[UA_TYPES_INT32]);
	attr.description = UA_LOCALIZEDTEXT("zh-CN",identifier);
	attr.displayName = UA_LOCALIZEDTEXT("zh-CN",identifier);
	attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
	attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
	/* 将变量节点添加到信息模型中 */
	UA_NodeId myIntegerNodeId = UA_NODEID_STRING(nsIndex, identifier);
	UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(nsIndex, identifier);
	UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
	UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
	UA_StatusCode code =  UA_Server_addVariableNode(
		server, 
		myIntegerNodeId, 
		parentNodeId,
		parentReferenceNodeId, 
		myIntegerName,
		UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), 
		attr, 
		NULL, 
		NULL);
	printf("添加节点完成!%d\n",code);
	return myIntegerNodeId;
}

static void writeVariable(UA_Server *server,const UA_NodeId nodeId,UA_Int32 value) {
	UA_Variant myVar;
	UA_Variant_init(&myVar);
	UA_Variant_setScalar(&myVar, &value, &UA_TYPES[UA_TYPES_INT32]);
	UA_StatusCode code =  UA_Server_writeValue(server, nodeId, myVar);
	printf("已修改节点的值,code = %d ,value = %d\n",code,value);
}

编译选项 -lpthread :因为使用线程,引用了 pthread.h,指定库文件位置。
下面截图中的修改节点值的提示信息是错误的,代码已更改,截图未更改。

gcc DemoServer.c open62541.c -o ds01 -I../opcua_c -lpthread

在这里插入图片描述
Ua_Expert 显示内容
在这里插入图片描述
暂时写到这吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值