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:
Klaus Basan
2015-09-23 19:05:31 +02:00
committed by Mathew Sutcliffe
parent 33330394a9
commit 07c6370819
15 changed files with 1538 additions and 586 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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);
};
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View 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

View 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

View 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

View 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