Open62541: Массовая подписка с UA_Client_MonitoredItems_createDataChanges не запускает обратные вызовы для изменения данC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Open62541: Массовая подписка с UA_Client_MonitoredItems_createDataChanges не запускает обратные вызовы для изменения дан

Сообщение Anonymous »

Я реализую клиент OPC UA с использованием open62541 (v1.x), и столкнулся с проблемой при подписке на множество тегов в массовом режиме.
При использовании API одного элемента все работает правильно, но когда я переключаюсь на массовое создание с помощью UA_Client_MonitoredItems_createDataChanges(), отслеживаемые элементы успешно создаются, но обратные вызовы для изменения данных никогда не запускаются.
Ниже приведен упрощенный пример. версия двух моих реализаций.
✔ Рабочая реализация (создание одного отслеживаемого элемента)
Эта версия подписывается на каждый тег индивидуально с помощью UA_Client_MonitoredItems_createDataChange():

Код: Выделить всё

UA_MonitoredItemCreateResult monResponse =
UA_Client_MonitoredItems_createDataChange(
client,
subscriptionId,
UA_TIMESTAMPSTORETURN_BOTH,
monRequest,
monContext,
handler_DataChange,
nullptr);
Это работает отлично:
  • Все отслеживаемые элементы создаются
  • Обратные вызовы вызываются правильно
  • Значения поступают нормально
❌ НЕ работает: массовое создание отслеживаемых элементов
Когда я переключаюсь на пакетный API:

Код: Выделить всё

UA_CreateMonitoredItemsResponse resp =
UA_Client_MonitoredItems_createDataChanges(
client,
req,
ctxRaw.data(),
cbRaw.data(),
nullptr);
Происходит следующее:
✔ Отслеживаемые элементы создаются успешно (сервер возвращает GOOD)
✔ Я получаю правильный MonitoredItemId для всех элементов
❌ Но ни один из назначенных обратных вызовов никогда не запускается
Вот соответствующая часть массовой реализации:

Код: Выделить всё

UA_CreateMonitoredItemsRequest req;
UA_CreateMonitoredItemsRequest_init(&req);
req.subscriptionId = subscriptionId;
req.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH;
req.itemsToCreateSize = tags.size();
req.itemsToCreate = (UA_MonitoredItemCreateRequest*)UA_Array_new(
tags.size(),
&UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST]);

// persistent storage (to keep contexts alive)
auto& ctxList = subscriptionContexts[subscriptionId];
auto& cbList  = subscriptionCallbacks[subscriptionId];

for (size_t i = 0; i < tags.size(); i++) {
UA_MonitoredItemCreateRequest_init(&req.itemsToCreate[i]);
UA_NodeId nodeId = parseNodeIdFromAddress(tags[i]->address, logger);
UA_NodeId_copy(&nodeId, &req.itemsToCreate[i].itemToMonitor.nodeId);

req.itemsToCreate[i].itemToMonitor.attributeId = UA_ATTRIBUTEID_VALUE;

// Store context in a stable buffer
auto ctx = std::make_unique();
ctx->deviceId = device->uniqueId;
ctx->tag      = tags[i];
ctxList.push_back(std::move(ctx));

// Store callback
cbList.push_back(handler_DataChange);

UA_NodeId_clear(&nodeId);
}
// prepare raw pointer arrays
std::vector ctxRaw;
for (auto& c : ctxList) ctxRaw.push_back(c.get());

std::vector cbRaw;
for (auto& cb : cbList) cbRaw.push_back(cb);

UA_CreateMonitoredItemsResponse resp =
UA_Client_MonitoredItems_createDataChanges(
client,
req,
ctxRaw.data(),
cbRaw.data(),
nullptr);
Наблюдения:
  • resp.responseHeader.serviceResult == UA_STATUSCODE_GOOD
  • Все resp.results.statusCode == UA_STATUSCODE_GOOD
  • В журнале показаны все отслеживаемые элементы считаются успешно подписанными
  • Но никакие изменения значений никогда не доставляются в мой обратный вызов


Что я уже проверял
  • Обратные вызовы хранятся в постоянном std::vector → они НЕ выходят за рамки
  • Объекты контекста принадлежат unique_ptr и остаются активными на протяжении всей подписки.
  • Та же функция обратного вызова отлично работает в режиме одного элемента.
  • Сервер публикует значения нормально.
  • Параметры подписки (samplingInterval,queueSize и т. д.) верны
  • Клиент получает ответы на публикацию, но не содержит уведомлений


Мой вопрос?
Почему UA_Client_MonitoredItems_createDataChanges() успешно создает отслеживаемые элементы, но никогда не доставляет обратные вызовы для изменения данных, даже если тот же обратный вызов работает при создании одного элемента?
Есть ли что-то особенное в том, как должны быть структурированы массивы обратных вызовов/контекста для этого API?
Нужно ли мне хранить их в определенном формате или порядке?
Или существует ли известное ограничение/ошибка в open62541, касающаяся массового создания отслеживаемых элементов?>

Подробнее здесь: https://stackoverflow.com/questions/798 ... hanges-doe
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»