@@ -0,0 +1,19 | |||||
|
1 | #ifndef SCIQLOP_AMDARESULTPARSER_H | |||
|
2 | #define SCIQLOP_AMDARESULTPARSER_H | |||
|
3 | ||||
|
4 | #include "AmdaGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | ||||
|
8 | #include <memory> | |||
|
9 | ||||
|
10 | class IDataSeries; | |||
|
11 | ||||
|
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser) | |||
|
13 | ||||
|
14 | struct SCIQLOP_AMDA_EXPORT AmdaResultParser { | |||
|
15 | ||||
|
16 | static std::shared_ptr<IDataSeries> readTxt(const QString &filePath) noexcept; | |||
|
17 | }; | |||
|
18 | ||||
|
19 | #endif // SCIQLOP_AMDARESULTPARSER_H |
@@ -0,0 +1,70 | |||||
|
1 | #include "AmdaResultParser.h" | |||
|
2 | ||||
|
3 | #include <Data/ScalarSeries.h> | |||
|
4 | ||||
|
5 | #include <QDateTime> | |||
|
6 | #include <QFile> | |||
|
7 | ||||
|
8 | Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser") | |||
|
9 | ||||
|
10 | namespace { | |||
|
11 | ||||
|
12 | /// Format for dates in result files | |||
|
13 | const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz"); | |||
|
14 | ||||
|
15 | /// @todo ALX | |||
|
16 | double doubleDate(const QString &stringDate) noexcept | |||
|
17 | { | |||
|
18 | auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT); | |||
|
19 | return dateTime.toMSecsSinceEpoch() / 1000.; | |||
|
20 | } | |||
|
21 | ||||
|
22 | } // namespace | |||
|
23 | ||||
|
24 | std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept | |||
|
25 | { | |||
|
26 | QFile file{filePath}; | |||
|
27 | ||||
|
28 | if (!file.open(QFile::ReadOnly | QIODevice::Text)) { | |||
|
29 | qCCritical(LOG_AmdaResultParser()) | |||
|
30 | << QObject::tr("Can't retrieve AMDA data from file %1: %2") | |||
|
31 | .arg(filePath, file.errorString()); | |||
|
32 | return nullptr; | |||
|
33 | } | |||
|
34 | ||||
|
35 | auto xData = QVector<double>{}; | |||
|
36 | auto valuesData = QVector<double>{}; | |||
|
37 | ||||
|
38 | QTextStream stream{&file}; | |||
|
39 | ||||
|
40 | // Ignore comment lines (3 lines) | |||
|
41 | stream.readLine(); | |||
|
42 | stream.readLine(); | |||
|
43 | stream.readLine(); | |||
|
44 | ||||
|
45 | QString line{}; | |||
|
46 | auto lineRegex = QRegExp{QStringLiteral("\\s+")}; | |||
|
47 | while (stream.readLineInto(&line)) { | |||
|
48 | auto lineData = line.split(lineRegex, QString::SkipEmptyParts); | |||
|
49 | if (lineData.size() == 2) { | |||
|
50 | // X : the data is converted from date to double (in secs) | |||
|
51 | xData.push_back(doubleDate(lineData.at(0))); | |||
|
52 | ||||
|
53 | // Value | |||
|
54 | valuesData.push_back(lineData.at(1).toDouble()); | |||
|
55 | } | |||
|
56 | else { | |||
|
57 | /// @todo ALX : log | |||
|
58 | } | |||
|
59 | } | |||
|
60 | ||||
|
61 | /// @todo ALX : handle units | |||
|
62 | auto scalarSeries = std::make_shared<ScalarSeries>(xData.size(), Unit{"nT", true}, Unit{}); | |||
|
63 | ||||
|
64 | const auto count = xData.size(); | |||
|
65 | for (auto i = 0; i < count; ++i) { | |||
|
66 | scalarSeries->setData(i, xData.at(i), valuesData.at(i)); | |||
|
67 | } | |||
|
68 | ||||
|
69 | return scalarSeries; | |||
|
70 | } |
@@ -1,123 +1,134 | |||||
1 | #include "AmdaProvider.h" |
|
1 | #include "AmdaProvider.h" | |
|
2 | #include "AmdaResultParser.h" | |||
|
3 | ||||
2 | #include <Data/DataProviderParameters.h> |
|
4 | #include <Data/DataProviderParameters.h> | |
3 |
|
5 | |||
4 | #include <QNetworkAccessManager> |
|
6 | #include <QNetworkAccessManager> | |
5 | #include <QNetworkReply> |
|
7 | #include <QNetworkReply> | |
6 | #include <QTemporaryFile> |
|
8 | #include <QTemporaryFile> | |
7 |
|
9 | |||
8 | Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider") |
|
10 | Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider") | |
9 |
|
11 | |||
10 | namespace { |
|
12 | namespace { | |
11 |
|
13 | |||
12 | /// URL format for a request on AMDA server. The parameters are as follows: |
|
14 | /// URL format for a request on AMDA server. The parameters are as follows: | |
13 | /// - %1: start date |
|
15 | /// - %1: start date | |
14 | /// - %2: end date |
|
16 | /// - %2: end date | |
15 | /// - %3: parameter id |
|
17 | /// - %3: parameter id | |
16 | const auto AMDA_URL_FORMAT = QStringLiteral( |
|
18 | const auto AMDA_URL_FORMAT = QStringLiteral( | |
17 | "http://amda.irap.omp.eu/php/rest/" |
|
19 | "http://amda.irap.omp.eu/php/rest/" | |
18 | "getParameter.php?startTime=%1&stopTime=%2¶meterID=%3&sampling=60&outputFormat=ASCII&" |
|
20 | "getParameter.php?startTime=%1&stopTime=%2¶meterID=%3&sampling=60&outputFormat=ASCII&" | |
19 | "timeFormat=ISO8601&gzip=0"); |
|
21 | "timeFormat=ISO8601&gzip=0"); | |
20 |
|
22 | |||
21 | /// Dates format passed in the URL (e.g 2013-09-23T09:00) |
|
23 | /// Dates format passed in the URL (e.g 2013-09-23T09:00) | |
22 | const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss"); |
|
24 | const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:ss"); | |
23 |
|
25 | |||
24 | /// Formats a time to a date that can be passed in URL |
|
26 | /// Formats a time to a date that can be passed in URL | |
25 | QString dateFormat(double sqpDateTime) noexcept |
|
27 | QString dateFormat(double sqpDateTime) noexcept | |
26 | { |
|
28 | { | |
27 | auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.); |
|
29 | auto dateTime = QDateTime::fromMSecsSinceEpoch(sqpDateTime * 1000.); | |
28 | return dateTime.toString(AMDA_TIME_FORMAT); |
|
30 | return dateTime.toString(AMDA_TIME_FORMAT); | |
29 | } |
|
31 | } | |
30 |
|
32 | |||
31 | } // namespace |
|
33 | } // namespace | |
32 |
|
34 | |||
33 | struct AmdaProvider::AmdaProviderPrivate { |
|
35 | struct AmdaProvider::AmdaProviderPrivate { | |
34 | DataProviderParameters m_Params{}; |
|
36 | DataProviderParameters m_Params{}; | |
35 | std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr}; |
|
37 | std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr}; | |
36 | QNetworkReply *m_Reply{nullptr}; |
|
38 | QNetworkReply *m_Reply{nullptr}; | |
37 | std::unique_ptr<QTemporaryFile> m_File{nullptr}; |
|
39 | std::unique_ptr<QTemporaryFile> m_File{nullptr}; | |
38 | QUuid m_Token; |
|
40 | QUuid m_Token; | |
39 | }; |
|
41 | }; | |
40 |
|
42 | |||
41 | AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()} |
|
43 | AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()} | |
42 | { |
|
44 | { | |
43 | } |
|
45 | } | |
44 |
|
46 | |||
45 | void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) |
|
47 | void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) | |
46 | { |
|
48 | { | |
47 | // NOTE: Try to use multithread if possible |
|
49 | // NOTE: Try to use multithread if possible | |
48 | for (const auto &dateTime : dateTimeList) { |
|
50 | for (const auto &dateTime : dateTimeList) { | |
49 | retrieveData(token, DataProviderParameters{dateTime}); |
|
51 | retrieveData(token, DataProviderParameters{dateTime}); | |
50 | } |
|
52 | } | |
51 | } |
|
53 | } | |
52 |
|
54 | |||
53 | void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters ¶meters) const |
|
55 | void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters ¶meters) const | |
54 | { |
|
56 | { | |
55 | // /////////// // |
|
57 | // /////////// // | |
56 | // Creates URL // |
|
58 | // Creates URL // | |
57 | // /////////// // |
|
59 | // /////////// // | |
58 |
|
60 | |||
59 | auto startDate = dateFormat(parameters.m_Time.m_TStart); |
|
61 | auto startDate = dateFormat(parameters.m_Time.m_TStart); | |
60 | auto endDate = dateFormat(parameters.m_Time.m_TEnd); |
|
62 | auto endDate = dateFormat(parameters.m_Time.m_TEnd); | |
61 | auto productId = QStringLiteral("imf(0)"); |
|
63 | auto productId = QStringLiteral("imf(0)"); | |
62 |
|
64 | |||
63 | auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)}; |
|
65 | auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)}; | |
64 |
|
66 | |||
65 | // //////////////// // |
|
67 | // //////////////// // | |
66 | // Executes request // |
|
68 | // Executes request // | |
67 | // //////////////// // |
|
69 | // //////////////// // | |
68 |
|
70 | |||
69 | impl->m_Token = token; |
|
71 | impl->m_Token = token; | |
70 | impl->m_Params = parameters; |
|
72 | impl->m_Params = parameters; | |
71 | impl->m_AccessManager = std::make_unique<QNetworkAccessManager>(); |
|
73 | impl->m_AccessManager = std::make_unique<QNetworkAccessManager>(); | |
72 | impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{url}); |
|
74 | impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{url}); | |
73 | connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpFinished); |
|
75 | connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpFinished); | |
74 | } |
|
76 | } | |
75 |
|
77 | |||
76 | void AmdaProvider::httpFinished() noexcept |
|
78 | void AmdaProvider::httpFinished() noexcept | |
77 | { |
|
79 | { | |
78 | // ////////////////////// // |
|
80 | // ////////////////////// // | |
79 | // Gets download file url // |
|
81 | // Gets download file url // | |
80 | // ////////////////////// // |
|
82 | // ////////////////////// // | |
81 |
|
83 | |||
82 | auto downloadFileUrl = QUrl{QString{impl->m_Reply->readAll()}}; |
|
84 | auto downloadFileUrl = QUrl{QString{impl->m_Reply->readAll()}}; | |
83 |
|
85 | |||
84 | // ///////////////////////////////////// // |
|
86 | // ///////////////////////////////////// // | |
85 | // Executes request for downloading file // |
|
87 | // Executes request for downloading file // | |
86 | // ///////////////////////////////////// // |
|
88 | // ///////////////////////////////////// // | |
87 |
|
89 | |||
88 | // Deletes old reply |
|
90 | // Deletes old reply | |
89 | impl->m_Reply->deleteLater(); |
|
91 | impl->m_Reply->deleteLater(); | |
90 | impl->m_Reply = nullptr; |
|
92 | impl->m_Reply = nullptr; | |
91 |
|
93 | |||
92 | // Creates destination file |
|
94 | // Creates destination file | |
93 | impl->m_File = std::make_unique<QTemporaryFile>(); |
|
95 | impl->m_File = std::make_unique<QTemporaryFile>(); | |
94 | if (impl->m_File->open()) { |
|
96 | if (impl->m_File->open()) { | |
95 | qCDebug(LOG_AmdaProvider()) << "Temp file: " << impl->m_File->fileName(); |
|
97 | qCDebug(LOG_AmdaProvider()) << "Temp file: " << impl->m_File->fileName(); | |
96 |
|
98 | |||
97 | // Executes request |
|
99 | // Executes request | |
98 | impl->m_AccessManager = std::make_unique<QNetworkAccessManager>(); |
|
100 | impl->m_AccessManager = std::make_unique<QNetworkAccessManager>(); | |
99 | impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{downloadFileUrl}); |
|
101 | impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{downloadFileUrl}); | |
100 | connect(impl->m_Reply, &QNetworkReply::finished, this, |
|
102 | connect(impl->m_Reply, &QNetworkReply::finished, this, | |
101 | &AmdaProvider::httpDownloadReadyRead); |
|
103 | &AmdaProvider::httpDownloadReadyRead); | |
102 | connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpDownloadFinished); |
|
104 | connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpDownloadFinished); | |
103 | } |
|
105 | } | |
104 | } |
|
106 | } | |
105 |
|
107 | |||
106 | void AmdaProvider::httpDownloadFinished() noexcept |
|
108 | void AmdaProvider::httpDownloadFinished() noexcept | |
107 | { |
|
109 | { | |
108 | if (impl->m_File) { |
|
110 | if (impl->m_File) { | |
109 | impl->m_File->close(); |
|
111 | impl->m_File->close(); | |
|
112 | ||||
|
113 | // Parse results file | |||
|
114 | if (auto dataSeries = AmdaResultParser::readTxt(impl->m_File->fileName())) { | |||
|
115 | emit dataProvided(impl->m_Token, dataSeries, impl->m_Params.m_Time); | |||
|
116 | } | |||
|
117 | else { | |||
|
118 | /// @todo ALX : debug | |||
|
119 | } | |||
|
120 | ||||
110 | impl->m_File = nullptr; |
|
121 | impl->m_File = nullptr; | |
111 | } |
|
122 | } | |
112 |
|
123 | |||
113 | // Deletes reply |
|
124 | // Deletes reply | |
114 | impl->m_Reply->deleteLater(); |
|
125 | impl->m_Reply->deleteLater(); | |
115 | impl->m_Reply = nullptr; |
|
126 | impl->m_Reply = nullptr; | |
116 | } |
|
127 | } | |
117 |
|
128 | |||
118 | void AmdaProvider::httpDownloadReadyRead() noexcept |
|
129 | void AmdaProvider::httpDownloadReadyRead() noexcept | |
119 | { |
|
130 | { | |
120 | if (impl->m_File) { |
|
131 | if (impl->m_File) { | |
121 | impl->m_File->write(impl->m_Reply->readAll()); |
|
132 | impl->m_File->write(impl->m_Reply->readAll()); | |
122 | } |
|
133 | } | |
123 | } |
|
134 | } |
General Comments 0
You need to be logged in to leave comments.
Login now