OPC-UA open62541 sdk Динамическое добавление узлов переменных после запуска сервера

Читая документацию и примеры OPC-UA Foundation и OPC-UA open62541 sdk, узлы переменных всегда добавляются перед оператором запуска сервера. Можно ли добавить их после запуска сервера? Если я изменю порядок операторов, это не сработает.

Подумайте вместе со мной о следующей ситуации: мне нужно выполнить несколько HTTP-запросов, как только мы начнем асинхронно запускать приложение / программное обеспечение (не сервер). Затем запускается сервер, после того как мой http-запрос выполнен, я добавил узлы переменных на основе информации, возвращаемой из Интернета.

Я добавил несколько комментариев к коду, чтобы пояснить, что я пытаюсь сделать.

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;
}

person Lucas Santos    schedule 14.03.2019    source источник


Ответы (2)


Да, можно использовать UA_Server_addVariableNode, поскольку вы уже используете его (возможно) в addVariable(). Я предполагаю, что ваш код основан на https://github.com/open62541/open62541/blob/master/examples/tutorial_server_variable.c

Простое изменение порядка кода не работает, так как

UA_StatusCode retval = UA_Server_run(server, &running);

блокирует.

Вам нужно изменить это, чтобы использовать итерационный подход:

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);

Обратите внимание, что open62541 в настоящее время не поддерживает многопоточность. Если вы добавляете переменные в другой поток, вам необходимо убедиться, что вы блокируете доступ к объекту server.

Приведенный выше пример основан на: https://github.com/open62541/open62541/blob/master/examples/server_mainloop.c

Другой подход - просто запустить другой поток, который обрабатывает ваши асинхронные запросы, а затем вызывает UA_Server_addVariableNode в отдельном потоке. Тем не менее убедитесь, что вы используете мьютексы.

person Stefan Profanter    schedule 15.03.2019
comment
Большое спасибо, @Stefan Profanter. Это было именно то, что я хотел сделать, и да, ваше предположение было правильным относительно того, где был основан мой код. У меня есть еще один вопрос? В моем случае я жду выполнения задачи в другом потоке, прежде чем продолжить выполнение программы. Потому что мне нужны эти данные, прежде чем выполнять другие запросы для поиска дополнительных данных. Это нормально для сервера? Я знаю, что если бы это было приложение с графическим интерфейсом, я бы заблокировал его, если бы дождался потока, но как насчет этого случая? - person Lucas Santos; 16.03.2019
comment
В общем, вы можете заблокировать (или, лучше сказать, не звонить UA_Server_run_iterate) столько, сколько захотите. Сам сервер с этим справляется достаточно хорошо. Единственная проблема, с которой вы столкнетесь, заключается в том, что сервер также не отвечает на сетевые сообщения, например, если клиент пытается подключиться. Или также, если у клиента есть активная подписка, это не будет обрабатываться, пока вы не вызовете _iterate снова. Рекомендуется звонить сюда периодически. - person Stefan Profanter; 18.03.2019
comment
Спасибо за подробное объяснение @Stefan Profanter - person Lucas Santos; 18.03.2019

Решение может быть, но оно должно запускаться клиентом OPC UA.

Спецификация OPC UA определяет некоторые службы, позволяющие клиенту добавлять / удалять узлы или ссылки (AddNodes, AddRefererences, DeleteNodes, DeleteReferences)

И клиент, и сервер OPC UA должны поддерживать эти службы.

person Camille G.    schedule 15.03.2019