diff options
Diffstat (limited to 'src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp')
-rw-r--r-- | src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp | 247 |
1 files changed, 140 insertions, 107 deletions
diff --git a/src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp b/src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp index 487b3ed..f89ae57 100644 --- a/src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp +++ b/src/plugins/opcua/freeopcua/qfreeopcuasubscription.cpp @@ -35,13 +35,9 @@ ****************************************************************************/ #include "qfreeopcuaclient.h" -#include "qfreeopcuanode.h" #include "qfreeopcuasubscription.h" #include "qfreeopcuavalueconverter.h" -#include <QtOpcUa/qopcuamonitoredvalue.h> -#include <QtOpcUa/qopcuasubscription.h> -#include <private/qopcuamonitoredevent_p.h> -#include <private/qopcuamonitoredvalue_p.h> +#include "qfreeopcuaworker.h" #include <private/qopcuanode_p.h> #include <QtCore/qloggingcategory.h> @@ -50,157 +46,194 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(QT_OPCUA_PLUGINS_FREEOPCUA) -QFreeOpcUaSubscription::QFreeOpcUaSubscription(OpcUa::UaClient *client, quint32 interval) - : m_client(client) +QFreeOpcUaSubscription::QFreeOpcUaSubscription(QFreeOpcUaWorker *backend, const QOpcUaMonitoringParameters &settings) + : m_interval(settings.publishingInterval()) + , m_shared(settings.shared()) + , m_backend(backend) { - Q_ASSERT(m_client); + Q_ASSERT(m_backend); +} + +QFreeOpcUaSubscription::~QFreeOpcUaSubscription() +{ + removeOnServer(); +} + +quint32 QFreeOpcUaSubscription::createOnServer() +{ + if (m_subscription) + return 0; try { - m_subscription = m_client->CreateSubscription(interval, *this); + m_subscription = m_backend->CreateSubscription(m_interval, *this); + m_interval = m_subscription->GetData().RevisedPublishingInterval; } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "CreateOnServer caught: %s", ex.what()); + return 0; } + return m_subscription->GetId(); } -QFreeOpcUaSubscription::~QFreeOpcUaSubscription() +bool QFreeOpcUaSubscription::removeOnServer() { + bool success = false; try { if (m_subscription) { - for (int32_t handle : m_dataChangeHandles.keys()) - m_subscription->UnSubscribe(handle); - - for (int32_t handle : m_eventHandles.keys()) - m_subscription->UnSubscribe(handle); - m_subscription->Delete(); + m_subscription.reset(); + success = true; } } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "RemoveOnServer caught: %s", ex.what()); } + + qDeleteAll(m_itemIdToItemMapping); + + m_itemIdToItemMapping.clear(); + m_handleToItemMapping.clear(); + + return success; } -void QFreeOpcUaSubscription::DataChange(quint32 handle, const OpcUa::Node &node, - const OpcUa::Variant &val, - OpcUa::AttributeId attr) +void QFreeOpcUaSubscription::modifyMonitoring(uintptr_t handle, QOpcUaNode::NodeAttribute attr, QOpcUaMonitoringParameters::Parameter item, QVariant value) { - OPCUA_UNUSED(node); - OPCUA_UNUSED(attr); - - auto it = m_dataChangeHandles.find(handle); - if (it == m_dataChangeHandles.end()) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Received event for unknown handle: %ul", handle); + Q_UNUSED(item); + Q_UNUSED(value); + + if (!getItemForAttribute(handle, attr)) { + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Could not modify parameter for %lu, there are no monitored items", handle); + QOpcUaMonitoringParameters p; + p.setStatusCode(QOpcUa::UaStatusCode::BadAttributeIdInvalid); + emit m_backend->monitoringStatusChanged(handle, attr, item, p); return; } - try { - (*it)->d_func()->triggerValueChanged(QFreeOpcUaValueConverter::toQVariant(val)); - } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); - } + QOpcUaMonitoringParameters s; + s.setStatusCode(QOpcUa::UaStatusCode::BadNotImplemented); + emit m_backend->monitoringEnableDisable(handle, attr, true, s); } -QOpcUaMonitoredValue *QFreeOpcUaSubscription::addValue(QOpcUaNode *node) +bool QFreeOpcUaSubscription::addAttributeMonitoredItem(uintptr_t handle, QOpcUaNode::NodeAttribute attr, const OpcUa::Node &node, QOpcUaMonitoringParameters settings) { - if (!m_subscription) - return nullptr; + Q_UNUSED(settings); // Setting these options is not yet supported - try { - // Only add a monitored item if the node has a value attribute - QFreeOpcUaNode *nnode = static_cast<QFreeOpcUaNode *>(node->d_func()->m_impl.data()); - if (nnode->m_node.GetAttribute(OpcUa::AttributeId::Value).Status != OpcUa::StatusCode::Good) - return nullptr; + quint32 monitoredItemId; + try { if (m_subscription) { - uint32_t handle = m_subscription->SubscribeDataChange(m_client->GetNode(node->nodeId().toStdString())); - QOpcUaMonitoredValue *monitoredValue = new QOpcUaMonitoredValue(node, m_qsubscription); - m_dataChangeHandles[handle] = monitoredValue; - return monitoredValue; + monitoredItemId = m_subscription->SubscribeDataChange(node, QFreeOpcUaValueConverter::toUaAttributeId(attr)); + } + else { + QOpcUaMonitoringParameters s; + s.setStatusCode(QOpcUa::UaStatusCode::BadSubscriptionIdInvalid); + emit m_backend->monitoringEnableDisable(handle, attr, true, s); + return false; } } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "addAttributeMonitoredItem caught: %s", ex.what()); + QOpcUaMonitoringParameters s; + s.setStatusCode(QFreeOpcUaValueConverter::exceptionToStatusCode(ex)); + emit m_backend->monitoringEnableDisable(handle, attr, true, s); + return false; } - return nullptr; + + MonitoredItem *temp = new MonitoredItem(handle, attr, monitoredItemId); + m_handleToItemMapping[handle][attr] = temp; + m_itemIdToItemMapping[monitoredItemId] = temp; + + QOpcUaMonitoringParameters s; + s.setSubscriptionId(m_subscription->GetId()); + s.setPublishingInterval(m_interval); + s.setMaxKeepAliveCount(m_subscription->GetData().RevisedMaxKeepAliveCount); + s.setLifetimeCount(m_subscription->GetData().RevisedLifetimeCount); + s.setStatusCode(QOpcUa::UaStatusCode::Good); + s.setSamplingInterval(m_interval); + emit m_backend->monitoringEnableDisable(handle, attr, true, s); + + return true; } -void QFreeOpcUaSubscription::Event(quint32 handle, const OpcUa::Event &event) +bool QFreeOpcUaSubscription::removeAttributeMonitoredItem(uintptr_t handle, QOpcUaNode::NodeAttribute attr) { - auto it = m_eventHandles.find(handle); - if (it == m_eventHandles.end()) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "Received event for unknown handle:" << handle; - return; + QScopedPointer<MonitoredItem> item(getItemForAttribute(handle, attr)); + + if (!item) { + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "There is no monitored item for this attribute"); + QOpcUaMonitoringParameters s; + s.setStatusCode(QOpcUa::UaStatusCode::BadMonitoredItemIdInvalid); + emit m_backend->monitoringEnableDisable(handle, attr, false, s); + return false; } - try { - QVector<QVariant> val; - val.reserve(3); - - val.push_back(QVariant(QString::fromStdString(event.Message.Text))); - val.push_back(QVariant(QString::fromStdString(event.SourceName))); - val.push_back(QVariant(event.Severity)); + QOpcUaMonitoringParameters s; - QOpcUaMonitoredEvent *me = *it; - me->d_func()->triggerNewEvent(val); + try { + m_subscription->UnSubscribe(item->monitoredItemId); + s.setStatusCode(QOpcUa::UaStatusCode::Good); } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); + qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "removeAttributeMonitoredItem caught: %s", ex.what()); + s.setStatusCode(QFreeOpcUaValueConverter::exceptionToStatusCode(ex)); } + + m_itemIdToItemMapping.remove(item->monitoredItemId); + auto it = m_handleToItemMapping.find(handle); + it->remove(attr); + if (it->empty()) + m_handleToItemMapping.erase(it); + + emit m_backend->monitoringEnableDisable(handle, attr, false, s); + + return true; } -QOpcUaMonitoredEvent *QFreeOpcUaSubscription::addEvent(QOpcUaNode *node) +double QFreeOpcUaSubscription::interval() const { - // Note: Callback is not called due to some error in the event implementation in freeopcua - if (!m_subscription) - return nullptr; + return m_interval; +} - try { - QFreeOpcUaNode *nnode = static_cast<QFreeOpcUaNode *>(node->d_func()->m_impl.data()); - if (nnode->m_node.GetAttribute(OpcUa::AttributeId::EventNotifier).Status != OpcUa::StatusCode::Good) - return nullptr; +QOpcUaMonitoringParameters::SubscriptionType QFreeOpcUaSubscription::shared() const +{ + return m_shared; +} - OpcUa::Node serverNode = m_client->GetNode(OpcUa::ObjectId::Server); - OpcUa::Node typeNode = m_client->GetNode(node->nodeId().toStdString()); +quint32 QFreeOpcUaSubscription::subscriptionId() const +{ + if (m_subscription) + return m_subscription->GetId(); + else + return 0; +} - uint32_t handle = m_subscription->SubscribeEvents(serverNode, typeNode); - QOpcUaMonitoredEvent *monitoredEvent = new QOpcUaMonitoredEvent(node, m_qsubscription); - m_eventHandles[handle] = monitoredEvent; - return monitoredEvent; - } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); - } - return nullptr; +int QFreeOpcUaSubscription::monitoredItemsCount() const +{ + return m_itemIdToItemMapping.size(); } -void QFreeOpcUaSubscription::removeEvent(QOpcUaMonitoredEvent *event) +QFreeOpcUaSubscription::MonitoredItem *QFreeOpcUaSubscription::getItemForAttribute(uintptr_t handle, QOpcUaNode::NodeAttribute attr) { - try { - auto it = m_eventHandles.begin(); - while (it != m_eventHandles.end()) { - if (it.value() == event) { - m_subscription->UnSubscribe(it.key()); - m_eventHandles.erase(it); - break; - } - ++it; - } - } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); - } + auto nodeEntry = m_handleToItemMapping.find(handle); + + if (nodeEntry == m_handleToItemMapping.end()) + return nullptr; + + auto item = nodeEntry->find(attr); + if (item == nodeEntry->end()) + return nullptr; + + return item.value(); } -void QFreeOpcUaSubscription::removeValue(QOpcUaMonitoredValue *value) +void QFreeOpcUaSubscription::DataChange(quint32 handle, const OpcUa::Node &node, + const OpcUa::Variant &val, + OpcUa::AttributeId attr) { - try { - auto it = m_dataChangeHandles.begin(); - while (it != m_dataChangeHandles.end()) { - if (it.value() == value) { - m_subscription->UnSubscribe(it.key()); - m_dataChangeHandles.erase(it); - break; - } - ++it; - } - } catch (const std::exception &ex) { - qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA, "Caught: %s", ex.what()); - } + OPCUA_UNUSED(node); + OPCUA_UNUSED(attr); + + auto item = m_itemIdToItemMapping.find(handle); + if (item == m_itemIdToItemMapping.end()) + return; + emit m_backend->attributeUpdated(item.value()->handle, item.value()->attr, QFreeOpcUaValueConverter::toQVariant(val)); } QT_END_NAMESPACE |