AmdaProvider.cpp
168 lines
| 5.7 KiB
| text/x-c
|
CppLexer
Alexandre Leroux
|
r348 | #include "AmdaProvider.h" | ||
Alexandre Leroux
|
r380 | #include "AmdaDefs.h" | ||
Alexandre Leroux
|
r351 | #include "AmdaResultParser.h" | ||
Alexandre Leroux
|
r450 | #include <Common/DateUtils.h> | ||
Alexandre Leroux
|
r349 | #include <Data/DataProviderParameters.h> | ||
r358 | #include <Network/NetworkController.h> | |||
#include <SqpApplication.h> | ||||
#include <Variable/Variable.h> | ||||
Alexandre Leroux
|
r349 | |||
#include <QNetworkAccessManager> | ||||
#include <QNetworkReply> | ||||
Alexandre Leroux
|
r350 | #include <QTemporaryFile> | ||
r358 | #include <QThread> | |||
Alexandre Leroux
|
r348 | |||
Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider") | ||||
Alexandre Leroux
|
r349 | namespace { | ||
/// URL format for a request on AMDA server. The parameters are as follows: | ||||
/// - %1: start date | ||||
/// - %2: end date | ||||
/// - %3: parameter id | ||||
const auto AMDA_URL_FORMAT = QStringLiteral( | ||||
"http://amda.irap.omp.eu/php/rest/" | ||||
Alexandre Leroux
|
r437 | "getParameter.php?startTime=%1&stopTime=%2¶meterID=%3&outputFormat=ASCII&" | ||
Alexandre Leroux
|
r349 | "timeFormat=ISO8601&gzip=0"); | ||
/// Dates format passed in the URL (e.g 2013-09-23T09:00) | ||||
r406 | const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss"); | |||
Alexandre Leroux
|
r349 | |||
/// Formats a time to a date that can be passed in URL | ||||
r471 | QString dateFormat(double sqpRange) noexcept | |||
Alexandre Leroux
|
r349 | { | ||
r471 | auto dateTime = DateUtils::dateTime(sqpRange); | |||
Alexandre Leroux
|
r349 | return dateTime.toString(AMDA_TIME_FORMAT); | ||
} | ||||
Alexandre Leroux
|
r533 | AmdaResultParser::ValueType valueType(const QString &valueType) | ||
{ | ||||
if (valueType == QStringLiteral("scalar")) { | ||||
return AmdaResultParser::ValueType::SCALAR; | ||||
} | ||||
else if (valueType == QStringLiteral("vector")) { | ||||
return AmdaResultParser::ValueType::VECTOR; | ||||
} | ||||
else { | ||||
return AmdaResultParser::ValueType::UNKNOWN; | ||||
} | ||||
} | ||||
Alexandre Leroux
|
r349 | } // namespace | ||
Alexandre Leroux
|
r376 | AmdaProvider::AmdaProvider() | ||
Alexandre Leroux
|
r348 | { | ||
Alexandre Leroux
|
r424 | qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread(); | ||
r358 | if (auto app = sqpApp) { | |||
auto &networkController = app->networkController(); | ||||
Alexandre Leroux
|
r383 | connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid, | ||
std::function<void(QNetworkReply *, QUuid)>)), | ||||
&networkController, | ||||
SLOT(onProcessRequested(QNetworkRequest, QUuid, | ||||
std::function<void(QNetworkReply *, QUuid)>))); | ||||
r391 | ||||
connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this, | ||||
SIGNAL(dataProvidedProgress(QUuid, double))); | ||||
r358 | } | |||
Alexandre Leroux
|
r348 | } | ||
r510 | void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) | |||
Alexandre Leroux
|
r348 | { | ||
// NOTE: Try to use multithread if possible | ||||
Alexandre Leroux
|
r375 | const auto times = parameters.m_Times; | ||
Alexandre Leroux
|
r380 | const auto data = parameters.m_Data; | ||
Alexandre Leroux
|
r375 | for (const auto &dateTime : qAsConst(times)) { | ||
r511 | this->retrieveData(acqIdentifier, dateTime, data); | |||
r517 | ||||
r587 | // TORM when AMDA will support quick asynchrone request | |||
QThread::msleep(1000); | ||||
Alexandre Leroux
|
r348 | } | ||
} | ||||
r510 | void AmdaProvider::requestDataAborting(QUuid acqIdentifier) | |||
r388 | { | |||
if (auto app = sqpApp) { | ||||
auto &networkController = app->networkController(); | ||||
r510 | networkController.onReplyCanceled(acqIdentifier); | |||
r388 | } | |||
} | ||||
r471 | void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data) | |||
Alexandre Leroux
|
r349 | { | ||
Alexandre Leroux
|
r380 | // Retrieves product ID from data: if the value is invalid, no request is made | ||
auto productId = data.value(AMDA_XML_ID_KEY).toString(); | ||||
if (productId.isNull()) { | ||||
qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id"); | ||||
return; | ||||
} | ||||
r510 | qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime; | |||
Alexandre Leroux
|
r380 | |||
Alexandre Leroux
|
r533 | // Retrieves the data type that determines whether the expected format for the result file is | ||
// scalar, vector... | ||||
auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString()); | ||||
Alexandre Leroux
|
r349 | // /////////// // | ||
// Creates URL // | ||||
// /////////// // | ||||
Alexandre Leroux
|
r375 | auto startDate = dateFormat(dateTime.m_TStart); | ||
auto endDate = dateFormat(dateTime.m_TEnd); | ||||
Alexandre Leroux
|
r349 | |||
auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)}; | ||||
r517 | qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url; | |||
r358 | auto tempFile = std::make_shared<QTemporaryFile>(); | |||
Alexandre Leroux
|
r349 | |||
r358 | // LAMBDA | |||
Alexandre Leroux
|
r533 | auto httpDownloadFinished = [this, dateTime, tempFile, | ||
productValueType](QNetworkReply *reply, QUuid dataId) noexcept { | ||||
// Don't do anything if the reply was abort | ||||
if (reply->error() != QNetworkReply::OperationCanceledError) { | ||||
if (tempFile) { | ||||
auto replyReadAll = reply->readAll(); | ||||
if (!replyReadAll.isEmpty()) { | ||||
tempFile->write(replyReadAll); | ||||
} | ||||
tempFile->close(); | ||||
// Parse results file | ||||
if (auto dataSeries | ||||
= AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) { | ||||
emit dataProvided(dataId, dataSeries, dateTime); | ||||
} | ||||
else { | ||||
/// @todo ALX : debug | ||||
} | ||||
} | ||||
} | ||||
}; | ||||
r397 | auto httpFinishedLambda | |||
= [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept { | ||||
Alexandre Leroux
|
r350 | |||
r397 | // Don't do anything if the reply was abort | |||
if (reply->error() != QNetworkReply::OperationCanceledError) { | ||||
auto downloadFileUrl = QUrl{QString{reply->readAll()}}; | ||||
r388 | ||||
Alexandre Leroux
|
r350 | |||
r517 | qCInfo(LOG_AmdaProvider()) | |||
<< tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl; | ||||
r397 | // Executes request for downloading file // | |||
r358 | ||||
r397 | // Creates destination file | |||
if (tempFile->open()) { | ||||
// Executes request | ||||
emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, | ||||
httpDownloadFinished); | ||||
} | ||||
} | ||||
}; | ||||
r358 | ||||
// //////////////// // | ||||
// Executes request // | ||||
// //////////////// // | ||||
emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda); | ||||
Alexandre Leroux
|
r348 | } | ||