open62541-server编程
Posted retry
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了open62541-server编程相关的知识,希望对你有一定的参考价值。
open62541--Server
1、服务构建
#include <signal.h>
#include "open62541.h"
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);
//server->config进行缺省化配置。(部分参数按照系统定义配置)
UA_ServerConfig *config = UA_ServerConfig_new_default();
/*
* 缺省配置后也可进行自定义修改。
config->customHostname.data = "192.168.0.108";
config->customHostname.length = 14;
*/
UA_Server *server = UA_Server_new(config);
UA_StatusCode retval = UA_Server_run(server, &running); //启动server
UA_Server_delete(server);
UA_ServerConfig_delete(config);
return (int)retval;
}
2、 变量类型(variable)节点的添加
static void addVariable(UA_Server *server)
{
/*变量节点的属性*/
UA_VariableAttributes attr = UA_VariableAttributes_default;
UA_Int32 myInteger = 1024;
//节点数据的设置attr.value
//P1:节点的数据属性 P2:要设置的数据 P3:数据的数据类型
UA_Variant_setScalar(&attr.value,&myInteger,&UA_TYPES[UA_TYPES_INT32]);
//节点在用户接口显示的名字(本地化)
attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
//节点在自身本地化描述
attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
//变量节点的访问权限:可读可写
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
/*定义1个节点:节点的命名空间 节点的ID标识符*/
UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1,"the.answer");
//节点对外的浏览名称(非本地化)
UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1,"the answer");
//定义1个节点
UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_OBJECTSFOLDER);
//定义1个节点
UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES);
/*************************************************************
UA_Server_addVariableNode(UA_Server *server, // 服务
const UA_NodeId requestedNewNodeId, //请求添加的节点
const UA_NodeId parentNodeId, //父节点
const UA_NodeId referenceTypeId, //父节点引用类型节点
const UA_QualifiedName browseName, //节点对外的浏览名称(非本地化)
const UA_NodeId typeDefinition, //引用节点
const UA_VariableAttributes attr,
void *nodeContext, UA_NodeId *outNewNodeId)
**************************************************************/
UA_Server_addVariableNode(server,myIntegerNodeId,parentNodeId,
parentReferenceNodeId,myIntegerName,
UA_NODEID_NUMERIC(0,UA_NS0ID_BASEDATAVARIABLETYPE),
attr,NULL,NULL);
}
2.1、变量节点数据的更新
2.1.1、手动更新
#include <signal.h>
#include "open62541.h"
static void
updateCurrentTime(UA_Server *server) {
UA_DateTime now = UA_DateTime_now();
UA_Variant value;
UA_Variant_setScalar(&value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
UA_Server_writeValue(server, currentNodeId, value);
}
static void
addCurrentTimeVariable(UA_Server *server) {
UA_DateTime now = 0;
UA_VariableAttributes attr = UA_VariableAttributes_default;
attr.displayName = UA_LOCALIZEDTEXT("en-US", "Current time");
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_Variant_setScalar(&attr.value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
UA_QualifiedName currentName = UA_QUALIFIEDNAME(1, "current-time");
UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
UA_NodeId variableTypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
UA_Server_addVariableNode(server, currentNodeId, parentNodeId,
parentReferenceNodeId, currentName,
variableTypeNodeId, attr, NULL, NULL);
//手动更新变量值
updateCurrentTime(server);
}
2.1.3、客户端访问时通过回调函数更新
//方法一:当值连续变化时,手动更新值将占用大量资源。值回调允许将变量值与外部进行同步,它们将回调附加到在每次读取之前和每次写入操作之后执行的变量。
static void
beforeReadTime(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeid, void *nodeContext,
const UA_NumericRange *range, const UA_DataValue *data) {
UA_DateTime now = UA_DateTime_now();
UA_Variant value;
UA_Variant_setScalar(&value, &now, &UA_TYPES[UA_TYPES_DATETIME]);
UA_NodeId currentNodeId = UA_NODEID_STRING(1, "current-time");
UA_Server_writeValue(server, currentNodeId, value);
}
//方法二:对于连续变化的数据,
static UA_StatusCode
readCurrentTime(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext,
UA_Boolean sourceTimeStamp, const UA_NumericRange *range,
UA_DataValue *dataValue) {
UA_DateTime now = UA_DateTime_now();
UA_Variant_setScalarCopy(&dataValue->value, &now,
&UA_TYPES[UA_TYPES_DATETIME]);
dataValue->hasValue = true;
return UA_STATUSCODE_GOOD;
}
2.1.4、订阅模式
对变量的当前值感兴趣的客户端不需要定期轮询变量。相反,他可以使用订阅机制来通知有关更改。
在Subscription中,客户端添加了所谓的MonitoredItems。DataChange MonitoredItem定义监视更改的节点属性(通常是值属性)。服务器在内部读取定义的时间间隔内的值并生成相应的通知。上面讨论的更新节点值的三种方式都可以与通知结合使用。这是因为通知使用标准的读取服务来查找值更改。
3、对象节点的添加
4、对象类型节点的使用
5、变量类型节点的使用
6、服务集的使用
6.1.1服务端方法服务集的集成
6.1.2客户端方法服务的调用
以上是关于open62541-server编程的主要内容,如果未能解决你的问题,请参考以下文章