c++opc-uaopen62541

OPC-UA open62541 sdk Add Variable nodes dynamically after run the server


Reading the documentation and examples of the OPC-UA foundation and OPC-UA open62541 sdk, the variables nodes are always added before the statement to start run the server. Is it possible to add them after the server has been started? If I change the order of the statements that doesn't work.

Think with me the following situation: I need to do some http requests as soon we start running the application/software (not the server) asynchronously. Then the server starts, after my http request is done, I added variable nodes based on the information returned from the web.

I put some comments on the code to clarify what I am trying to do.

int main() {
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);

    UA_ServerConfig *config = UA_ServerConfig_new_default();
    UA_Server *server = UA_Server_new(config);

    // If I put this statement after the other statement:
    // UA_StatusCode retval = UA_Server_run(server, &running);
    // The variables are not added.
    addVariable(server);

    // I would like to add some variables nodes after this statement, 
    // for example, like I said I request some information online 
    // and I will add the nodes after return from this request asynchronous.
    UA_StatusCode retval = UA_Server_run(server, &running);
    UA_Server_delete(server);
    UA_ServerConfig_delete(config);
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

Solution

  • Yes, it is possible using the UA_Server_addVariableNode as you are already using it (probably) in addVariable(). I guess your code is based on https://github.com/open62541/open62541/blob/master/examples/tutorial_server_variable.c

    Simply reordering the code does not work since

    UA_StatusCode retval = UA_Server_run(server, &running);
    

    is blocking.

    You need to change this to use the iterate approach:

    UA_StatusCode retval = UA_Server_run_startup(server);
    if(retval != UA_STATUSCODE_GOOD)
       return 1;
    
    while(running) {
        UA_UInt16 timeout = UA_Server_run_iterate(server, waitInternal);
    
        // HERE you can add any node to the server you like.
        // e.g. call addVariable2().
        // Make sure that you only call it once in the loop.
    
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = timeout * 1000;
        select(0, NULL, NULL, NULL, &tv);
    }
    retval = UA_Server_run_shutdown(server);
    

    Note that open62541 currently does not support multithreading. If you are adding variables in another thread you need to make sure that you are mutexing the access to the server object.

    The example above is based on: https://github.com/open62541/open62541/blob/master/examples/server_mainloop.c

    Another approach is to just start another thread which handles your async requests and then calls UA_Server_addVariableNode in the separated thread. Still make sure that you are using mutexes.