mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-13 15:45:42 +08:00
refs #452, data readers / writers for DB (via web services)
* flags for readers (which reader is reading specific entities etc.) * web data services: bundling multiple readers (webdataservices) and implementing IWebDataReaderProvider * readers now able to read single entities
This commit is contained in:
committed by
Mathew Sutcliffe
parent
33330394a9
commit
07c6370819
@@ -4,6 +4,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "blackcorefreefunctions.h"
|
||||
#include "blackcore/webreaderflags.h"
|
||||
|
||||
#include "voice_channel.h"
|
||||
#include "network.h"
|
||||
#include "simulator.h"
|
||||
@@ -13,8 +15,15 @@ namespace BlackCore
|
||||
{
|
||||
void registerMetadata()
|
||||
{
|
||||
qRegisterMetaType<BlackCore::IVoiceChannel::ConnectionStatus>();
|
||||
qRegisterMetaType<BlackCore::INetwork::ConnectionStatus>();
|
||||
int id;
|
||||
id = qRegisterMetaType<BlackCore::IVoiceChannel::ConnectionStatus>();
|
||||
Q_ASSERT_X(id >= 1024, Q_FUNC_INFO, "wrong id for metatype");
|
||||
id = qRegisterMetaType<BlackCore::INetwork::ConnectionStatus>();
|
||||
Q_ASSERT_X(id >= 1024, Q_FUNC_INFO, "wrong id for metatype");
|
||||
id = qRegisterMetaType<BlackCore::CWebReaderFlags::WebReaderFlags>();
|
||||
Q_ASSERT_X(id >= 1024, Q_FUNC_INFO, "wrong id for metatype");
|
||||
id = qRegisterMetaType<BlackCore::CWebReaderFlags::WebReader>();
|
||||
Q_UNUSED(id);
|
||||
}
|
||||
|
||||
bool isCurrentThreadObjectThread(QObject *toBeTested)
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
|
||||
#include "databasereader.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/datastoreutility.h"
|
||||
#include <QJsonDocument>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Network;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
@@ -18,54 +21,61 @@ namespace BlackCore
|
||||
BlackMisc::CThreadedReader(owner, name)
|
||||
{ }
|
||||
|
||||
void CDatabaseReader::readInBackgroundThread()
|
||||
void CDatabaseReader::readInBackgroundThread(CDbFlags::Entity entities)
|
||||
{
|
||||
bool s = QMetaObject::invokeMethod(this, "ps_read");
|
||||
if (m_shutdown) { return; }
|
||||
bool s = QMetaObject::invokeMethod(this, "ps_read", Q_ARG(BlackMisc::Network::CDbFlags::Entity, entities));
|
||||
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
|
||||
Q_UNUSED(s);
|
||||
}
|
||||
|
||||
QJsonArray CDatabaseReader::transformReplyIntoJsonArray(QNetworkReply *nwReply) const
|
||||
CDatabaseReader::JsonDatastoreResponse CDatabaseReader::transformReplyIntoDatastoreResponse(QNetworkReply *nwReply) const
|
||||
{
|
||||
this->threadAssertCheck();
|
||||
QJsonArray array;
|
||||
if (this->isFinished())
|
||||
JsonDatastoreResponse datastoreResponse;
|
||||
if (m_shutdown || this->isFinished())
|
||||
{
|
||||
CLogMessage(this).debug() << Q_FUNC_INFO;
|
||||
CLogMessage(this).info("Terminated data parsing process"); // for users
|
||||
return array; // stop, terminate straight away, ending thread
|
||||
nwReply->abort();
|
||||
return datastoreResponse; // stop, terminate straight away, ending thread
|
||||
}
|
||||
|
||||
if (nwReply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
const QString dataFileData = nwReply->readAll();
|
||||
const QString dataFileData = nwReply->readAll().trimmed();
|
||||
nwReply->close(); // close asap
|
||||
if (dataFileData.isEmpty()) { return array; }
|
||||
if (dataFileData.isEmpty()) { datastoreResponse.updated = QDateTime::currentDateTimeUtc(); return datastoreResponse; }
|
||||
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(dataFileData.toUtf8());
|
||||
QJsonObject jsonObject = jsonResponse.object();
|
||||
QJsonArray jsonArray = jsonObject["rows"].toArray();
|
||||
return jsonArray;
|
||||
if (jsonResponse.isArray())
|
||||
{
|
||||
// directly an array, no further info
|
||||
datastoreResponse.jsonArray = jsonResponse.array();
|
||||
datastoreResponse.updated = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonObject responseObject(jsonResponse.object());
|
||||
datastoreResponse.jsonArray = responseObject["data"].toArray();
|
||||
QString ts(responseObject["latest"].toString());
|
||||
datastoreResponse.updated = ts.isEmpty() ? QDateTime::currentDateTimeUtc() : CDatastoreUtility::parseTimestamp(ts);
|
||||
}
|
||||
return datastoreResponse;
|
||||
}
|
||||
CLogMessage(this).warning("Reading data failed %1 %2") << nwReply->errorString() << nwReply->url().toString();
|
||||
|
||||
// no valid response
|
||||
QString error(nwReply->errorString());
|
||||
QString url(nwReply->url().toString());
|
||||
CLogMessage(this).warning("Reading data failed %1 %2") << error << url;
|
||||
nwReply->abort();
|
||||
return array;
|
||||
return datastoreResponse;
|
||||
}
|
||||
|
||||
QString CDatabaseReader::buildUrl(const QString &protocol, const QString &server, const QString &baseUrl, const QString &serviceUrl)
|
||||
bool CDatabaseReader::canConnect() const
|
||||
{
|
||||
Q_ASSERT_X(protocol.length() > 3, Q_FUNC_INFO, "worng protocol");
|
||||
Q_ASSERT_X(!server.isEmpty(), Q_FUNC_INFO, "missing server");
|
||||
Q_ASSERT_X(!serviceUrl.isEmpty(), Q_FUNC_INFO, "missing service URL");
|
||||
|
||||
QString url(server);
|
||||
if (!baseUrl.isEmpty())
|
||||
{
|
||||
url.append("/").append(baseUrl);
|
||||
}
|
||||
url.append("/").append(serviceUrl);
|
||||
url.replace("//", "/");
|
||||
return protocol + "://" + url;
|
||||
QString m;
|
||||
return canConnect(m);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackmisc/threadedreader.h"
|
||||
#include "blackmisc/network/dbflags.h"
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonArray>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
@@ -26,19 +28,47 @@ namespace BlackCore
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Response from our database
|
||||
struct JsonDatastoreResponse
|
||||
{
|
||||
QJsonArray jsonArray; //!< JSON array data
|
||||
QDateTime updated; //!< when updated
|
||||
|
||||
//! Any data?
|
||||
bool isEmpty() const { return jsonArray.isEmpty(); }
|
||||
|
||||
//! Number of elements
|
||||
int size() const { return jsonArray.size(); }
|
||||
|
||||
//! Any timestamp?
|
||||
bool hasTimestamp() const { return updated.isValid(); }
|
||||
|
||||
//! Is response newer?
|
||||
bool isNewer(const QDateTime &ts) const { return updated.toMSecsSinceEpoch() > ts.toMSecsSinceEpoch(); }
|
||||
|
||||
//! Is response newer?
|
||||
bool isNewer(qint64 mSecsSinceEpoch) const { return updated.toMSecsSinceEpoch() > mSecsSinceEpoch; }
|
||||
|
||||
//! Implicit conversion
|
||||
operator QJsonArray() const { return jsonArray; }
|
||||
};
|
||||
|
||||
//! Start reading in own thread
|
||||
void readInBackgroundThread();
|
||||
void readInBackgroundThread(BlackMisc::Network::CDbFlags::Entity entities);
|
||||
|
||||
//! Can connect to DB
|
||||
bool canConnect() const;
|
||||
|
||||
//! Can connect to server?
|
||||
//! \return message why connect failed
|
||||
virtual bool canConnect(QString &message) const = 0;
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
CDatabaseReader(QObject *owner, const QString &name);
|
||||
|
||||
//! Check if terminated or error, otherwise split into array of objects
|
||||
QJsonArray transformReplyIntoJsonArray(QNetworkReply *nwReply) const;
|
||||
|
||||
//! Build service URL
|
||||
static QString buildUrl(const QString &protocol, const QString &server, const QString &baseUrl, const QString &serviceUrl);
|
||||
|
||||
JsonDatastoreResponse transformReplyIntoDatastoreResponse(QNetworkReply *nwReply) const;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
135
src/blackcore/databasewriter.cpp
Normal file
135
src/blackcore/databasewriter.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "databasewriter.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/datastoreutility.h"
|
||||
#include "blackmisc/networkutils.h"
|
||||
#include <QUrlQuery>
|
||||
#include <QJsonDocument>
|
||||
#include <QHttpPart>
|
||||
#include <QHttpMultiPart>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Simulation;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
CDatabaseWriter::CDatabaseWriter(const QString &protocol, const QString &server, const QString &baseUrl, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_modelUrl(getModelWriteUrl(protocol, server, baseUrl))
|
||||
{
|
||||
this->m_networkManager = new QNetworkAccessManager(this);
|
||||
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CDatabaseWriter::ps_postResponse);
|
||||
}
|
||||
|
||||
CStatusMessageList CDatabaseWriter::asyncWriteModel(const CAircraftModel &model)
|
||||
{
|
||||
CStatusMessageList msg;
|
||||
if (m_shutdown)
|
||||
{
|
||||
msg.push_back(CStatusMessage(CStatusMessage::SeverityWarning, "Database writer shuts down"));
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (m_pendingReply)
|
||||
{
|
||||
msg.push_back(CStatusMessage(CStatusMessage::SeverityWarning, "Another write operation in progress"));
|
||||
return msg;
|
||||
}
|
||||
|
||||
QUrl url(m_modelUrl);
|
||||
QNetworkRequest request(url);
|
||||
const QByteArray jsonData(QJsonDocument(model.toJson()).toJson(QJsonDocument::Compact));
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
QHttpPart textPart;
|
||||
QString name("form-data; name=\"swiftjson\"");
|
||||
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(name));
|
||||
textPart.setBody(jsonData);
|
||||
multiPart->append(textPart);
|
||||
|
||||
if (m_phpDebug)
|
||||
{
|
||||
QHttpPart textPartDebug;
|
||||
textPartDebug.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"XDEBUG_SESSION_START\""));
|
||||
textPartDebug.setBody(QString("ECLIPSE_DBGP").toUtf8());
|
||||
multiPart->append(textPartDebug);
|
||||
}
|
||||
|
||||
m_pendingReply = this->m_networkManager->post(request, multiPart);
|
||||
multiPart->setParent(m_pendingReply);
|
||||
return msg;
|
||||
}
|
||||
|
||||
void CDatabaseWriter::gracefulShutdown()
|
||||
{
|
||||
m_shutdown = true;
|
||||
if (m_pendingReply)
|
||||
{
|
||||
m_pendingReply->abort();
|
||||
m_pendingReply = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CDatabaseWriter::ps_postResponse(QNetworkReply *nwReplyPtr)
|
||||
{
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
m_pendingReply = nullptr;
|
||||
|
||||
if (m_shutdown)
|
||||
{
|
||||
nwReply->abort();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nwReply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
const QString dataFileData(nwReply->readAll().trimmed());
|
||||
nwReply->close(); // close asap
|
||||
|
||||
if (dataFileData.isEmpty())
|
||||
{
|
||||
CLogMessage(this).error("No response data");
|
||||
return;
|
||||
}
|
||||
|
||||
CStatusMessageList msgs;
|
||||
CVariant id;
|
||||
bool success = CDatastoreUtility::parseSwiftWriteResponse(dataFileData, msgs, id);
|
||||
CLogMessage(this).preformatted(msgs);
|
||||
Q_UNUSED(success);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString error = nwReply->errorString();
|
||||
nwReply->close(); // close asap
|
||||
CLogMessage(this).error(error);
|
||||
}
|
||||
}
|
||||
|
||||
QString CDatabaseWriter::getModelWriteUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/swiftwritemodel.php");
|
||||
}
|
||||
|
||||
QList<QByteArray> CDatabaseWriter::splitData(const QByteArray &data, int size)
|
||||
{
|
||||
if (data.size() <= size) { return QList<QByteArray>({data}); }
|
||||
int pos = 0, arrsize = data.size();
|
||||
QList<QByteArray> arrays;
|
||||
while (pos < arrsize)
|
||||
{
|
||||
QByteArray arr = data.mid(pos, size);
|
||||
arrays << arr;
|
||||
pos += arr.size();
|
||||
}
|
||||
return arrays;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
60
src/blackcore/databasewriter.h
Normal file
60
src/blackcore/databasewriter.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef BLACKCORE_DATABASE_WRITER_H
|
||||
#define BLACKCORE_DATABASE_WRITER_H
|
||||
|
||||
//! \file
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackmisc/threadedreader.h"
|
||||
#include "blackmisc/simulation/aircraftmodel.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonArray>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
//! Write to the swift DB
|
||||
class BLACKCORE_EXPORT CDatabaseWriter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
CDatabaseWriter(const QString &protocol, const QString &server, const QString &baseUrl, QObject *parent);
|
||||
|
||||
//! Write model to DB
|
||||
BlackMisc::CStatusMessageList asyncWriteModel(const BlackMisc::Simulation::CAircraftModel &model);
|
||||
|
||||
//! Shutdown
|
||||
void gracefulShutdown();
|
||||
|
||||
private slots:
|
||||
//! Post response
|
||||
void ps_postResponse(QNetworkReply *nwReplyPtr);
|
||||
|
||||
private:
|
||||
QString m_modelUrl;
|
||||
QNetworkAccessManager *m_networkManager = nullptr;
|
||||
QNetworkReply *m_pendingReply = nullptr;
|
||||
bool m_shutdown = false;
|
||||
bool m_phpDebug = true;
|
||||
|
||||
//! URL model web service
|
||||
static QString getModelWriteUrl(const QString &protocol, const QString &server, const QString &baseUrl);
|
||||
|
||||
//! Split data array
|
||||
static QList<QByteArray> splitData(const QByteArray &data, int size);
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
#endif // guard
|
||||
@@ -9,24 +9,30 @@
|
||||
|
||||
#include "blackmisc/sequence.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/networkutils.h"
|
||||
#include "icaodatareader.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::Network;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
CIcaoDataReader::CIcaoDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl) :
|
||||
CDatabaseReader(owner, "CIcaoDataReader"),
|
||||
m_urlAircraftIcao(getAircraftIcaoUrl(protocol, server, baseUrl)), m_urlAirlineIcao(getAirlineIcaoUrl(protocol, server, baseUrl))
|
||||
m_urlAircraftIcao(getAircraftIcaoUrl(protocol, server, baseUrl)),
|
||||
m_urlAirlineIcao(getAirlineIcaoUrl(protocol, server, baseUrl)),
|
||||
m_urlCountry(getCountryUrl(protocol, server, baseUrl))
|
||||
{
|
||||
this->m_networkManagerAircraft = new QNetworkAccessManager(this);
|
||||
this->m_networkManagerAirlines = new QNetworkAccessManager(this);
|
||||
this->m_networkManagerCountries = new QNetworkAccessManager(this);
|
||||
|
||||
this->connect(this->m_networkManagerAircraft, &QNetworkAccessManager::finished, this, &CIcaoDataReader::ps_parseAircraftIcaoData);
|
||||
this->connect(this->m_networkManagerAirlines, &QNetworkAccessManager::finished, this, &CIcaoDataReader::ps_parseAirlineIcaoData);
|
||||
this->connect(this->m_networkManagerCountries, &QNetworkAccessManager::finished, this, &CIcaoDataReader::ps_parseCountryData);
|
||||
}
|
||||
|
||||
CAircraftIcaoCodeList CIcaoDataReader::getAircraftIcaoCodes() const
|
||||
@@ -35,12 +41,99 @@ namespace BlackCore
|
||||
return m_aircraftIcaos;
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CIcaoDataReader::getAircraftIcaoCodeForDesignator(const QString &designator) const
|
||||
{
|
||||
return getAircraftIcaoCodes().findFirstByDesignatorAndRank(designator);
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CIcaoDataReader::getAircraftIcaoCodeForDbKey(int key) const
|
||||
{
|
||||
return getAircraftIcaoCodes().findByKey(key);
|
||||
}
|
||||
|
||||
CAirlineIcaoCodeList CIcaoDataReader::getAirlineIcaoCodes() const
|
||||
{
|
||||
QReadLocker l(&m_lockAirline);
|
||||
return m_airlineIcaos;
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CIcaoDataReader::smartAircraftIcaoSelector(const CAircraftIcaoCode &icao) const
|
||||
{
|
||||
CAircraftIcaoCodeList codes(getAircraftIcaoCodes()); // thread safe copy
|
||||
if (icao.hasValidDbKey())
|
||||
{
|
||||
int k = icao.getDbKey();
|
||||
CAircraftIcaoCode c(codes.findByKey(k));
|
||||
if (c.hasCompleteData()) { return c; }
|
||||
}
|
||||
|
||||
if (icao.hasKnownDesignator())
|
||||
{
|
||||
const QString d(icao.getDesignator());
|
||||
codes = codes.findByDesignator(d);
|
||||
if (codes.size() == 1) { return codes.front(); }
|
||||
if (codes.isEmpty()) { return icao; }
|
||||
codes.sortByRank();
|
||||
|
||||
// intentionally continue here
|
||||
}
|
||||
|
||||
// further reduce by manufacturer
|
||||
if (icao.hasManufacturer())
|
||||
{
|
||||
const QString m(icao.getManufacturer());
|
||||
codes = codes.findByManufacturer(m);
|
||||
if (codes.size() == 1) { return codes.front(); }
|
||||
if (codes.isEmpty()) { return icao; }
|
||||
|
||||
// intentionally continue here
|
||||
}
|
||||
|
||||
// lucky punch on description?
|
||||
if (icao.hasModelDescription())
|
||||
{
|
||||
// do not affect codes here, it might return no results
|
||||
const QString d(icao.getModelDescription());
|
||||
CAircraftIcaoCodeList cm(codes.findByDescription(d));
|
||||
if (cm.size() == 1) { return cm.front(); }
|
||||
if (cm.size() > 1 && cm.size() < codes.size()) { return codes.front(); }
|
||||
}
|
||||
return codes.frontOrDefault(); // sorted by rank
|
||||
}
|
||||
|
||||
CCountryList CIcaoDataReader::getCountries() const
|
||||
{
|
||||
QReadLocker l(&m_lockCountry);
|
||||
return m_countries;
|
||||
}
|
||||
|
||||
CCountry CIcaoDataReader::getCountryForIsoCode(const QString &isoCode) const
|
||||
{
|
||||
QReadLocker l(&m_lockCountry);
|
||||
return m_countries.findByIsoCode(isoCode);
|
||||
}
|
||||
|
||||
CCountry CIcaoDataReader::getCountryForName(const QString &name) const
|
||||
{
|
||||
QReadLocker l(&m_lockCountry);
|
||||
return m_countries.findBestMatchByCountryName(name);
|
||||
}
|
||||
|
||||
CAirlineIcaoCode CIcaoDataReader::getAirlineIcaoCodeForDesignator(const QString &designator) const
|
||||
{
|
||||
return getAirlineIcaoCodes().findByVDesignator(designator);
|
||||
}
|
||||
|
||||
CAirlineIcaoCode CIcaoDataReader::getAirlineIcaoCodeForDbKey(int key) const
|
||||
{
|
||||
return getAirlineIcaoCodes().findByKey(key);
|
||||
}
|
||||
|
||||
CAirlineIcaoCode CIcaoDataReader::smartAirlineIcaoSelector(const CAirlineIcaoCode &icao) const
|
||||
{
|
||||
return icao;
|
||||
}
|
||||
|
||||
int CIcaoDataReader::getAircraftIcaoCodesCount() const
|
||||
{
|
||||
QReadLocker l(&m_lockAircraft);
|
||||
@@ -53,27 +146,50 @@ namespace BlackCore
|
||||
return m_airlineIcaos.size();
|
||||
}
|
||||
|
||||
QString CIcaoDataReader::getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
bool CIcaoDataReader::areAllDataRead() const
|
||||
{
|
||||
return buildUrl(protocol, server, baseUrl, "service/allaircrafticao.php?rows=20000&sord=asc");
|
||||
return getCountriesCount() > 0 && getAirlineIcaoCodesCount() > 0 && getAircraftIcaoCodesCount() > 0;
|
||||
}
|
||||
|
||||
QString CIcaoDataReader::getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
int CIcaoDataReader::getCountriesCount() const
|
||||
{
|
||||
return buildUrl(protocol, server, baseUrl, "service/allairlineicao.php?rows=20000&sord=asc");
|
||||
QReadLocker l(&m_lockCountry);
|
||||
return m_countries.size();
|
||||
}
|
||||
|
||||
void CIcaoDataReader::ps_read()
|
||||
void CIcaoDataReader::ps_read(BlackMisc::Network::CDbFlags::Entity entities)
|
||||
{
|
||||
this->threadAssertCheck();
|
||||
Q_ASSERT(this->m_networkManagerAircraft);
|
||||
Q_ASSERT(this->m_networkManagerAirlines);
|
||||
Q_ASSERT(this->m_networkManagerCountries);
|
||||
Q_ASSERT(!m_urlAircraftIcao.isEmpty());
|
||||
Q_ASSERT(!m_urlAirlineIcao.isEmpty());
|
||||
QNetworkRequest requestAircraft(m_urlAircraftIcao);
|
||||
QNetworkRequest requestAirline(m_urlAirlineIcao);
|
||||
this->m_networkManagerAircraft->get(requestAircraft);
|
||||
this->m_networkManagerAirlines->get(requestAirline);
|
||||
Q_ASSERT(!m_urlCountry.isEmpty());
|
||||
|
||||
CDbFlags::Entity entitiesTriggered = CDbFlags::NoEntity;
|
||||
if (entities.testFlag(CDbFlags::AircraftIcaoEntity))
|
||||
{
|
||||
QNetworkRequest requestAircraft(m_urlAircraftIcao);
|
||||
this->m_networkManagerAircraft->get(requestAircraft);
|
||||
entitiesTriggered |= CDbFlags::AircraftIcaoEntity;
|
||||
}
|
||||
|
||||
if (entities.testFlag(CDbFlags::AirlineIcaoEntity))
|
||||
{
|
||||
QNetworkRequest requestAirline(m_urlAirlineIcao);
|
||||
this->m_networkManagerAirlines->get(requestAirline);
|
||||
entitiesTriggered |= CDbFlags::AirlineIcaoEntity;
|
||||
}
|
||||
|
||||
if (entities.testFlag(CDbFlags::CountryEntity))
|
||||
{
|
||||
QNetworkRequest requestCountry(m_urlCountry);
|
||||
this->m_networkManagerCountries->get(requestCountry);
|
||||
entitiesTriggered |= CDbFlags::CountryEntity;
|
||||
}
|
||||
|
||||
emit readData(entitiesTriggered, CDbFlags::StartRead, 0);
|
||||
}
|
||||
|
||||
void CIcaoDataReader::ps_parseAircraftIcaoData(QNetworkReply *nwReplyPtr)
|
||||
@@ -81,8 +197,12 @@ namespace BlackCore
|
||||
// wrap pointer, make sure any exit cleans up reply
|
||||
// required to use delete later as object is created in a different thread
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
|
||||
if (array.isEmpty()) { return; }
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::AircraftIcaoEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CAircraftIcaoCodeList codes = CAircraftIcaoCodeList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
@@ -92,15 +212,18 @@ namespace BlackCore
|
||||
this->m_aircraftIcaos = codes;
|
||||
n = codes.size();
|
||||
}
|
||||
emit readAircraftIcaoCodes(n);
|
||||
if (this->getAirlineIcaoCodesCount() > 0) { emit readAll(); }
|
||||
emit readData(CDbFlags::AircraftIcaoEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
void CIcaoDataReader::ps_parseAirlineIcaoData(QNetworkReply *nwReplyPtr)
|
||||
{
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
|
||||
if (array.isEmpty()) { return; }
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::AirlineIcaoEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CAirlineIcaoCodeList codes = CAirlineIcaoCodeList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
@@ -110,7 +233,52 @@ namespace BlackCore
|
||||
this->m_airlineIcaos = codes;
|
||||
n = codes.size();
|
||||
}
|
||||
emit readAirlinesIcaoCodes(n);
|
||||
if (this->getAircraftIcaoCodesCount() > 0) { emit readAll(); }
|
||||
emit readData(CDbFlags::AirlineIcaoEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
void CIcaoDataReader::ps_parseCountryData(QNetworkReply *nwReplyPtr)
|
||||
{
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::CountryEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CCountryList countries = CCountryList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
int n;
|
||||
{
|
||||
QWriteLocker wl(&this->m_lockCountry);
|
||||
this->m_countries = countries;
|
||||
n = m_countries.size();
|
||||
}
|
||||
emit readData(CDbFlags::CountryEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
bool CIcaoDataReader::canConnect(QString &message) const
|
||||
{
|
||||
if (m_urlAircraftIcao.isEmpty() || m_urlAirlineIcao.isEmpty()) { return false; }
|
||||
bool cm = CNetworkUtils::canConnect(m_urlAircraftIcao, message);
|
||||
|
||||
// currently only testing one URL, might be changed in the future
|
||||
return cm;
|
||||
}
|
||||
|
||||
QString CIcaoDataReader::getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonaircrafticao.php");
|
||||
}
|
||||
|
||||
QString CIcaoDataReader::getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonairlineicao.php");
|
||||
}
|
||||
|
||||
QString CIcaoDataReader::getCountryUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsoncountry.php");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackcore/databasereader.h"
|
||||
#include "blackmisc/countrylist.h"
|
||||
#include "blackmisc/aviation/aircrafticaocodelist.h"
|
||||
#include "blackmisc/aviation/airlineicaocodelist.h"
|
||||
#include "blackmisc/network/dbflags.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
@@ -37,10 +39,50 @@ namespace BlackCore
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const;
|
||||
|
||||
//! Get aircraft ICAO information for designator
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDesignator(const QString &designator) const;
|
||||
|
||||
//! Get aircraft ICAO information for key
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const;
|
||||
|
||||
//! Get airline ICAO information
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const;
|
||||
|
||||
//! Get best match for incomplete aircraft ICAO code
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const BlackMisc::Aviation::CAircraftIcaoCode &icao) const;
|
||||
|
||||
//! Get countries
|
||||
//! \threadsafe
|
||||
BlackMisc::CCountryList getCountries() const;
|
||||
|
||||
//! Get countries count
|
||||
//! \threadsafe
|
||||
int getCountriesCount() const;
|
||||
|
||||
//! Get country for ISO code
|
||||
//! \threadsafe
|
||||
BlackMisc::CCountry getCountryForIsoCode(const QString &isoCode) const;
|
||||
|
||||
//! Get country for ISO name
|
||||
//! \threadsafe
|
||||
BlackMisc::CCountry getCountryForName(const QString &name) const;
|
||||
|
||||
//! Get airline ICAO information for designator
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const;
|
||||
|
||||
//! Get airline ICAO information for key
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int key) const;
|
||||
|
||||
//! Get best match for incomplete airline ICAO code
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CAirlineIcaoCode smartAirlineIcaoSelector(const BlackMisc::Aviation::CAirlineIcaoCode &icao) const;
|
||||
|
||||
//! Get aircraft ICAO information count
|
||||
//! \threadsafe
|
||||
int getAircraftIcaoCodesCount() const;
|
||||
@@ -49,15 +91,19 @@ namespace BlackCore
|
||||
//! \threadsafe
|
||||
int getAirlineIcaoCodesCount() const;
|
||||
|
||||
//! All data read?
|
||||
//! \threadsafe
|
||||
bool areAllDataRead() const;
|
||||
|
||||
//! Can connect to server?
|
||||
virtual bool canConnect(QString &message) const override;
|
||||
|
||||
//! \copydoc CDatabaseReader::canConnect()
|
||||
using CDatabaseReader::canConnect;
|
||||
|
||||
signals:
|
||||
//! Codes have been read
|
||||
void readAircraftIcaoCodes(int number);
|
||||
|
||||
//! Codes have been read
|
||||
void readAirlinesIcaoCodes(int number);
|
||||
|
||||
//! Everything has been read
|
||||
void readAll();
|
||||
//! Combined read signal
|
||||
void readData(BlackMisc::Network::CDbFlags::Entity entity, BlackMisc::Network::CDbFlags::ReadState state, int number);
|
||||
|
||||
private slots:
|
||||
//! Aircraft have been read
|
||||
@@ -66,25 +112,35 @@ namespace BlackCore
|
||||
//! Airlines have been read
|
||||
void ps_parseAirlineIcaoData(QNetworkReply *nwReply);
|
||||
|
||||
//! Airlines have been read
|
||||
void ps_parseCountryData(QNetworkReply *nwReply);
|
||||
|
||||
//! Read / re-read data file
|
||||
void ps_read();
|
||||
void ps_read(BlackMisc::Network::CDbFlags::Entity entities);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_networkManagerAircraft = nullptr;
|
||||
QNetworkAccessManager *m_networkManagerAirlines = nullptr;
|
||||
QNetworkAccessManager *m_networkManagerCountries = nullptr;
|
||||
BlackMisc::Aviation::CAircraftIcaoCodeList m_aircraftIcaos;
|
||||
BlackMisc::Aviation::CAirlineIcaoCodeList m_airlineIcaos;
|
||||
BlackMisc::CCountryList m_countries;
|
||||
QString m_urlAircraftIcao;
|
||||
QString m_urlAirlineIcao;
|
||||
QString m_urlCountry;
|
||||
|
||||
mutable QReadWriteLock m_lockAirline;
|
||||
mutable QReadWriteLock m_lockAircraft;
|
||||
mutable QReadWriteLock m_lockCountry;
|
||||
|
||||
//! URL
|
||||
static QString getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
|
||||
|
||||
//! URL
|
||||
static QString getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
|
||||
|
||||
//! URL
|
||||
static QString getCountryUrl(const QString &protocol, const QString &server, const QString &baseUrl);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "blackmisc/sequence.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/networkutils.h"
|
||||
#include "modeldatareader.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
@@ -16,6 +17,7 @@
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Network;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
@@ -40,6 +42,50 @@ namespace BlackCore
|
||||
return m_liveries;
|
||||
}
|
||||
|
||||
CLivery CModelDataReader::getLiveryForCombinedCode(const QString &combinedCode) const
|
||||
{
|
||||
if (!CLivery::isValidCombinedCode(combinedCode)) { return CLivery(); }
|
||||
CLiveryList liveries(getLiveries());
|
||||
return liveries.findByCombinedCode(combinedCode);
|
||||
}
|
||||
|
||||
CLivery CModelDataReader::getLiveryForDbKey(int id) const
|
||||
{
|
||||
if (id < 0) { return CLivery(); }
|
||||
CLiveryList liveries(getLiveries());
|
||||
return liveries.findByKey(id);
|
||||
}
|
||||
|
||||
CLivery CModelDataReader::smartLiverySelector(const CLivery &livery) const
|
||||
{
|
||||
CLiveryList liveries(getLiveries()); // thread safe copy
|
||||
|
||||
// first try on id, that would be perfect
|
||||
if (livery.hasValidDbKey())
|
||||
{
|
||||
int k = livery.getDbKey();
|
||||
CLivery l(liveries.findByKey(k));
|
||||
if (l.hasCompleteData()) { return l; }
|
||||
}
|
||||
|
||||
// by combined code
|
||||
if (livery.hasCombinedCode())
|
||||
{
|
||||
QString cc(livery.getCombinedCode());
|
||||
CLivery l(liveries.findByCombinedCode(cc));
|
||||
if (l.hasCompleteData()) { return l; }
|
||||
}
|
||||
|
||||
if (livery.hasValidAirlineDesignator())
|
||||
{
|
||||
QString icao(livery.getAirlineIcaoCodeDesignator());
|
||||
CLivery l(liveries.findByAirlineIcaoDesignatorStdLivery(icao));
|
||||
if (l.hasCompleteData()) { return l; }
|
||||
}
|
||||
|
||||
return CLivery();
|
||||
}
|
||||
|
||||
CDistributorList CModelDataReader::getDistributors() const
|
||||
{
|
||||
QReadLocker l(&m_lockDistributor);
|
||||
@@ -52,6 +98,20 @@ namespace BlackCore
|
||||
return m_models;
|
||||
}
|
||||
|
||||
CAircraftModel CModelDataReader::getModelForModelString(const QString &modelString) const
|
||||
{
|
||||
if (modelString.isEmpty()) { return CAircraftModel(); }
|
||||
CAircraftModelList models(getModels());
|
||||
return models.findFirstByModelString(modelString);
|
||||
}
|
||||
|
||||
CAircraftModelList CModelDataReader::getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode)
|
||||
{
|
||||
if (aircraftDesignator.isEmpty()) { return CAircraftModelList(); }
|
||||
CAircraftModelList models(getModels());
|
||||
return models.findByAircraftDesignatorAndLiveryCombinedCode(aircraftDesignator, combinedCode);
|
||||
}
|
||||
|
||||
int CModelDataReader::getLiveriesCount() const
|
||||
{
|
||||
QReadLocker l(&m_lockLivery);
|
||||
@@ -64,21 +124,45 @@ namespace BlackCore
|
||||
return m_distributors.size();
|
||||
}
|
||||
|
||||
CDistributor CModelDataReader::smartDistributorSelector(const CDistributor &distributor) const
|
||||
{
|
||||
CDistributorList distributors(getDistributors()); // thread safe copy
|
||||
if (distributor.hasValidDbKey())
|
||||
{
|
||||
QString k(distributor.getDbKey());
|
||||
CDistributor d(distributors.findByKey(k));
|
||||
if (d.hasCompleteData()) { return d; }
|
||||
|
||||
// more lenient search
|
||||
return distributors.findByIdOrAlias(k);
|
||||
}
|
||||
return CDistributor();
|
||||
}
|
||||
|
||||
int CModelDataReader::getModelsCount() const
|
||||
{
|
||||
QReadLocker l(&m_lockModels);
|
||||
return m_models.size();
|
||||
}
|
||||
|
||||
bool CModelDataReader::allRead() const
|
||||
bool CModelDataReader::areAllDataRead() const
|
||||
{
|
||||
return
|
||||
getLiveriesCount() > 0 &&
|
||||
getModelsCount() > 0 &&
|
||||
getDistributorsCount();
|
||||
getDistributorsCount() > 0;
|
||||
}
|
||||
|
||||
void CModelDataReader::ps_read()
|
||||
bool CModelDataReader::canConnect(QString &message) const
|
||||
{
|
||||
if (m_urlDistributors.isEmpty() || m_urlLiveries.isEmpty() || m_urlModels.isEmpty()) { return false; }
|
||||
bool cm = CNetworkUtils::canConnect(m_urlModels, message);
|
||||
|
||||
// currently only testing one URL, might be changed in the future
|
||||
return cm;
|
||||
}
|
||||
|
||||
void CModelDataReader::ps_read(CDbFlags::Entity entity)
|
||||
{
|
||||
this->threadAssertCheck();
|
||||
Q_ASSERT(this->m_networkManagerLivery);
|
||||
@@ -86,27 +170,30 @@ namespace BlackCore
|
||||
Q_ASSERT(this->m_networkManagerModel);
|
||||
Q_ASSERT(!m_urlLiveries.isEmpty());
|
||||
Q_ASSERT(!m_urlDistributors.isEmpty());
|
||||
QNetworkRequest requestLivery(m_urlLiveries);
|
||||
QNetworkRequest requestDistributor(m_urlDistributors);
|
||||
QNetworkRequest requestModel(m_urlModels);
|
||||
this->m_networkManagerLivery->get(requestLivery);
|
||||
this->m_networkManagerDistributor->get(requestDistributor);
|
||||
this->m_networkManagerModel->get(requestModel);
|
||||
}
|
||||
|
||||
QString CModelDataReader::getLiveryUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return buildUrl(protocol, server, baseUrl, "service/alllivery.php?rows=20000&sord=asc");
|
||||
}
|
||||
CDbFlags::Entity triggeredRead = CDbFlags::NoEntity;
|
||||
if (entity.testFlag(CDbFlags::LiveryEntity))
|
||||
{
|
||||
QNetworkRequest requestLivery(m_urlLiveries);
|
||||
this->m_networkManagerLivery->get(requestLivery);
|
||||
triggeredRead |= CDbFlags::LiveryEntity;
|
||||
}
|
||||
|
||||
QString CModelDataReader::getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return buildUrl(protocol, server, baseUrl, "service/alldistributor.php?rows=20000&sord=asc");
|
||||
}
|
||||
if (entity.testFlag(CDbFlags::DistributorEntity))
|
||||
{
|
||||
QNetworkRequest requestDistributor(m_urlDistributors);
|
||||
this->m_networkManagerDistributor->get(requestDistributor);
|
||||
triggeredRead |= CDbFlags::DistributorEntity;
|
||||
}
|
||||
|
||||
QString CModelDataReader::getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return buildUrl(protocol, server, baseUrl, "service/allaircraftmodel.php?rows=20000&sord=asc");
|
||||
if (entity.testFlag(CDbFlags::ModelEntity))
|
||||
{
|
||||
QNetworkRequest requestModel(m_urlModels);
|
||||
this->m_networkManagerModel->get(requestModel);
|
||||
triggeredRead |= CDbFlags::ModelEntity;
|
||||
}
|
||||
|
||||
emit readData(triggeredRead, CDbFlags::StartRead, 0);
|
||||
}
|
||||
|
||||
void CModelDataReader::ps_parseLiveryData(QNetworkReply *nwReplyPtr)
|
||||
@@ -114,55 +201,79 @@ namespace BlackCore
|
||||
// wrap pointer, make sure any exit cleans up reply
|
||||
// required to use delete later as object is created in a different thread
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
|
||||
if (array.isEmpty()) { return; }
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::LiveryEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CLiveryList liveries = CLiveryList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
int n;
|
||||
int n = 0;
|
||||
{
|
||||
QWriteLocker wl(&this->m_lockLivery);
|
||||
this->m_liveries = liveries;
|
||||
n = liveries.size();
|
||||
}
|
||||
emit readLiveries(n);
|
||||
if (allRead()) { emit readAll(); }
|
||||
emit readData(CDbFlags::LiveryEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
void CModelDataReader::ps_parseDistributorData(QNetworkReply *nwReplyPtr)
|
||||
{
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
|
||||
if (array.isEmpty()) { return; }
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::DistributorEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CDistributorList distributors = CDistributorList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
int n;
|
||||
int n = 0;
|
||||
{
|
||||
QWriteLocker wl(&this->m_lockDistributor);
|
||||
this->m_distributors = distributors;
|
||||
n = distributors.size();
|
||||
}
|
||||
emit readDistributors(n);
|
||||
if (allRead()) { emit readAll(); }
|
||||
emit readData(CDbFlags::DistributorEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
void CModelDataReader::ps_parseModelData(QNetworkReply *nwReplyPtr)
|
||||
{
|
||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
|
||||
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
|
||||
if (array.isEmpty()) { return; }
|
||||
QJsonArray array = this->transformReplyIntoDatastoreResponse(nwReply.data());
|
||||
if (array.isEmpty())
|
||||
{
|
||||
emit readData(CDbFlags::ModelEntity, CDbFlags::ReadFailed, 0);
|
||||
return;
|
||||
}
|
||||
CAircraftModelList models = CAircraftModelList::fromDatabaseJson(array);
|
||||
|
||||
// this part needs to be synchronized
|
||||
int n;
|
||||
int n = 0;
|
||||
{
|
||||
QWriteLocker wl(&this->m_lockModels);
|
||||
this->m_models = models;
|
||||
n = models.size();
|
||||
}
|
||||
emit readModels(n);
|
||||
if (allRead()) { emit readAll(); }
|
||||
emit readData(CDbFlags::ModelEntity, CDbFlags::ReadFinished, n);
|
||||
}
|
||||
|
||||
QString CModelDataReader::getLiveryUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonlivery.php");
|
||||
}
|
||||
|
||||
QString CModelDataReader::getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsondistributor.php");
|
||||
}
|
||||
|
||||
QString CModelDataReader::getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl)
|
||||
{
|
||||
return CNetworkUtils::buildUrl(protocol, server, baseUrl, "service/jsonaircraftmodel.php");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackcore/databasereader.h"
|
||||
#include "blackmisc/network/webdataservicesprovider.h"
|
||||
#include "blackmisc/aviation/liverylist.h"
|
||||
#include "blackmisc/simulation/distributorlist.h"
|
||||
#include "blackmisc/simulation/aircraftmodellist.h"
|
||||
@@ -38,6 +39,18 @@ namespace BlackCore
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CLiveryList getLiveries() const;
|
||||
|
||||
//! Get aircraft livery for code
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CLivery getLiveryForCombinedCode(const QString &combinedCode) const;
|
||||
|
||||
//! Get aircraft livery for id
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CLivery getLiveryForDbKey(int id) const;
|
||||
|
||||
//! Best match specified by livery
|
||||
//! \threadsafe
|
||||
BlackMisc::Aviation::CLivery smartLiverySelector(const BlackMisc::Aviation::CLivery &livery) const;
|
||||
|
||||
//! Get distributors (of models)
|
||||
//! \threadsafe
|
||||
BlackMisc::Simulation::CDistributorList getDistributors() const;
|
||||
@@ -46,6 +59,14 @@ namespace BlackCore
|
||||
//! \threadsafe
|
||||
BlackMisc::Simulation::CAircraftModelList getModels() const;
|
||||
|
||||
//! Get model for string
|
||||
//! \threadsafe
|
||||
BlackMisc::Simulation::CAircraftModel getModelForModelString(const QString &modelString) const;
|
||||
|
||||
//! Get model for designator/combined code
|
||||
//! \threadsafe
|
||||
BlackMisc::Simulation::CAircraftModelList getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode);
|
||||
|
||||
//! Get aircraft liveries count
|
||||
//! \threadsafe
|
||||
int getLiveriesCount() const;
|
||||
@@ -54,25 +75,27 @@ namespace BlackCore
|
||||
//! \threadsafe
|
||||
int getDistributorsCount() const;
|
||||
|
||||
//! Best match specified by distributor
|
||||
//! \threadsafe
|
||||
BlackMisc::Simulation::CDistributor smartDistributorSelector(const BlackMisc::Simulation::CDistributor &distributor) const;
|
||||
|
||||
//! Get models count
|
||||
//! \threadsafe
|
||||
int getModelsCount() const;
|
||||
|
||||
//! All data read
|
||||
bool allRead() const;
|
||||
//! All data read?
|
||||
//! \threadsafe
|
||||
bool areAllDataRead() const;
|
||||
|
||||
//! Can connect?
|
||||
virtual bool canConnect(QString &message) const override;
|
||||
|
||||
//! \copydoc CDatabaseReader::canConnect()
|
||||
using CDatabaseReader::canConnect;
|
||||
|
||||
signals:
|
||||
//! Liveries have been read
|
||||
void readLiveries(int number);
|
||||
|
||||
//! Distributors have been read
|
||||
void readDistributors(int number);
|
||||
|
||||
//! Models have been read
|
||||
void readModels(int number);
|
||||
|
||||
//! All data read
|
||||
void readAll();
|
||||
//! Combined read signal
|
||||
void readData(BlackMisc::Network::CDbFlags::Entity entity, BlackMisc::Network::CDbFlags::ReadState state, int number);
|
||||
|
||||
private slots:
|
||||
//! Liveries have been read
|
||||
@@ -85,7 +108,7 @@ namespace BlackCore
|
||||
void ps_parseModelData(QNetworkReply *nwReply);
|
||||
|
||||
//! Read / re-read data file
|
||||
void ps_read();
|
||||
void ps_read(BlackMisc::Network::CDbFlags::Entity entity = BlackMisc::Network::CDbFlags::DistributorLiveryModel);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_networkManagerLivery = nullptr;
|
||||
|
||||
@@ -1,287 +0,0 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackcore/web_datareader.h"
|
||||
#include "vatsimbookingreader.h"
|
||||
#include "vatsimdatafilereader.h"
|
||||
#include "vatsim_metar_reader.h"
|
||||
#include "icaodatareader.h"
|
||||
#include "modeldatareader.h"
|
||||
#include "global_reader_settings.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/worker.h"
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
|
||||
CWebDataReader::CWebDataReader(WebReader readerFlags, QObject *parent) :
|
||||
QObject(parent), m_readerFlags(readerFlags)
|
||||
{
|
||||
this->setObjectName("CWebDataReader");
|
||||
this->initReaders(readerFlags);
|
||||
}
|
||||
|
||||
QList<QMetaObject::Connection> CWebDataReader::connectVatsimDataSignals(std::function<void(int)> bookingsRead,
|
||||
std::function<void(int)> dataFileRead,
|
||||
std::function<void(int)> metarRead)
|
||||
{
|
||||
// bind does not allow to define connection type
|
||||
// so anything in its own thread will be sent with this thread affinity
|
||||
QList<QMetaObject::Connection> cl;
|
||||
|
||||
if (m_readerFlags.testFlag(VatsimBookingReader))
|
||||
{
|
||||
QMetaObject::Connection c1 = connect(this, &CWebDataReader::vatsimBookingsRead, bookingsRead);
|
||||
Q_ASSERT_X(c1, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c1);
|
||||
}
|
||||
|
||||
if (m_readerFlags.testFlag(VatsimDataReader))
|
||||
{
|
||||
QMetaObject::Connection c2 = connect(this, &CWebDataReader::vatsimDataFileRead, dataFileRead);
|
||||
Q_ASSERT_X(c2, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c2);
|
||||
}
|
||||
|
||||
if (m_readerFlags.testFlag(VatsimMetarReader))
|
||||
{
|
||||
QMetaObject::Connection c3 = connect(this, &CWebDataReader::vatsimMetarRead, metarRead);
|
||||
Q_ASSERT_X(c3, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c3);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
QList<QMetaObject::Connection> CWebDataReader::connectSwiftDatabaseSignals(
|
||||
QObject *receiver,
|
||||
std::function<void(int)> aircraftIcaoCodeRead, std::function<void(int)> airlineIcaoCodeRead,
|
||||
std::function<void(int)> liveriesRead, std::function<void(int)> distributorsRead,
|
||||
std::function<void(int)> modelsRead)
|
||||
{
|
||||
Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
|
||||
|
||||
// bind does not allow to define connection type
|
||||
// so anything in its own thread will be sent with this thread affinity
|
||||
QList<QMetaObject::Connection> cl;
|
||||
|
||||
if (m_readerFlags.testFlag(IcaoDataReader))
|
||||
{
|
||||
QMetaObject::Connection c1 = connect(this, &CWebDataReader::aircraftIcaoCodeRead, receiver, aircraftIcaoCodeRead);
|
||||
Q_ASSERT_X(c1, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c1);
|
||||
QMetaObject::Connection c2 = connect(this, &CWebDataReader::airlineIcaoCodeRead, receiver, airlineIcaoCodeRead);
|
||||
Q_ASSERT_X(c2, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c2);
|
||||
}
|
||||
|
||||
if (m_readerFlags.testFlag(ModelReader))
|
||||
{
|
||||
QMetaObject::Connection c1 = connect(this, &CWebDataReader::liveriesRead, receiver, liveriesRead);
|
||||
Q_ASSERT_X(c1, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c1);
|
||||
QMetaObject::Connection c2 = connect(this, &CWebDataReader::distributorsRead, receiver, distributorsRead);
|
||||
Q_ASSERT_X(c2, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c2);
|
||||
QMetaObject::Connection c3 = connect(this, &CWebDataReader::modelsRead, receiver, modelsRead);
|
||||
Q_ASSERT_X(c3, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c3);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
CServerList CWebDataReader::getVatsimFsdServers() const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getFsdServers(); }
|
||||
return CServerList();
|
||||
}
|
||||
|
||||
CServerList CWebDataReader::getVatsimVoiceServers() const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getVoiceServers(); }
|
||||
return CServerList();
|
||||
}
|
||||
|
||||
CDistributorList CWebDataReader::getDistributors() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getDistributors(); }
|
||||
return CDistributorList();
|
||||
}
|
||||
|
||||
CLiveryList CWebDataReader::getLiveries() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getLiveries(); }
|
||||
return CLiveryList();
|
||||
}
|
||||
|
||||
CAircraftModelList CWebDataReader::getModels() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getModels(); }
|
||||
return CAircraftModelList();
|
||||
}
|
||||
|
||||
CAircraftIcaoCodeList CWebDataReader::getAircraftIcaoCodes() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodes(); }
|
||||
return CAircraftIcaoCodeList();
|
||||
}
|
||||
|
||||
CAirlineIcaoCodeList CWebDataReader::getAirlineIcaoCodes() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodes(); }
|
||||
return CAirlineIcaoCodeList();
|
||||
}
|
||||
|
||||
void CWebDataReader::gracefulShutdown()
|
||||
{
|
||||
this->disconnect(); // all signals
|
||||
if (this->m_vatsimBookingReader) { this->m_vatsimBookingReader->requestStop(); this->m_vatsimBookingReader->quit(); }
|
||||
if (this->m_vatsimDataFileReader) { this->m_vatsimDataFileReader->requestStop(); this->m_vatsimDataFileReader->quit(); }
|
||||
if (this->m_vatsimMetarReader) { this->m_vatsimMetarReader->requestStop(); this->m_vatsimMetarReader->quit(); }
|
||||
}
|
||||
|
||||
const CLogCategoryList &CWebDataReader::getLogCategories()
|
||||
{
|
||||
static const BlackMisc::CLogCategoryList cats { CLogCategory("swift.datareader") };
|
||||
return cats;
|
||||
}
|
||||
|
||||
void CWebDataReader::initReaders(WebReader flags)
|
||||
{
|
||||
// 1. VATSIM bookings
|
||||
if (flags.testFlag(VatsimBookingReader))
|
||||
{
|
||||
this->m_vatsimBookingReader = new CVatsimBookingReader(this, CGlobalReaderSettings::instance().bookingsUrl());
|
||||
connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CWebDataReader::ps_receivedBookings);
|
||||
this->m_vatsimBookingReader->start();
|
||||
this->m_vatsimBookingReader->setInterval(3 * 60 * 1000);
|
||||
}
|
||||
|
||||
// 2. VATSIM data file
|
||||
if (flags.testFlag(VatsimDataReader))
|
||||
{
|
||||
this->m_vatsimDataFileReader = new CVatsimDataFileReader(this, CGlobalReaderSettings::instance().vatsimDataFileUrls());
|
||||
connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CWebDataReader::ps_dataFileRead);
|
||||
this->m_vatsimDataFileReader->start();
|
||||
this->m_vatsimDataFileReader->setInterval(90 * 1000);
|
||||
}
|
||||
|
||||
// 3. VATSIM metar
|
||||
if (flags.testFlag(VatsimMetarReader))
|
||||
{
|
||||
this->m_vatsimMetarReader = new CVatsimMetarReader(this, CGlobalReaderSettings::instance().vatsimMetarUrl());
|
||||
connect(this->m_vatsimMetarReader, &CVatsimMetarReader::metarUpdated, this, &CWebDataReader::ps_metarRead);
|
||||
this->m_vatsimMetarReader->start();
|
||||
this->m_vatsimMetarReader->setInterval(5 * 60 * 1000);
|
||||
}
|
||||
|
||||
// 4. ICAO data reader
|
||||
if (flags.testFlag(IcaoDataReader))
|
||||
{
|
||||
this->m_icaoDataReader = new CIcaoDataReader(this, CGlobalReaderSettings::instance().protocolIcaoReader(), CGlobalReaderSettings::instance().serverIcaoReader(), CGlobalReaderSettings::instance().baseUrlIcaoReader());
|
||||
connect(this->m_icaoDataReader, &CIcaoDataReader::readAircraftIcaoCodes, this, &CWebDataReader::ps_readAircraftIcaoCodes);
|
||||
connect(this->m_icaoDataReader, &CIcaoDataReader::readAirlinesIcaoCodes, this, &CWebDataReader::ps_readAirlinesIcaoCodes);
|
||||
this->m_icaoDataReader->start();
|
||||
}
|
||||
|
||||
// 5. Model reader
|
||||
if (flags.testFlag(ModelReader))
|
||||
{
|
||||
this->m_modelDataReader = new CModelDataReader(this, CGlobalReaderSettings::instance().protocolModelReader(), CGlobalReaderSettings::instance().serverModelReader(), CGlobalReaderSettings::instance().baseUrlModelReader());
|
||||
connect(this->m_modelDataReader, &CModelDataReader::readLiveries, this, &CWebDataReader::ps_readLiveries);
|
||||
connect(this->m_modelDataReader, &CModelDataReader::readDistributors, this, &CWebDataReader::ps_readDistributors);
|
||||
connect(this->m_modelDataReader, &CModelDataReader::readModels, this, &CWebDataReader::ps_readModels);
|
||||
this->m_modelDataReader->start();
|
||||
}
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_receivedBookings(const CAtcStationList &stations)
|
||||
{
|
||||
CLogMessage(this).info("Read bookings from network");
|
||||
emit vatsimBookingsRead(stations.size());
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_dataFileRead(int lines)
|
||||
{
|
||||
CLogMessage(this).info("Read VATSIM data file, %1 lines") << lines;
|
||||
emit vatsimDataFileRead(lines);
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_metarRead(const BlackMisc::Weather::CMetarSet &metars)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 VATSIM metar stations") << metars.size();
|
||||
emit vatsimMetarRead(metars.size());
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_readAircraftIcaoCodes(int number)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 aircraft ICAO codes") << number;
|
||||
emit aircraftIcaoCodeRead(number);
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_readAirlinesIcaoCodes(int number)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 airline ICAO codes") << number;
|
||||
emit airlineIcaoCodeRead(number);
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_readLiveries(int number)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 liveries") << number;
|
||||
emit liveriesRead(number);
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_readDistributors(int number)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 distributors") << number;
|
||||
emit distributorsRead(number);
|
||||
}
|
||||
|
||||
void CWebDataReader::ps_readModels(int number)
|
||||
{
|
||||
CLogMessage(this).info("Read %1 models") << number;
|
||||
emit modelsRead(number);
|
||||
}
|
||||
|
||||
void CWebDataReader::readAllInBackground(int delayMs)
|
||||
{
|
||||
if (delayMs > 100)
|
||||
{
|
||||
BlackMisc::singleShot(delayMs, QThread::currentThread(), [ = ]()
|
||||
{
|
||||
this->readAllInBackground(0);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->m_vatsimBookingReader) {this->m_vatsimBookingReader->readInBackgroundThread(); }
|
||||
if (this->m_vatsimDataFileReader) this->m_vatsimDataFileReader->readInBackgroundThread();
|
||||
if (this->m_vatsimMetarReader) this->m_vatsimMetarReader->readInBackgroundThread();
|
||||
if (this->m_icaoDataReader) { this->m_icaoDataReader->readInBackgroundThread(); }
|
||||
if (this->m_modelDataReader) { this->m_modelDataReader->readInBackgroundThread(); }
|
||||
}
|
||||
|
||||
void CWebDataReader::readAtcBookingsInBackground() const
|
||||
{
|
||||
if (!this->m_vatsimBookingReader) { return; }
|
||||
this->m_vatsimBookingReader->readInBackgroundThread();
|
||||
}
|
||||
|
||||
void CWebDataReader::readModelDataInBackground() const
|
||||
{
|
||||
if (!this->m_modelDataReader) { return; }
|
||||
this->m_modelDataReader->readInBackgroundThread();
|
||||
}
|
||||
|
||||
} // ns
|
||||
@@ -1,188 +0,0 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKCORE_WEB_DATAREADER_H
|
||||
#define BLACKCORE_WEB_DATAREADER_H
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackmisc/logcategorylist.h"
|
||||
#include "blackmisc/aviation/atcstationlist.h"
|
||||
#include "blackmisc/aviation/liverylist.h"
|
||||
#include "blackmisc/aviation/airlineicaocodelist.h"
|
||||
#include "blackmisc/aviation/aircrafticaocodelist.h"
|
||||
#include "blackmisc/network/serverlist.h"
|
||||
#include "blackmisc/simulation/distributorlist.h"
|
||||
#include "blackmisc/weather/metarset.h"
|
||||
#include <QObject>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
class CVatsimBookingReader;
|
||||
class CVatsimDataFileReader;
|
||||
class CIcaoDataReader;
|
||||
class CModelDataReader;
|
||||
class CVatsimMetarReader;
|
||||
|
||||
/**
|
||||
* Encapsulates reading data from web sources
|
||||
*/
|
||||
class BLACKCORE_EXPORT CWebDataReader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//! \todo Qt5.5: Make use of QFlags
|
||||
enum WebReaderFlags
|
||||
{
|
||||
None = 0,
|
||||
VatsimBookingReader = 1 << 0,
|
||||
VatsimDataReader = 1 << 1,
|
||||
VatsimMetarReader = 1 << 2,
|
||||
IcaoDataReader = 1 << 3,
|
||||
ModelReader = 1 << 4,
|
||||
AllVatsimReaders = VatsimBookingReader | VatsimDataReader | VatsimMetarReader,
|
||||
AllSwiftDbReaders = IcaoDataReader | ModelReader,
|
||||
AllReaders = 0xFFFF
|
||||
};
|
||||
Q_DECLARE_FLAGS(WebReader, WebReaderFlags)
|
||||
|
||||
//! Constructor
|
||||
CWebDataReader(WebReader readerFlags, QObject *parent = nullptr);
|
||||
|
||||
//! Shutdown
|
||||
void gracefulShutdown();
|
||||
|
||||
//! Relay signals for VATSIM data
|
||||
QList<QMetaObject::Connection> connectVatsimDataSignals(std::function<void(int)> bookingsRead,
|
||||
std::function<void(int)> dataFileRead,
|
||||
std::function<void(int)> metarRead);
|
||||
|
||||
//! Relay signals for swift data
|
||||
QList<QMetaObject::Connection> connectSwiftDatabaseSignals(
|
||||
QObject *receiver,
|
||||
std::function<void(int)> aircraftIcaoCodeRead, std::function<void(int)> airlineIcaoCodeRead,
|
||||
std::function<void(int)> liveriesRead, std::function<void(int)> distributorsRead,
|
||||
std::function<void(int)> modelsRead);
|
||||
|
||||
//! \copydoc CVatsimDataFileReader::getVatsimFsdServers
|
||||
BlackMisc::Network::CServerList getVatsimFsdServers() const;
|
||||
|
||||
//! \copydoc CVatsimDataFileReader::getVatsimVoiceServers
|
||||
BlackMisc::Network::CServerList getVatsimVoiceServers() const;
|
||||
|
||||
//! \copydoc CModelDataReader::getDistributors
|
||||
BlackMisc::Simulation::CDistributorList getDistributors() const;
|
||||
|
||||
//! \copydoc CModelDataReader::getLiveries
|
||||
BlackMisc::Aviation::CLiveryList getLiveries() const;
|
||||
|
||||
//! \copydoc CModelDataReader::getModels
|
||||
BlackMisc::Simulation::CAircraftModelList getModels() const;
|
||||
|
||||
//! \copydoc CIcaoDataReader::getAircraftIcaoCodes
|
||||
BlackMisc::Aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const;
|
||||
|
||||
//! \copydoc CIcaoDataReader::getAirlineIcaoCodes
|
||||
BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const;
|
||||
|
||||
//! Read ATC bookings
|
||||
void readAtcBookingsInBackground() const;
|
||||
|
||||
//! Read liveries
|
||||
void readModelDataInBackground() const;
|
||||
|
||||
//! Booking reader
|
||||
CVatsimBookingReader *getBookingReader() const { return m_vatsimBookingReader; }
|
||||
|
||||
//! Data file reader
|
||||
CVatsimDataFileReader *getDataFileReader() const { return m_vatsimDataFileReader; }
|
||||
|
||||
//! Metar reader
|
||||
CVatsimMetarReader *getMetarReader() const { return m_vatsimMetarReader; }
|
||||
|
||||
//! Reader flags
|
||||
WebReader getReaderFlags() const { return m_readerFlags; }
|
||||
|
||||
//! Log categories
|
||||
static const BlackMisc::CLogCategoryList &getLogCategories();
|
||||
|
||||
public slots:
|
||||
//! First read (allows to immediately read in background)
|
||||
void readAllInBackground(int delayMs);
|
||||
|
||||
signals:
|
||||
//! Data file read
|
||||
void vatsimDataFileRead(int lines);
|
||||
|
||||
//! Bookings read
|
||||
void vatsimBookingsRead(int number);
|
||||
|
||||
//! Metars read
|
||||
void vatsimMetarRead(int number);
|
||||
|
||||
//! ICAO codes read
|
||||
void aircraftIcaoCodeRead(int number);
|
||||
|
||||
//! ICAO codes read
|
||||
void airlineIcaoCodeRead(int number);
|
||||
|
||||
//! Liveries read
|
||||
void liveriesRead(int number);
|
||||
|
||||
//! Distributors read
|
||||
void distributorsRead(int number);
|
||||
|
||||
//! Models read
|
||||
void modelsRead(int number);
|
||||
|
||||
private slots:
|
||||
//! ATC bookings received
|
||||
void ps_receivedBookings(const BlackMisc::Aviation::CAtcStationList &bookedStations);
|
||||
|
||||
//! Data file has been read
|
||||
void ps_dataFileRead(int lines);
|
||||
|
||||
//! Metars have been read
|
||||
void ps_metarRead(const BlackMisc::Weather::CMetarSet &metars);
|
||||
|
||||
//! Read ICAO codes
|
||||
void ps_readAircraftIcaoCodes(int number);
|
||||
|
||||
//! Read ICAO codes
|
||||
void ps_readAirlinesIcaoCodes(int number);
|
||||
|
||||
//! Read liveries
|
||||
void ps_readLiveries(int number);
|
||||
|
||||
//! Read distributors
|
||||
void ps_readDistributors(int number);
|
||||
|
||||
//! Read models
|
||||
void ps_readModels(int number);
|
||||
|
||||
private:
|
||||
//! Init the readers
|
||||
void initReaders(WebReader flags);
|
||||
|
||||
WebReader m_readerFlags = None; //!< which readers are available
|
||||
|
||||
// for reading XML and VATSIM data files
|
||||
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
|
||||
CVatsimDataFileReader *m_vatsimDataFileReader = nullptr;
|
||||
CVatsimMetarReader *m_vatsimMetarReader = nullptr;
|
||||
CIcaoDataReader *m_icaoDataReader = nullptr;
|
||||
CModelDataReader *m_modelDataReader = nullptr;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackCore::CWebDataReader::WebReader)
|
||||
|
||||
#endif
|
||||
447
src/blackcore/webdataservices.cpp
Normal file
447
src/blackcore/webdataservices.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "blackcore/webdataservices.h"
|
||||
#include "blackcore/modeldatareader.h"
|
||||
#include "blackcore/databasewriter.h"
|
||||
#include "vatsimbookingreader.h"
|
||||
#include "vatsimdatafilereader.h"
|
||||
#include "icaodatareader.h"
|
||||
#include "settings/global_reader_settings.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/worker.h"
|
||||
|
||||
using namespace BlackCore::Settings;
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::Simulation;
|
||||
using namespace BlackMisc::Network;
|
||||
using namespace BlackMisc::Aviation;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
CWebDataServices::CWebDataServices(CWebReaderFlags::WebReader readerFlags, QObject *parent) :
|
||||
QObject(parent), m_readerFlags(readerFlags)
|
||||
{
|
||||
this->setObjectName("CWebDataReader");
|
||||
this->initReaders(readerFlags);
|
||||
this->initWriters();
|
||||
}
|
||||
|
||||
QList<QMetaObject::Connection> CWebDataServices::connectVatsimDataSignals(QObject *receiver, std::function<void(int)> bookingsRead, std::function<void(int)> dataFileRead)
|
||||
{
|
||||
// bind does not allow to define connection type
|
||||
// so anything in its own thread will be sent with this thread affinity
|
||||
Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
|
||||
QList<QMetaObject::Connection> cl;
|
||||
|
||||
if (m_readerFlags.testFlag(CWebReaderFlags::WebReaderFlags::VatsimBookingReader))
|
||||
{
|
||||
QMetaObject::Connection c1 = connect(this, &CWebDataServices::vatsimBookingsRead, receiver, bookingsRead);
|
||||
Q_ASSERT_X(c1, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c1);
|
||||
}
|
||||
|
||||
if (m_readerFlags.testFlag(CWebReaderFlags::WebReaderFlags::VatsimDataReader))
|
||||
{
|
||||
QMetaObject::Connection c2 = connect(this, &CWebDataServices::vatsimDataFileRead, receiver, dataFileRead);
|
||||
Q_ASSERT_X(c2, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(c2);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
QList<QMetaObject::Connection> CWebDataServices::connectSwiftDatabaseSignals(QObject *receiver, std::function<void(CDbFlags::Entity, CDbFlags::ReadState, int)> dataRead)
|
||||
{
|
||||
Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
|
||||
|
||||
// bind does not allow to define connection type
|
||||
// so anything in its own thread will be sent with this thread affinity
|
||||
QList<QMetaObject::Connection> cl;
|
||||
|
||||
if (m_readerFlags.testFlag(CWebReaderFlags::WebReaderFlags::IcaoDataReader))
|
||||
{
|
||||
Q_ASSERT_X(this->m_icaoDataReader, Q_FUNC_INFO, "Missing reader");
|
||||
QMetaObject::Connection con = connect(this->m_icaoDataReader, &CIcaoDataReader::readData, receiver, dataRead);
|
||||
Q_ASSERT_X(con, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(con);
|
||||
}
|
||||
|
||||
if (m_readerFlags.testFlag(CWebReaderFlags::WebReaderFlags::ModelReader))
|
||||
{
|
||||
Q_ASSERT_X(this->m_modelDataReader, Q_FUNC_INFO, "Missing reader");
|
||||
QMetaObject::Connection con = connect(this->m_modelDataReader, &CModelDataReader::readData, receiver, dataRead);
|
||||
Q_ASSERT_X(con, Q_FUNC_INFO, "connect failed");
|
||||
cl.append(con);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
CServerList CWebDataServices::getVatsimFsdServers() const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getFsdServers(); }
|
||||
return CServerList();
|
||||
}
|
||||
|
||||
CServerList CWebDataServices::getVatsimVoiceServers() const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getVoiceServers(); }
|
||||
return CServerList();
|
||||
}
|
||||
|
||||
CUserList CWebDataServices::getUsersForCallsign(const CCallsign &callsign) const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getUsersForCallsign(callsign); }
|
||||
return CUserList();
|
||||
}
|
||||
|
||||
CAtcStationList CWebDataServices::getAtcStationsForCallsign(const CCallsign &callsign) const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getAtcStationsForCallsign(callsign); }
|
||||
return CAtcStationList();
|
||||
}
|
||||
|
||||
CVoiceCapabilities CWebDataServices::getVoiceCapabilityForCallsign(const CCallsign &callsign) const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { return m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign); }
|
||||
return CVoiceCapabilities();
|
||||
}
|
||||
|
||||
void CWebDataServices::updateWithVatsimDataFileData(CSimulatedAircraft &aircraftToBeUdpated) const
|
||||
{
|
||||
if (m_vatsimDataFileReader) { m_vatsimDataFileReader->updateWithVatsimDataFileData(aircraftToBeUdpated); }
|
||||
}
|
||||
|
||||
CStatusMessageList CWebDataServices::asyncWriteModel(CAircraftModel &model) const
|
||||
{
|
||||
if (m_databaseWriter) { return m_databaseWriter->asyncWriteModel(model);}
|
||||
return CStatusMessageList();
|
||||
}
|
||||
|
||||
bool CWebDataServices::canConnectSwiftDb() const
|
||||
{
|
||||
if (!m_icaoDataReader && !m_modelDataReader) { return false; }
|
||||
if (m_icaoDataReader)
|
||||
{
|
||||
if (!m_icaoDataReader->canConnect()) { return false; }
|
||||
}
|
||||
if (m_modelDataReader)
|
||||
{
|
||||
if (!m_modelDataReader->canConnect()) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CDbFlags::Entity CWebDataServices::triggerRead(CDbFlags::Entity whatToRead)
|
||||
{
|
||||
CDbFlags::Entity triggeredRead = CDbFlags::NoEntity;
|
||||
if (m_vatsimDataFileReader)
|
||||
{
|
||||
if (whatToRead.testFlag(CDbFlags::VatsimDataFile))
|
||||
{
|
||||
m_vatsimDataFileReader->readInBackgroundThread();
|
||||
triggeredRead |= CDbFlags::VatsimDataFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_vatsimBookingReader)
|
||||
{
|
||||
if (whatToRead.testFlag(CDbFlags::VatsimBookings))
|
||||
{
|
||||
m_vatsimBookingReader->readInBackgroundThread();
|
||||
triggeredRead |= CDbFlags::VatsimBookings;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_icaoDataReader)
|
||||
{
|
||||
if (whatToRead.testFlag(CDbFlags::AircraftIcaoEntity) || whatToRead.testFlag(CDbFlags::AirlineIcaoEntity) || whatToRead.testFlag(CDbFlags::CountryEntity))
|
||||
{
|
||||
CDbFlags::Entity icaoEntities = whatToRead & CDbFlags::AllIcaoAndCountries;
|
||||
m_icaoDataReader->readInBackgroundThread(icaoEntities);
|
||||
triggeredRead |= icaoEntities;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_modelDataReader)
|
||||
{
|
||||
if (whatToRead.testFlag(CDbFlags::LiveryEntity) || whatToRead.testFlag(CDbFlags::DistributorEntity) || whatToRead.testFlag(CDbFlags::ModelEntity))
|
||||
{
|
||||
CDbFlags::Entity modelEntities = whatToRead & CDbFlags::DistributorLiveryModel;
|
||||
m_modelDataReader->readInBackgroundThread(modelEntities);
|
||||
triggeredRead |= modelEntities;
|
||||
}
|
||||
}
|
||||
return triggeredRead;
|
||||
}
|
||||
|
||||
CDistributorList CWebDataServices::getDistributors() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getDistributors(); }
|
||||
return CDistributorList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getDistributorsCount() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getDistributorsCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDistributor CWebDataServices::smartDistributorSelector(const CDistributor &distributor) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->smartDistributorSelector(distributor); }
|
||||
return CDistributor();
|
||||
}
|
||||
|
||||
CLiveryList CWebDataServices::getLiveries() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getLiveries(); }
|
||||
return CLiveryList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getLiveriesCount() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getLiveriesCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLivery CWebDataServices::getLiveryForCombinedCode(const QString &combinedCode) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getLiveryForCombinedCode(combinedCode); }
|
||||
return CLivery();
|
||||
}
|
||||
|
||||
CLivery CWebDataServices::getLiveryForDbKey(int id) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getLiveryForDbKey(id); }
|
||||
return CLivery();
|
||||
}
|
||||
|
||||
CLivery CWebDataServices::smartLiverySelector(const CLivery &livery) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->smartLiverySelector(livery); }
|
||||
return livery;
|
||||
}
|
||||
|
||||
CAircraftModelList CWebDataServices::getModels() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getModels(); }
|
||||
return CAircraftModelList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getModelsCount() const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getModelsCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAircraftModelList CWebDataServices::getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getModelsForAircraftDesignatorAndLiveryCombinedCode(aircraftDesignator, combinedCode); }
|
||||
return CAircraftModelList();
|
||||
}
|
||||
|
||||
CAircraftModel CWebDataServices::getModelForModelString(const QString &modelString) const
|
||||
{
|
||||
if (m_modelDataReader) { return m_modelDataReader->getModelForModelString(modelString); }
|
||||
return CAircraftModel();
|
||||
}
|
||||
|
||||
CAircraftIcaoCodeList CWebDataServices::getAircraftIcaoCodes() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodes(); }
|
||||
return CAircraftIcaoCodeList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getAircraftIcaoCodesCount() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodesCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CWebDataServices::getAircraftIcaoCodeForDesignator(const QString &designator) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDesignator(designator); }
|
||||
return CAircraftIcaoCode();
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CWebDataServices::getAircraftIcaoCodeForDbKey(int key) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAircraftIcaoCodeForDbKey(key); }
|
||||
return CAircraftIcaoCode();
|
||||
}
|
||||
|
||||
CAircraftIcaoCode CWebDataServices::smartAircraftIcaoSelector(const CAircraftIcaoCode &icao) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->smartAircraftIcaoSelector(icao); }
|
||||
return icao;
|
||||
}
|
||||
|
||||
CAirlineIcaoCodeList CWebDataServices::getAirlineIcaoCodes() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodes(); }
|
||||
return CAirlineIcaoCodeList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getAirlineIcaoCodesCount() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodesCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAirlineIcaoCode CWebDataServices::getAirlineIcaoCodeForDbKey(int key) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDbKey(key); }
|
||||
return CAirlineIcaoCode();
|
||||
}
|
||||
|
||||
CCountryList CWebDataServices::getCountries() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getCountries(); }
|
||||
return CCountryList();
|
||||
}
|
||||
|
||||
int CWebDataServices::getCountriesCount() const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getCountriesCount(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
CCountry CWebDataServices::getCountryForName(const QString &name) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getCountryForName(name); }
|
||||
return CCountry();
|
||||
}
|
||||
|
||||
CCountry CWebDataServices::getCountryForIsoCode(const QString &iso) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getCountryForIsoCode(iso); }
|
||||
return CCountry();
|
||||
}
|
||||
|
||||
CAirlineIcaoCode CWebDataServices::getAirlineIcaoCodeForDesignator(const QString &designator) const
|
||||
{
|
||||
if (m_icaoDataReader) { return m_icaoDataReader->getAirlineIcaoCodeForDesignator(designator); }
|
||||
return CAirlineIcaoCode();
|
||||
}
|
||||
|
||||
void CWebDataServices::gracefulShutdown()
|
||||
{
|
||||
this->disconnect(); // all signals
|
||||
if (this->m_vatsimBookingReader) { this->m_vatsimBookingReader->gracefulShutdown(); }
|
||||
if (this->m_vatsimDataFileReader) { this->m_vatsimDataFileReader->gracefulShutdown(); }
|
||||
if (this->m_modelDataReader) { this->m_modelDataReader->gracefulShutdown(); }
|
||||
if (this->m_icaoDataReader) { this->m_icaoDataReader->gracefulShutdown(); }
|
||||
if (this->m_databaseWriter) { this->m_databaseWriter->gracefulShutdown(); }
|
||||
}
|
||||
|
||||
const CLogCategoryList &CWebDataServices::getLogCategories()
|
||||
{
|
||||
static const BlackMisc::CLogCategoryList cats { CLogCategory("swift.datareader") };
|
||||
return cats;
|
||||
}
|
||||
|
||||
void CWebDataServices::initReaders(CWebReaderFlags::WebReader flags)
|
||||
{
|
||||
// 1. VATSIM bookings
|
||||
if (flags.testFlag(CWebReaderFlags::WebReaderFlags::VatsimBookingReader))
|
||||
{
|
||||
this->m_vatsimBookingReader = new CVatsimBookingReader(this, CGlobalReaderSettings::instance().bookingsUrl());
|
||||
bool c = connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CWebDataServices::ps_receivedBookings);
|
||||
Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM reader signals");
|
||||
Q_UNUSED(c);
|
||||
this->m_vatsimBookingReader->start();
|
||||
this->m_vatsimBookingReader->setInterval(3 * 60 * 1000);
|
||||
}
|
||||
|
||||
// 2. VATSIM data file
|
||||
if (flags.testFlag(CWebReaderFlags::WebReaderFlags::VatsimDataReader))
|
||||
{
|
||||
this->m_vatsimDataFileReader = new CVatsimDataFileReader(this, CGlobalReaderSettings::instance().vatsimDataFileUrls());
|
||||
bool c = connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CWebDataServices::ps_dataFileRead);
|
||||
Q_ASSERT_X(c, Q_FUNC_INFO, "VATSIM reader signals");
|
||||
Q_UNUSED(c);
|
||||
this->m_vatsimDataFileReader->start();
|
||||
this->m_vatsimDataFileReader->setInterval(90 * 1000);
|
||||
}
|
||||
|
||||
// 3. ICAO data reader
|
||||
if (flags.testFlag(CWebReaderFlags::WebReaderFlags::IcaoDataReader))
|
||||
{
|
||||
bool c;
|
||||
this->m_icaoDataReader = new CIcaoDataReader(this, CGlobalReaderSettings::instance().protocolIcaoReader(), CGlobalReaderSettings::instance().serverIcaoReader(), CGlobalReaderSettings::instance().baseUrlIcaoReader());
|
||||
c = connect(this->m_icaoDataReader, &CIcaoDataReader::readData, this, &CWebDataServices::ps_readFromSwiftDb);
|
||||
Q_ASSERT_X(c, Q_FUNC_INFO, "ICAO reader signals");
|
||||
Q_UNUSED(c);
|
||||
this->m_icaoDataReader->start();
|
||||
}
|
||||
|
||||
// 4. Model reader
|
||||
if (flags.testFlag(CWebReaderFlags::WebReaderFlags::ModelReader))
|
||||
{
|
||||
this->m_modelDataReader = new CModelDataReader(this, CGlobalReaderSettings::instance().protocolModelReader(), CGlobalReaderSettings::instance().serverModelReader(), CGlobalReaderSettings::instance().baseUrlModelReader());
|
||||
bool c = connect(this->m_modelDataReader, &CModelDataReader::readData, this, &CWebDataServices::ps_readFromSwiftDb);
|
||||
Q_ASSERT_X(c, Q_FUNC_INFO, "Model reader signals");
|
||||
Q_UNUSED(c);
|
||||
this->m_modelDataReader->start();
|
||||
}
|
||||
}
|
||||
|
||||
void CWebDataServices::initWriters()
|
||||
{
|
||||
this->m_databaseWriter = new CDatabaseWriter(
|
||||
CGlobalReaderSettings::instance().protocolModelReader(),
|
||||
CGlobalReaderSettings::instance().serverModelReader(),
|
||||
CGlobalReaderSettings::instance().baseUrlModelReader(),
|
||||
this);
|
||||
}
|
||||
|
||||
void CWebDataServices::ps_receivedBookings(const CAtcStationList &stations)
|
||||
{
|
||||
CLogMessage(this).info("Read bookings from network");
|
||||
emit vatsimBookingsRead(stations.size());
|
||||
}
|
||||
|
||||
void CWebDataServices::ps_dataFileRead(int lines)
|
||||
{
|
||||
CLogMessage(this).info("Read VATSIM data file, %1 lines") << lines;
|
||||
emit vatsimDataFileRead(lines);
|
||||
}
|
||||
|
||||
void CWebDataServices::ps_readFromSwiftDb(CDbFlags::Entity entity, CDbFlags::ReadState state, int number)
|
||||
{
|
||||
CLogMessage(this).info("Read data %1 %3 %2") << CDbFlags::flagToString(entity) << number << CDbFlags::flagToString(state);
|
||||
emit readSwiftDbData(entity, state, number);
|
||||
}
|
||||
|
||||
void CWebDataServices::readAllInBackground(int delayMs)
|
||||
{
|
||||
if (delayMs > 100)
|
||||
{
|
||||
BlackMisc::singleShot(delayMs, QThread::currentThread(), [ = ]()
|
||||
{
|
||||
this->readAllInBackground(0);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// only readers requested will be read
|
||||
if (this->m_vatsimBookingReader) {this->m_vatsimBookingReader->readInBackgroundThread(); }
|
||||
if (this->m_vatsimDataFileReader) this->m_vatsimDataFileReader->readInBackgroundThread();
|
||||
if (this->m_icaoDataReader) { this->m_icaoDataReader->readInBackgroundThread(CDbFlags::AllIcaoAndCountries); }
|
||||
if (this->m_modelDataReader) { this->m_modelDataReader->readInBackgroundThread(CDbFlags::DistributorLiveryModel); }
|
||||
}
|
||||
}
|
||||
|
||||
void CWebDataServices::readAtcBookingsInBackground() const
|
||||
{
|
||||
if (!this->m_vatsimBookingReader) { return; }
|
||||
this->m_vatsimBookingReader->readInBackgroundThread();
|
||||
}
|
||||
|
||||
} // ns
|
||||
266
src/blackcore/webdataservices.h
Normal file
266
src/blackcore/webdataservices.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKCORE_WEB_DATASERVICES_H
|
||||
#define BLACKCORE_WEB_DATASERVICES_H
|
||||
|
||||
#include "blackcore/blackcoreexport.h"
|
||||
#include "blackcore/webreaderflags.h"
|
||||
#include "blackmisc/aviation/atcstationlist.h"
|
||||
#include "blackmisc/aviation/liverylist.h"
|
||||
#include "blackmisc/aviation/airlineicaocodelist.h"
|
||||
#include "blackmisc/aviation/aircrafticaocodelist.h"
|
||||
#include "blackmisc/network/serverlist.h"
|
||||
#include "blackmisc/network/voicecapabilities.h"
|
||||
#include "blackmisc/network/webdataservicesprovider.h"
|
||||
#include "blackmisc/simulation/distributorlist.h"
|
||||
#include "blackmisc/logcategorylist.h"
|
||||
#include "blackmisc/countrylist.h"
|
||||
#include <QObject>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
class CVatsimBookingReader;
|
||||
class CVatsimDataFileReader;
|
||||
class CIcaoDataReader;
|
||||
class CModelDataReader;
|
||||
class CDatabaseWriter;
|
||||
|
||||
/*!
|
||||
* Encapsulates reading data from web sources
|
||||
*/
|
||||
class BLACKCORE_EXPORT CWebDataServices :
|
||||
public QObject,
|
||||
public BlackMisc::Network::IWebDataServicesProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(BlackMisc::Network::IWebDataServicesProvider)
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
CWebDataServices(CWebReaderFlags::WebReader readerFlags, QObject *parent = nullptr);
|
||||
|
||||
//! Shutdown
|
||||
void gracefulShutdown();
|
||||
|
||||
//! Read ATC bookings
|
||||
void readAtcBookingsInBackground() const;
|
||||
|
||||
//! Booking reader
|
||||
CVatsimBookingReader *getBookingReader() const { return m_vatsimBookingReader; }
|
||||
|
||||
//! Data file reader
|
||||
CVatsimDataFileReader *getDataFileReader() const { return m_vatsimDataFileReader; }
|
||||
|
||||
//! Reader flags
|
||||
CWebReaderFlags::WebReader getReaderFlags() const { return m_readerFlags; }
|
||||
|
||||
//! Log categories
|
||||
static const BlackMisc::CLogCategoryList &getLogCategories();
|
||||
|
||||
// ------------------------ provider functionality ------------------------------
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::connectVatsimDataSignals
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual QList<QMetaObject::Connection> connectVatsimDataSignals(
|
||||
QObject *receiver,
|
||||
std::function<void(int)> bookingsRead, std::function<void(int)> dataFileRead) override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::connectSwiftDatabaseSignals
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual QList<QMetaObject::Connection> connectSwiftDatabaseSignals(
|
||||
QObject *receiver,
|
||||
std::function<void (BlackMisc::Network::CDbFlags::Entity, BlackMisc::Network::CDbFlags::ReadState, int)> dataRead) override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::connectSwiftDatabaseSignals
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Network::CDbFlags::Entity triggerRead(BlackMisc::Network::CDbFlags::Entity whatToRead) override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getVatsimFsdServers
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Network::CServerList getVatsimFsdServers() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getVatsimVoiceServers
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Network::CServerList getVatsimVoiceServers() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getDistributors
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Simulation::CDistributorList getDistributors() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getDistributorsCount
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getDistributorsCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::smartDistributorSelector
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Simulation::CDistributor smartDistributorSelector(const BlackMisc::Simulation::CDistributor &distributor) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getLiveries
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CLiveryList getLiveries() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getLiveriesCount
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getLiveriesCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getLiveryForCombinedCode
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CLivery getLiveryForCombinedCode(const QString &combinedCode) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getLiveryForDbKey
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CLivery getLiveryForDbKey(int id) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::smartLiverySelector
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CLivery smartLiverySelector(const BlackMisc::Aviation::CLivery &livery) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getModels
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Simulation::CAircraftModelList getModels() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getModelsCount
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getModelsCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getModelsForAircraftDesignatorAndLiveryCombinedCode
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Simulation::CAircraftModelList getModelsForAircraftDesignatorAndLiveryCombinedCode(const QString &aircraftDesignator, const QString &combinedCode) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getModelForModelString
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Simulation::CAircraftModel getModelForModelString(const QString &modelString) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAircraftIcaoCodes
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAircraftIcaoCodesCount
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getAircraftIcaoCodesCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAircraftIcaoCodeForDesignator
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDesignator(const QString &designator) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAircraftIcaoCodeForDbKey
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int key) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAircraftIcaoCodeForDbKey
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const BlackMisc::Aviation::CAircraftIcaoCode &icao) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAirlineIcaoCodes
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAirlineIcaoCodesCount
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getAirlineIcaoCodesCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAirlineIcaoCodeForDbKey
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDbKey(int key) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAirlineIcaoCodeForDesignator
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAirlineIcaoCode getAirlineIcaoCodeForDesignator(const QString &designator) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getCountries
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::CCountryList getCountries() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getCountries
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual int getCountriesCount() const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getCountryForName
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::CCountry getCountryForName(const QString &name) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getCountryForIsoCode
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::CCountry getCountryForIsoCode(const QString &iso) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getUsersForCallsign
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Network::CUserList getUsersForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getAtcStationsForCallsign
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Aviation::CAtcStationList getAtcStationsForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::getVoiceCapabilityForCallsign
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::Network::CVoiceCapabilities getVoiceCapabilityForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::updateWithWebData
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual void updateWithVatsimDataFileData(BlackMisc::Simulation::CSimulatedAircraft &aircraftToBeUdpated) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::asyncWriteModel
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual BlackMisc::CStatusMessageList asyncWriteModel(BlackMisc::Simulation::CAircraftModel &model) const override;
|
||||
|
||||
//! \copydoc IWebDataReaderProvider::canConnectSwiftDb
|
||||
//! \ingroup webdatareaderprovider
|
||||
virtual bool canConnectSwiftDb() const override;
|
||||
|
||||
public slots:
|
||||
//! First read (allows to immediately read in background)
|
||||
void readAllInBackground(int delayMs);
|
||||
|
||||
signals:
|
||||
//! Data file read
|
||||
void vatsimDataFileRead(int lines);
|
||||
|
||||
//! Bookings read
|
||||
void vatsimBookingsRead(int number);
|
||||
|
||||
//! Combined read signal
|
||||
void readSwiftDbData(BlackMisc::Network::CDbFlags::Entity entity, BlackMisc::Network::CDbFlags::ReadState state, int number);
|
||||
|
||||
//! Model has been written
|
||||
void modelWritten(const BlackMisc::Simulation::CAircraftModel &model);
|
||||
|
||||
private slots:
|
||||
//! ATC bookings received
|
||||
void ps_receivedBookings(const BlackMisc::Aviation::CAtcStationList &bookedStations);
|
||||
|
||||
//! Data file has been read
|
||||
void ps_dataFileRead(int lines);
|
||||
|
||||
//! Read from model reader
|
||||
void ps_readFromSwiftDb(BlackMisc::Network::CDbFlags::Entity entity, BlackMisc::Network::CDbFlags::ReadState state, int number);
|
||||
|
||||
private:
|
||||
//! Init the readers
|
||||
void initReaders(CWebReaderFlags::WebReader flags);
|
||||
|
||||
//! Init the writers
|
||||
void initWriters();
|
||||
|
||||
CWebReaderFlags::WebReader m_readerFlags = CWebReaderFlags::WebReaderFlags::None; //!< which readers are available
|
||||
|
||||
// for reading XML and VATSIM data files
|
||||
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
|
||||
CVatsimDataFileReader *m_vatsimDataFileReader = nullptr;
|
||||
CIcaoDataReader *m_icaoDataReader = nullptr;
|
||||
CModelDataReader *m_modelDataReader = nullptr;
|
||||
|
||||
// writing objects directly into DB
|
||||
CDatabaseWriter *m_databaseWriter = nullptr;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
55
src/blackcore/webreaderflags.cpp
Normal file
55
src/blackcore/webreaderflags.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "webreaderflags.h"
|
||||
|
||||
using namespace BlackMisc::Network;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
CWebReaderFlags::WebReader CWebReaderFlags::entityToReader(CDbFlags::Entity entity)
|
||||
{
|
||||
WebReader f = None;
|
||||
if (entity.testFlag(CDbFlags::AircraftIcaoEntity) ||
|
||||
entity.testFlag(CDbFlags::AirlineIcaoEntity) ||
|
||||
entity.testFlag(CDbFlags::CountryEntity))
|
||||
{
|
||||
f |= IcaoDataReader;
|
||||
}
|
||||
|
||||
if (entity.testFlag(CDbFlags::ModelEntity) ||
|
||||
entity.testFlag(CDbFlags::DistributorEntity) ||
|
||||
entity.testFlag(CDbFlags::LiveryEntity))
|
||||
{
|
||||
f |= ModelReader;
|
||||
}
|
||||
|
||||
if (entity.testFlag(CDbFlags::VatsimBookings))
|
||||
{
|
||||
f |= VatsimBookingReader;
|
||||
}
|
||||
|
||||
if (entity.testFlag(CDbFlags::VatsimDataFile))
|
||||
{
|
||||
f |= VatsimDataReader;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
bool CWebReaderFlags::isFromSwiftDb(CDbFlags::Entity entity)
|
||||
{
|
||||
return isFromSwiftDb(entityToReader(entity));
|
||||
}
|
||||
|
||||
bool CWebReaderFlags::isFromSwiftDb(WebReader reader)
|
||||
{
|
||||
return reader.testFlag(ModelReader) || reader.testFlag(IcaoDataReader);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
57
src/blackcore/webreaderflags.h
Normal file
57
src/blackcore/webreaderflags.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright (C) 2015
|
||||
* swift project Community / Contributors
|
||||
*
|
||||
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||
* contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
//! \file
|
||||
|
||||
#include "blackcoreexport.h"
|
||||
#include "blackmisc/network/dbflags.h"
|
||||
#include <QFlags>
|
||||
#include <QMetaType>
|
||||
|
||||
#ifndef BLACKCORE_CWEBREADERFLAGS_H
|
||||
#define BLACKCORE_CWEBREADERFLAGS_H
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
/*!
|
||||
* Flags reg. the web readers
|
||||
*/
|
||||
class BLACKCORE_EXPORT CWebReaderFlags
|
||||
{
|
||||
public:
|
||||
//! Which readers to init
|
||||
enum WebReaderFlags
|
||||
{
|
||||
None = 0, ///< no reader at all
|
||||
VatsimBookingReader = 1 << 0, ///< reader for VATSIM booking data
|
||||
VatsimDataReader = 1 << 1, ///< reader for VATSIM data
|
||||
IcaoDataReader = 1 << 2, ///< reader for ICAO data
|
||||
ModelReader = 1 << 3, ///< reader for model data such as liveries, models, ..
|
||||
AllVatsimReaders = VatsimBookingReader | VatsimDataReader, ///< all readers
|
||||
AllSwiftDbReaders = IcaoDataReader | ModelReader, ///< all swift data
|
||||
AllReaders = AllSwiftDbReaders | AllVatsimReaders ///< everything
|
||||
};
|
||||
Q_DECLARE_FLAGS(WebReader, WebReaderFlags)
|
||||
|
||||
//! Relationship between reader and entity
|
||||
static WebReader entityToReader(BlackMisc::Network::CDbFlags::Entity entity);
|
||||
|
||||
//! Read from swift DB
|
||||
static bool isFromSwiftDb(BlackMisc::Network::CDbFlags::Entity entity);
|
||||
|
||||
//! Read from swift DB
|
||||
static bool isFromSwiftDb(WebReader reader);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE(BlackCore::CWebReaderFlags::WebReaderFlags)
|
||||
Q_DECLARE_METATYPE(BlackCore::CWebReaderFlags::WebReader)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackCore::CWebReaderFlags::WebReader)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user