diff --git a/CHANGELOG.rst b/CHANGELOG.rst index acdf41740..aad5ce90d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,10 @@ Release 3.6.3 ------------------------------------------------------------ +**Bugs**: + +* fix calling stop monitored item callback #132, by @flipback + **Documentation**: * fix apt-get command in installation guide #128, by @flipback diff --git a/src/OpcUaStackServer/ServiceSet/MonitorManager.cpp b/src/OpcUaStackServer/ServiceSet/MonitorManager.cpp index 9a69036d4..eac432ca1 100644 --- a/src/OpcUaStackServer/ServiceSet/MonitorManager.cpp +++ b/src/OpcUaStackServer/ServiceSet/MonitorManager.cpp @@ -1,5 +1,5 @@ /* - Copyright 2015-2018 Kai Huebl (kai@huebl-sgh.de) + Copyright 2015-2019 Kai Huebl (kai@huebl-sgh.de) Lizenziert gemäß Apache Licence Version 2.0 (die „Lizenz“); Nutzung dieser Datei nur in Übereinstimmung mit der Lizenz erlaubt. @@ -12,7 +12,7 @@ Informationen über die jeweiligen Bedingungen für Genehmigungen und Einschränkungen im Rahmen der Lizenz finden Sie in der Lizenz. - Autor: Kai Huebl (kai@huebl-sgh.de) + Autor: Kai Huebl (kai@huebl-sgh.de), Aleksey Timin (atimin@gmail.com) */ #include "OpcUaStackCore/Base/Log.h" @@ -582,8 +582,9 @@ namespace OpcUaStackServer } // check monitored item list + monitoredItemIds_.erase(it1); if (newMonitoredItemIds.size() > 0) { - monitoredItemIds_.insert(std::make_pair(baseNodeClass->nodeId().data(), monitoredItemIds)); + monitoredItemIds_.insert(std::make_pair(baseNodeClass->nodeId().data(), newMonitoredItemIds)); return; } diff --git a/src/OpcUaStackServer/ServiceSet/MonitorManager.h b/src/OpcUaStackServer/ServiceSet/MonitorManager.h index 194272a76..6708cb90e 100644 --- a/src/OpcUaStackServer/ServiceSet/MonitorManager.h +++ b/src/OpcUaStackServer/ServiceSet/MonitorManager.h @@ -1,5 +1,5 @@ /* - Copyright 2015-2018 Kai Huebl (kai@huebl-sgh.de) + Copyright 2015-2019 Kai Huebl (kai@huebl-sgh.de) Lizenziert gemäß Apache Licence Version 2.0 (die „Lizenz“); Nutzung dieser Datei nur in Übereinstimmung mit der Lizenz erlaubt. @@ -12,7 +12,7 @@ Informationen über die jeweiligen Bedingungen für Genehmigungen und Einschränkungen im Rahmen der Lizenz finden Sie in der Lizenz. - Autor: Kai Huebl (kai@huebl-sgh.de) + Autor: Kai Huebl (kai@huebl-sgh.de), Aleksey Timin (atimin@gmail.com) */ #ifndef __OpcUaStackServer_MonitorManager_h__ diff --git a/tst/OpcUaStackServer/ServiceSet/MonitorManager_t.cpp b/tst/OpcUaStackServer/ServiceSet/MonitorManager_t.cpp new file mode 100644 index 000000000..1ce448784 --- /dev/null +++ b/tst/OpcUaStackServer/ServiceSet/MonitorManager_t.cpp @@ -0,0 +1,169 @@ +#include "unittest.h" + +#include "OpcUaStackServer/ServiceSet/MonitorManager.h" +#include "OpcUaStackServer/AddressSpaceModel/VariableNodeClass.h" +#include "OpcUaStackCore/Application/ApplicationMonitoredItemStartContext.h" +#include "OpcUaStackCore/Application/ApplicationMonitoredItemStopContext.h" + +using namespace OpcUaStackServer; + + +struct F { + F() : mm() + , informationModel(constructSPtr()) + , ioThread(constructSPtr()) + , createMonitoredItemTransaction(constructSPtr()) + , startMonitoredItemCallCount(0) + , stopMonitoredItemCallCount(0) + { + + mm.informationModel(informationModel); + + ioThread = constructSPtr(); + ioThread->slotTimer(constructSPtr()); + mm.ioThread(ioThread.get()); + + auto nodeToMonitor = constructSPtr(); + OpcUaNodeId nodeToMonitorId(0, 0); + nodeToMonitor->setNodeId(nodeToMonitorId); + OpcUaDataValue value(0); + nodeToMonitor->setValue(value); + + auto sync = constructSPtr(); + auto startMonitoredItemCallback = Callback(boost::bind(&F::startMonitored, this, _1)); + auto stopMonitoredItemCallback = Callback(boost::bind(&F::stopMonitored, this, _1)); + sync->monitoredItemStartService().setCallback(startMonitoredItemCallback); + sync->monitoredItemStopService().setCallback(stopMonitoredItemCallback); + + nodeToMonitor->forwardNodeSync(sync); + + informationModel->insert(nodeToMonitor); + + auto monitoredItemCreateRequest = constructSPtr(); + + ReadValueId readValueId; + readValueId.nodeId(0, 0); + readValueId.attributeId(AttributeId_Value); + monitoredItemCreateRequest->itemToMonitor(readValueId); + + + auto itemsToCreate = constructSPtr(); + itemsToCreate->resize(1); + itemsToCreate->push_back(monitoredItemCreateRequest); + + createMonitoredItemTransaction->request()->itemsToCreate(itemsToCreate); + } + + void + startMonitored(ApplicationMonitoredItemStartContext* context) + { + startMonitoredItemCallCount++; + } + + void + stopMonitored(ApplicationMonitoredItemStopContext* context) + { + stopMonitoredItemCallCount++; + } + + ServiceTransactionDeleteMonitoredItems::SPtr makeDeleteMonitredItemTransaction(CreateMonitoredItemsResponse::SPtr response) { + MonitoredItemCreateResult::SPtr result; + response->results()->get(0, result); + + auto ids = constructSPtr(); + ids->resize(1); + ids->push_back(result->monitoredItemId()); + + auto deleteMonitoredItemTransaction = constructSPtr(); + deleteMonitoredItemTransaction->request()->monitoredItemIds(ids); + + return deleteMonitoredItemTransaction; + } + + ~F() { } + + MonitorManager mm; + InformationModel::SPtr informationModel; + IOThread::SPtr ioThread; + + ServiceTransactionCreateMonitoredItems::SPtr createMonitoredItemTransaction; + + size_t startMonitoredItemCallCount; + size_t stopMonitoredItemCallCount; + +}; + + +BOOST_FIXTURE_TEST_SUITE(MonitorManager_, F) + +BOOST_AUTO_TEST_CASE(MonitorManager_) +{ + std::cout << "MonitorManager_t" << std::endl; +} + +BOOST_AUTO_TEST_CASE(MonitorManager_CallStartMonitoredItemCallback) +{ + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + + MonitoredItemCreateResult::SPtr result; + createMonitoredItemTransaction->response()->results()->get(0, result); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, result->statusCode()); + BOOST_REQUIRE_EQUAL(1, startMonitoredItemCallCount); +} + +BOOST_AUTO_TEST_CASE(MonitorManager_CallStartMonitoredItemCallbackOnlyOnce) +{ + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + + MonitoredItemCreateResult::SPtr result; + createMonitoredItemTransaction->response()->results()->get(0, result); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, result->statusCode()); + BOOST_REQUIRE_EQUAL(1, startMonitoredItemCallCount); +} + +BOOST_AUTO_TEST_CASE(MonitorManager_CallStopMonitoredItemCallback) +{ + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + + auto deleteMonitoredItemTransaction = + makeDeleteMonitredItemTransaction(createMonitoredItemTransaction->response()); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(deleteMonitoredItemTransaction)); + + OpcUaStatusCode status; + deleteMonitoredItemTransaction->response()->results()->get(0, status); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, status); + BOOST_REQUIRE_EQUAL(1, stopMonitoredItemCallCount); +} + + +BOOST_AUTO_TEST_CASE(MonitorManager_CallStopMonitoredItemCallbackOnlyOnce) +{ + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + + auto deleteMonitoredItemTransaction1 = + makeDeleteMonitredItemTransaction(createMonitoredItemTransaction->response()); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(createMonitoredItemTransaction)); + + auto deleteMonitoredItemTransaction2 = + makeDeleteMonitredItemTransaction(createMonitoredItemTransaction->response()); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(deleteMonitoredItemTransaction1)); + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, mm.receive(deleteMonitoredItemTransaction2)); + + OpcUaStatusCode status; + deleteMonitoredItemTransaction2->response()->results()->get(0, status); + + BOOST_REQUIRE_EQUAL(OpcUaStatusCode::Success, status); + BOOST_REQUIRE_EQUAL(1, stopMonitoredItemCallCount); +} + + +BOOST_AUTO_TEST_SUITE_END() + +