// Set the publishing mode // ============================================================================================= Status Subscription::setPublishingMode( bool publishingEnabled, const ServiceSettings& serviceSettings) { OpcUa_Boolean uaPublishingEnabled = publishingEnabled ? OpcUa_True : OpcUa_False; UaClientSdk::ServiceSettings uaServiceSettings; serviceSettings.toSdk(uaServiceSettings); UaStatus uaStatus = uaSubscription_->setPublishingMode(uaServiceSettings, uaPublishingEnabled); Status ret; ret.fromSdk(uaStatus.statusCode(), "Couldn't set the publishing mode"); return ret; }
Status Subscription::createSubscription() { logger_->debug("Creating the subscription to the server"); Status ret; UaClientSdk::ServiceSettings serviceSettings; UaClientSdk::SubscriptionSettings subscriptionSettings; subscriptionSettings = toSdk(subscriptionSettings_); UaStatus uaStatus = uaSession_->createSubscription( serviceSettings, uaSubscriptionCallback_, clientSubscriptionHandle_, subscriptionSettings, OpcUa_True, &uaSubscription_); ret.fromSdk(uaStatus.statusCode(), "Could not create the subscription to the server"); if (ret.isGood()) { subscriptionState_ = uafc::subscriptionstates::Created; logger_->debug("The subscription has been successfully created to the server"); } else { subscriptionState_ = uafc::subscriptionstates::Deleted; ret.addDiagnostic("Subscription creation to the server failed"); logger_->error(ret); } return ret; }
Status Subscription::deleteSubscription() { Status ret; if (uaSession_->isConnected()) { if (isCreated()) { logger_->debug("Now deleting subscription %d and thereby deleting all monitored items", clientSubscriptionHandle_); UaClientSdk::ServiceSettings serviceSettings; UaStatus uaStatus = uaSession_->deleteSubscription(serviceSettings, &uaSubscription_); ret.fromSdk(uaStatus.statusCode(), "Could not delete the subscription"); } else { logger_->debug("No need to delete subscription %d on the server side, as it was " \ "already deleted", clientSubscriptionHandle_); ret.setGood(); } } else { ret.setStatus(statuscodes::ConnectionError, "Could not delete the subscription"); } // now update the persistent requests MonitoredItemsMap::iterator it = monitoredItemsMap_.begin(); while (it != monitoredItemsMap_.end()) { // remove the notification buffer according to the kind if (it->second.settings.kind() == MonitoredItemSettings::Data) { database_->createMonitoredDataRequestStore.updateTargetStatus( it->second.requestHandle, it->second.targetRank, Status(statuscodes::SubscriptionError, "The subscription was deleted")); } else { database_->createMonitoredEventsRequestStore.updateTargetStatus( it->second.requestHandle, it->second.targetRank, Status(statuscodes::SubscriptionError, "The subscription was deleted")); } // remove the monitoredItemsMap_ entry monitoredItemsMap_.erase(it++); } // log the result if (ret.isGood()) { logger_->debug("The subscription has been deleted successfully"); setSubscriptionState(uafc::subscriptionstates::Deleted); } else { logger_->error(ret); } return ret; }
// Invoke the service synchronously // ============================================================================================= Status HistoryReadRawModifiedInvocation::invokeSyncSdkService(UaClientSdk::UaSession* uaSession) { Status ret; UaStatus uaStatus = uaSession->historyReadRawModified( uaServiceSettings_, uaContext_, uaNodesToRead_, uaResults_); ret.fromSdk(uaStatus.statusCode(), "Synchronous HistoryRead invocation failed"); uint32_t autoReadMore = 0; uint32_t maxAutoReadMore = this->serviceSettings().maxAutoReadMore; // do we still have to automatically invoke another read, or are we finished? bool finished = (maxAutoReadMore == 0); // if we're not finished already, and the initial request was successful, we // may need to invoke the history read service again while ((!finished) && ret.isGood()) { UaHistoryReadValueIds uaNextNodesToRead; UaClientSdk::HistoryReadDataResults uaNextResults; vector<uint32_t> ranks; // the rank numbers of the original request // loop through the results and append "unfinished" read results to the // variables for the next read call, as defined above for (uint32_t i = 0; i < uaResults_.length(); i++) { if ( uaResults_[i].m_continuationPoint.length() > 0 && uaResults_[i].m_status.isGood()) { // get the rank number for the next call uint32_t current = uaNextNodesToRead.length(); // increase the size of the continuation points for the next BrowseNext call uaNextNodesToRead.resize(current + 1); // store the rank number of the current result ranks.push_back(i); uaResults_[i].m_continuationPoint.copyTo( &uaNextNodesToRead[current].ContinuationPoint); UaNodeId(uaNodesToRead_[i].NodeId).copyTo( &uaNextNodesToRead[current].NodeId); if (!UaQualifiedName(uaNodesToRead_[i].DataEncoding).isNull()) UaQualifiedName(uaNodesToRead_[i].DataEncoding).copyTo( &uaNextNodesToRead[current].DataEncoding); if (!UaString(&uaNodesToRead_[i].IndexRange).isNull()) UaString(&uaNodesToRead_[i].IndexRange).copyTo( &uaNextNodesToRead[current].IndexRange); } } // if necessary, call the historyReadRawModified service again if (uaNextNodesToRead.length() > 0) { // perform the BrowseNext call UaStatus uaNextStatus = uaSession->historyReadRawModified( uaServiceSettings_, uaContext_, uaNextNodesToRead, uaNextResults); ret.fromSdk(uaNextStatus.statusCode(), "Synchronous HistoryReadRawModified invocation failed"); // we've finished an automatic read call, so increment the counter autoReadMore++; // now append the results to the results of the original read call for (uint32_t iNext = 0; iNext < uaNextResults.length() && ret.isGood(); iNext++) { // get the rank number of the original request uint32_t rank = ranks[iNext]; // increment the autoBrowsedNext autoReadMorePerTarget_[rank] = autoReadMore; // update the status uaResults_[rank].m_status = uaNextResults[iNext].m_status; if (uaResults_[rank].m_status.isGood()) { // update the continuation point uaResults_[rank].m_continuationPoint = uaNextResults[iNext].m_continuationPoint; // now we want to append the retrieved data values to the existing data // values int32_t oldDataLength = uaResults_[rank].m_dataValues.length(); int32_t nextDataLength = uaNextResults[iNext].m_dataValues.length(); // resize the original results, so that it can hold the new results uaResults_[rank].m_dataValues.resize(oldDataLength + nextDataLength); // now copy the data from the new results to the original results: for (uint32_t i=0, j=oldDataLength; i<nextDataLength; i++, j++) { UaVariant(uaNextResults[iNext].m_dataValues[i].Value).copyTo( &uaResults_[rank].m_dataValues[j].Value); uaResults_[rank].m_dataValues[j].SourceTimestamp \ = uaNextResults[iNext].m_dataValues[i].SourceTimestamp; uaResults_[rank].m_dataValues[j].ServerTimestamp \ = uaNextResults[iNext].m_dataValues[i].ServerTimestamp; uaResults_[rank].m_dataValues[j].SourcePicoseconds \ = uaNextResults[iNext].m_dataValues[i].SourcePicoseconds; uaResults_[rank].m_dataValues[j].ServerPicoseconds \ = uaNextResults[iNext].m_dataValues[i].ServerPicoseconds; } // now we want to append the retrieved modification info values to the // existing modification info values oldDataLength = uaResults_[rank].m_modificationInformation.length(); nextDataLength = uaNextResults[iNext].m_modificationInformation.length(); // resize the original results, so that it can hold the new results uaResults_[rank].m_modificationInformation.resize(oldDataLength + nextDataLength); // now copy the data from the new results to the original results: for (uint32_t i=0, j=oldDataLength; i<nextDataLength; i++, j++) { UaString userName(&uaNextResults[iNext].m_modificationInformation[i].UserName); if (!userName.isNull()) userName.copyTo(&uaResults_[rank].m_modificationInformation[j].UserName); uaResults_[rank].m_modificationInformation[j].ModificationTime \ = uaNextResults[iNext].m_modificationInformation[i].ModificationTime; uaResults_[rank].m_modificationInformation[j].UpdateType \ = uaNextResults[iNext].m_modificationInformation[i].UpdateType; } } } // check if we may still need to do another automatic BrowseNext finished = autoReadMore >= maxAutoReadMore; } else { // ok, no more automatic BrowseNext invocations needed! finished = true; } } return ret; }