#c #opc-ua #open62541
#c #opc-ua #open62541
Вопрос:
Читая документацию и примеры 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, amp;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, amp;running);
UA_Server_delete(server);
UA_ServerConfig_delete(config);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
Ответ №1:
Да, это возможно с помощью UA_Server_addVariableNode
, поскольку вы уже используете его (вероятно) в addVariable()
. Я предполагаю, что ваш код основан на https://github.com/open62541/open62541/blob/master/examples/tutorial_server_variable.c
Простое изменение порядка кода не работает, поскольку
UA_StatusCode retval = UA_Server_run(server, amp;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, amp;tv);
}
retval = UA_Server_run_shutdown(server);
Обратите внимание, что open62541 в настоящее время не поддерживает многопоточность. Если вы добавляете переменные в другом потоке, вам нужно убедиться, что вы мьютексируете доступ к server
объекту.
Приведенный выше пример основан на:https://github.com/open62541/open62541/blob/master/examples/server_mainloop.c
Другой подход заключается в том, чтобы просто запустить другой поток, который обрабатывает ваши асинхронные запросы, а затем вызывает UA_Server_addVariableNode
в отдельном потоке. По-прежнему убедитесь, что вы используете мьютексы.
Комментарии:
1. Большое вам спасибо @Stefan Profanter. Это было именно то, что я хотел сделать, и да, ваше предположение было правильным относительно того, на чем основан мой код. У меня все еще есть еще один вопрос? В моем случае я жду выполнения задачи в другом потоке, прежде чем продолжить выполнение программы. Потому что сначала мне нужны эти данные, прежде чем выполнять другие запросы для поиска дополнительных данных. Это нормально для сервера? Я знаю, что если бы было приложение с графическим интерфейсом, я бы заблокировал, если бы я ждал потока, но что в этом случае?
2. В общем, вы можете блокировать (или, лучше сказать, не вызывать
UA_Server_run_iterate
) столько, сколько захотите. Сам сервер может справиться с этим довольно хорошо. Единственная проблема, с которой вы столкнетесь, заключается в том, что сервер также не отвечает на сетевые сообщения, например, если клиент пытается подключиться. Или также, если у клиента активная подписка, это не будет обработано до тех пор, пока вы снова не вызовете _iterate. Рекомендуется периодически вызывать это.3. Спасибо за подробное объяснение @Stefan Profanter
Ответ №2:
Возможно, есть решение, но оно должно быть запущено клиентом OPC UA.
Спецификация OPC UA определяет некоторые службы, позволяющие клиенту добавлять / удалять узлы или ссылки ( AddNodes
, AddRefererences
, DeleteNodes
, DeleteReferences
)
Как ваш клиент OPC UA, так и сервер должны поддерживать эти службы.