从之前使用C语言编写OPCUA的服务器就可以看出,使用C语言编写的代码量是比较大的,之前是创建了一个Object类型的节点,并在节点下添加了许多变量和方法节点,但是想要创建一百个Object类型的节点怎么办?
一个一个写是比较不好使的,要是一两个可以,一百个就不怎么靠谱了。
这里官方文档推荐的是创建一个ObjectType,然后在大量实例化的操作,我并没有先使用这个,而是将我之前的服务器的创建Object节点的函数
manuallyDefinePump(server)
添加一个参数:
void manuallyDefinePump(UA_Server* server,int *id)
{
...
}
int main()
{
...
int id[10];
for(i...):
manuallyDefinePump(server,&id[i])
....
}
这样就可以进行大量快速的创建Object.
当然不是这样就可以了,之后要将这个函数进行修改通用化处理。
下面无论是添加变量节点和方法节点都需要将这个参数传递下去:
变量节点添加修改:倒数第二个修改为id
UA_Server_addVariableNode(server, actposNodeId, pumpId,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
UA_QUALIFIEDNAME(1, "pos"),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),actposAttr, id, NULL);
然后添加回调函数时使用给定的参数:
static void beforeReadActpos0(UA_Server* server,const UA_NodeId* sessionId, void * sessionContext,
const UA_NodeId* nodeid, void * nodeContext,const UA_NumericRange* range, const UA_DataValue * data) {
int id = *(int *)nodeContext;
......
}
这样便将一个自定义的参数nodeContext的内容取出来了,再进行大量创建回调函数便比较简单了。
方法节点添加修改
同样的添加id到倒第二个参数:
UA_Server_addMethodNode(server, UA_NODEID_STRING(1,"setpos"),
pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT), UA_QUALIFIEDNAME(1, "setpos"),
helloAttr, &McPower0MethodCallback,
1, &inputArgument, 1, &outputArgument, id, NULL);
然后回调函数修改:
static UA_StatusCode McPower0MethodCallback(UA_Server *server,
const UA_NodeId *sessionId, void *sessionHandle, const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, void *objectContext, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) {
int id = *(int *)methodContext;
.......
}
这样快速创建大量重复的结构化的节点集便没有任何问题。
另外
Open62541的这个独有的nodeContent有着一个独立获取自定义内容的函数,只需要添加节点ID即可。
void *nodeContext;
UA_Server_getNodeContext(server,currentNodeId,&nodeContext);
注意
1.该int型的id不要使用局部变量,应该使用全局变量,因为你在回调函数实际上获取的是你在添加该节点时的指针,指向了实际的变量,并没有进行值的拷贝,要是局部变量会出现错误。