3

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;
}
Etienne
  • 16,249
  • 3
  • 26
  • 31
Lucas Santos
  • 597
  • 6
  • 18

2 Answers2

4

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.

Stefan Profanter
  • 6,458
  • 6
  • 41
  • 73
  • Thank you so much @Stefan Profanter. This was exactly what I wanted to do and yes, your guess was right about where my code was based. I still have one more question? In my case I wait for the task in another thread to be done before continue with the execution of the program. Because I need these data first before do other requests to search more data. Is that ok for a server? I know if was a GUI application I would block if I wait for the thread but what about in this case? – Lucas Santos Mar 16 '19 at 03:02
  • 1
    In general you can block (or better say not call `UA_Server_run_iterate`) as long as you want. The server itself can handle that quite well. The only issue you will have is that the server also does not respond to network messages, e.g., if a client tries to connect. Or also if a client has an active subscription, this will not be handled as long as you do not call _iterate again. It is recommended to call this periodically. – Stefan Profanter Mar 18 '19 at 13:56
  • Thank you for the detail explanation @Stefan Profanter – Lucas Santos Mar 18 '19 at 19:50
0

There might be a solution but it has to be triggererd by the OPC UA Client.

The OPC UA Specification defines some Services to allow a client adding/deleting Nodes or References (AddNodes, AddRefererences, DeleteNodes, DeleteReferences)

Both your OPC UA Client and Server need to support those Services.

Camille G.
  • 3,058
  • 1
  • 25
  • 41