refs #445, encapsulated web service based reading in CWebDataReader

* the reader will be used in context, but can also be used standalone (ie mapping GUI) GUI
* adjustments in context/airspace as required
** for web reader
** livery
* base class for database based reading (via JSON/web)
* model data reader for models
This commit is contained in:
Klaus Basan
2015-07-10 01:03:11 +02:00
committed by Mathew Sutcliffe
parent 6ccc23fb32
commit c760f1d424
24 changed files with 1197 additions and 202 deletions

View File

@@ -9,6 +9,9 @@
#include "airspace_monitor.h"
#include "blackcore/blackcorefreefunctions.h"
#include "blackcore/web_datareader.h"
#include "blackcore/vatsimbookingreader.h"
#include "blackcore/vatsimdatafilereader.h"
#include "blackmisc/project.h"
#include "blackmisc/testing.h"
#include "blackmisc/logmessage.h"
@@ -26,10 +29,10 @@ using namespace BlackMisc::PhysicalQuantities;
namespace BlackCore
{
CAirspaceMonitor::CAirspaceMonitor(QObject *parent, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile)
CAirspaceMonitor::CAirspaceMonitor(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, INetwork *network, CWebDataReader *webDataReader, QObject *parent)
: QObject(parent),
COwnAircraftAware(ownAircraftProvider),
m_network(network), m_vatsimBookingReader(bookings), m_vatsimDataFileReader(dataFile),
m_network(network), m_webDataReader(webDataReader),
m_analyzer(new CAirspaceAnalyzer(ownAircraftProvider, this, network, this))
{
this->setObjectName("CAirspaceMonitor");
@@ -55,8 +58,8 @@ namespace BlackCore
this->connect(&m_interimPositionUpdateTimer, &QTimer::timeout, this, &CAirspaceMonitor::ps_sendInterimPositions);
// AutoConnection: this should also avoid race conditions by updating the bookings
this->connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CAirspaceMonitor::ps_receivedBookings);
this->connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CAirspaceMonitor::ps_receivedDataFile);
this->connect(this->m_webDataReader->getBookingReader(), &CVatsimBookingReader::dataRead, this, &CAirspaceMonitor::ps_receivedBookings);
this->connect(this->m_webDataReader->getDataFileReader(), &CVatsimDataFileReader::dataRead, this, &CAirspaceMonitor::ps_receivedDataFile);
// Force snapshot in the main event loop
this->connect(this->m_analyzer, &CAirspaceAnalyzer::airspaceAircraftSnapshot, this, &CAirspaceMonitor::airspaceAircraftSnapshot, Qt::QueuedConnection);
@@ -287,7 +290,7 @@ namespace BlackCore
// those are the ones not in range
for (const CCallsign &callsign : searchList)
{
CUserList usersByCallsign = this->m_vatsimDataFileReader->getUsersForCallsign(callsign);
CUserList usersByCallsign = this->m_webDataReader->getDataFileReader()->getUsersForCallsign(callsign);
if (usersByCallsign.isEmpty())
{
CUser user;
@@ -438,13 +441,13 @@ namespace BlackCore
void CAirspaceMonitor::ps_realNameReplyReceived(const CCallsign &callsign, const QString &realname)
{
Q_ASSERT(this->m_vatsimDataFileReader);
Q_ASSERT(this->m_webDataReader->getDataFileReader());
if (!this->m_connected || realname.isEmpty()) { return; }
CPropertyIndexVariantMap vm({CAtcStation::IndexController, CUser::IndexRealName}, realname);
this->m_atcStationsOnline.applyIf(&CAtcStation::getCallsign, callsign, vm);
this->m_atcStationsBooked.applyIf(&CAtcStation::getCallsign, callsign, vm);
CVoiceCapabilities caps = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign);
CVoiceCapabilities caps = this->m_webDataReader->getDataFileReader()->getVoiceCapabilityForCallsign(callsign);
vm = CPropertyIndexVariantMap({CAircraft::IndexPilot, CUser::IndexRealName}, realname);
vm.addValue({ CSimulatedAircraft::IndexClient, CClient::IndexUser, CUser::IndexRealName }, realname);
vm.addValue({ CSimulatedAircraft::IndexClient, CClient::IndexVoiceCapabilities }, caps);
@@ -472,7 +475,7 @@ namespace BlackCore
capabilities.addValue(CClient::FsdWithAircraftConfig, (flags & INetwork::SupportsAircraftConfigs));
CPropertyIndexVariantMap vm(CClient::IndexCapabilities, CVariant::from(capabilities));
CVoiceCapabilities caps = m_vatsimDataFileReader->getVoiceCapabilityForCallsign(callsign);
CVoiceCapabilities caps = m_webDataReader->getDataFileReader()->getVoiceCapabilityForCallsign(callsign);
vm.addValue({CClient::IndexVoiceCapabilities}, caps);
if (!this->m_otherClients.containsCallsign(callsign)) { this->m_otherClients.push_back(CClient(callsign)); }
this->m_otherClients.applyIf(&CClient::getCallsign, callsign, vm);
@@ -634,7 +637,7 @@ namespace BlackCore
for (auto client = this->m_otherClients.begin(); client != this->m_otherClients.end(); ++client)
{
if (client->hasSpecifiedVoiceCapabilities()) { continue; } // we already have voice caps
CVoiceCapabilities vc = this->m_vatsimDataFileReader->getVoiceCapabilityForCallsign(client->getCallsign());
CVoiceCapabilities vc = this->m_webDataReader->getDataFileReader()->getVoiceCapabilityForCallsign(client->getCallsign());
if (vc.isUnknown()) { continue; }
client->setVoiceCapabilities(vc);
}
@@ -683,7 +686,7 @@ namespace BlackCore
if (stationsWithCallsign.isEmpty())
{
// new station, init with data from data file
CAtcStation station(this->m_vatsimDataFileReader->getAtcStationsForCallsign(callsign).frontOrDefault());
CAtcStation station(this->m_webDataReader->getDataFileReader()->getAtcStationsForCallsign(callsign).frontOrDefault());
station.setCallsign(callsign);
station.setRange(range);
station.setFrequency(frequency);
@@ -819,7 +822,7 @@ namespace BlackCore
{
// empty so far, try to fetch from data file
CLogMessage(this).warning("Empty ICAO info for %1 %2") << callsign.toQString() << icaoData.toQString();
CAircraftIcaoData icaoDataFromDataFile = this->m_vatsimDataFileReader->getIcaoInfo(callsign);
CAircraftIcaoData icaoDataFromDataFile = this->m_webDataReader->getDataFileReader()->getIcaoInfo(callsign);
if (!icaoDataFromDataFile.hasAircraftDesignator()) { return; } // give up!
vm = CPropertyIndexVariantMap(CAircraft::IndexIcao, CVariant::from(icaoDataFromDataFile));
}
@@ -873,7 +876,7 @@ namespace BlackCore
setIcao = true;
}
this->m_vatsimDataFileReader->updateWithVatsimDataFileData(aircraft);
this->m_webDataReader->getDataFileReader()->updateWithVatsimDataFileData(aircraft);
// only place where aircraft is added
this->m_aircraftInRange.push_back(aircraft);

View File

@@ -14,8 +14,6 @@
#include "blackcore/blackcoreexport.h"
#include "blackcore/network.h"
#include "blackcore/vatsimbookingreader.h"
#include "blackcore/vatsimdatafilereader.h"
#include "airspace_analyzer.h"
#include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/simulation/ownaircraftprovider.h"
@@ -29,6 +27,7 @@
namespace BlackCore
{
class CWebDataReader;
//! Keeps track of other entities in the airspace: aircraft, ATC stations, etc.
//! Central instance of data for \sa IRemoteAircraftProvider.
@@ -42,7 +41,7 @@ namespace BlackCore
public:
//! Constructor
CAirspaceMonitor(QObject *parent, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraft, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile);
CAirspaceMonitor(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraft, INetwork *network, CWebDataReader *webDataReader, QObject *parent);
//! \copydoc IRemoteAircraftProvider::getAircraftInRange
//! \ingroup remoteaircraftprovider
@@ -212,12 +211,11 @@ namespace BlackCore
BlackMisc::Aviation::CCallsignSet m_aircraftSupportingParts; //!< aircraft supporting parts
QMap<BlackMisc::Aviation::CAirportIcaoCode, BlackMisc::Aviation::CInformationMessage> m_metarCache;
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CFlightPlan> m_flightPlanCache;
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CFlightPlan> m_flightPlanCache;
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftIcaoData> m_icaoCodeCache;
INetwork *m_network = nullptr;
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
CVatsimDataFileReader *m_vatsimDataFileReader = nullptr;
CWebDataReader *m_webDataReader = nullptr;
CAirspaceAnalyzer *m_analyzer = nullptr; //!< owned analyzer
bool m_serverSupportsNameQuery = false; //!< not all servers support name query
bool m_connected = false; //!< retrieve data

View File

@@ -15,6 +15,12 @@ using namespace BlackMisc;
namespace BlackCore
{
const CLogCategoryList &CContext::getLogCategories()
{
static const BlackMisc::CLogCategoryList cats { BlackMisc::CLogCategory::context() };
return cats;
}
IContextNetwork *CContext::getIContextNetwork()
{
return this->getRuntime()->getIContextNetwork();

View File

@@ -28,12 +28,8 @@ namespace BlackCore
//! Destructor
~CContext() {}
//! Log category
static const BlackMisc::CLogCategoryList &getLogCategories()
{
static const BlackMisc::CLogCategoryList cats { BlackMisc::CLogCategory::context() };
return cats;
}
//! Log categories
static const BlackMisc::CLogCategoryList &getLogCategories();
//! Using local implementing object?
bool isUsingImplementingObject() const

View File

@@ -116,12 +116,6 @@ namespace BlackCore
//! Terminated connection
void connectionTerminated();
//! VATSIM data file was read
void vatsimDataFileRead();
//! Bookings read
void vatsimBookingsRead();
//! Connection status changed
//! \param from old status
//! \param to new status
@@ -138,8 +132,30 @@ namespace BlackCore
//! Text message sent (by me)
void textMessageSent(const BlackMisc::Network::CTextMessage &sentMessage);
public slots:
// --------------------------- data readers -------------------------------
//! Data file read
void vatsimDataFileRead(int lines);
//! Bookings read
void vatsimBookingsRead(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);
//! Number of models read
void modelsRead(int number);
public slots:
//! Reload bookings from booking service
virtual void readAtcBookingsFromSource() const = 0;

View File

@@ -14,10 +14,8 @@
#include "context_simulator.h"
#include "context_ownaircraft_impl.h"
#include "network_vatlib.h"
#include "vatsimbookingreader.h"
#include "vatsimdatafilereader.h"
#include "icaodatareader.h"
#include "airspace_monitor.h"
#include "web_datareader.h"
#include "blackmisc/networkutils.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/logmessage.h"
@@ -41,6 +39,7 @@ namespace BlackCore
IContextNetwork(mode, runtime)
{
Q_ASSERT(this->getRuntime());
Q_ASSERT(this->getIContextSettings());
Q_ASSERT(this->getIContextOwnAircraft());
Q_ASSERT(this->getIContextOwnAircraft()->isUsingImplementingObject());
@@ -51,38 +50,31 @@ namespace BlackCore
connect(this->m_network, &INetwork::textMessagesReceived, this, &CContextNetwork::ps_checkForSupervisiorTextMessage);
connect(this->m_network, &INetwork::textMessageSent, this, &CContextNetwork::textMessageSent);
// 2. VATSIM bookings
this->m_vatsimBookingReader = new CVatsimBookingReader(this);
connect(this->m_vatsimBookingReader, &CVatsimBookingReader::dataRead, this, &CContextNetwork::ps_receivedBookings);
this->m_vatsimBookingReader->start();
this->m_vatsimBookingReader->setInterval(180 * 1000);
this->m_vatsimBookingReader->readInBackgroundThread(); // first read
// 3. VATSIM data file
const QStringList dataFileUrls = { "http://info.vroute.net/vatsim-data.txt" };
this->m_vatsimDataFileReader = new CVatsimDataFileReader(this, dataFileUrls);
connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CContextNetwork::ps_dataFileRead);
this->m_vatsimDataFileReader->start();
this->m_vatsimDataFileReader->readInBackgroundThread(); // first read
this->m_vatsimDataFileReader->setInterval(90 * 1000);
// 4. ICAO data reader
this->m_icaoDataReader = new CIcaoDataReader(this,
"http://vatrep.vatsim-germany.org/service/allaircrafticao.php?rows=20000&sord=asc",
"http://vatrep.vatsim-germany.org/service/allairlineicao.php?rows=20000&sord=asc");
connect(this->m_icaoDataReader, &CIcaoDataReader::readAircraftIcaoCodes, this, &CContextNetwork::ps_readAircraftIcaoCodes);
connect(this->m_icaoDataReader, &CIcaoDataReader::readAirlinesIcaoCodes, this, &CContextNetwork::ps_readAirlinesIcaoCodes);
this->m_icaoDataReader->start();
this->m_icaoDataReader->readInBackgroundThread();
// 5. Update timer for data (network data such as frequency)
// 2. Update timer for data (network data such as frequency)
this->m_dataUpdateTimer = new QTimer(this);
connect(this->m_dataUpdateTimer, &QTimer::timeout, this, &CContextNetwork::requestDataUpdates);
this->m_dataUpdateTimer->start(30 * 1000);
// 6. Airspace contents
// 3. data reader
this->m_webDataReader = new CWebDataReader(CWebDataReader::AllReaders, this);
this->m_webReaderSignalConnections = this->m_webDataReader->connectVatsimDataSignals(
std::bind(&CContextNetwork::vatsimBookingsRead, this, std::placeholders::_1),
std::bind(&CContextNetwork::vatsimDataFileRead, this, std::placeholders::_1));
this->m_webReaderSignalConnections.append(
this->m_webDataReader->connectSwiftDatabaseSignals(
this, // the object here must be the same as in the bind
std::bind(&CContextNetwork::aircraftIcaoCodeRead, this, std::placeholders::_1),
std::bind(&CContextNetwork::airlineIcaoCodeRead, this, std::placeholders::_1),
std::bind(&CContextNetwork::liveriesRead, this, std::placeholders::_1),
std::bind(&CContextNetwork::distributorsRead, this, std::placeholders::_1),
std::bind(&CContextNetwork::modelsRead, this, std::placeholders::_1)
));
this->m_webDataReader->readAllInBackground(1000);
// 4. Airspace contents
Q_ASSERT_X(this->getRuntime()->getCContextOwnAircraft(), Q_FUNC_INFO, "this and own aircraft context must be local");
this->m_airspace = new CAirspaceMonitor(this, this->getRuntime()->getCContextOwnAircraft(), this->m_network, this->m_vatsimBookingReader, this->m_vatsimDataFileReader);
Q_ASSERT_X(this->m_webDataReader, Q_FUNC_INFO, "Missing reader");
this->m_airspace = new CAirspaceMonitor(this->getRuntime()->getCContextOwnAircraft(), this->m_network, this->m_webDataReader, this);
connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationsOnline, this, &CContextNetwork::changedAtcStationsOnline);
connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationsBooked, this, &CContextNetwork::changedAtcStationsBooked);
connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationOnlineConnectionStatus, this, &CContextNetwork::changedAtcStationOnlineConnectionStatus);
@@ -147,8 +139,9 @@ namespace BlackCore
void CContextNetwork::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(); }
this->m_webReaderSignalConnections.clear(); // disconnect
this->m_webDataReader->gracefulShutdown();
if (this->isConnected()) { this->disconnectFromNetwork(); }
if (this->m_airspace) { this->m_airspace->gracefulShutdown(); }
}
@@ -203,14 +196,9 @@ namespace BlackCore
CServer CContextNetwork::getConnectedServer() const
{
if (this->isConnected())
{
return this->m_network->getPresetServer();
}
else
{
return CServer();
}
return this->isConnected() ?
this->m_network->getPresetServer() :
CServer();
}
CStatusMessage CContextNetwork::disconnectFromNetwork()
@@ -392,19 +380,16 @@ namespace BlackCore
CServerList CContextNetwork::getVatsimFsdServers() const
{
Q_ASSERT_X(this->m_webDataReader, Q_FUNC_INFO, "Missing data reader");
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
Q_ASSERT(this->m_vatsimDataFileReader);
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
return this->m_vatsimDataFileReader->getFsdServers();
return this->m_webDataReader->getVatsimFsdServers();
}
CServerList CContextNetwork::getVatsimVoiceServers() const
{
Q_ASSERT_X(this->m_webDataReader, Q_FUNC_INFO, "Missing data reader");
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
Q_ASSERT(this->m_vatsimDataFileReader);
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
return this->m_vatsimDataFileReader->getVoiceServers();
return this->m_webDataReader->getVatsimVoiceServers();
}
void CContextNetwork::ps_fsdConnectionStatusChanged(INetwork::ConnectionStatus from, INetwork::ConnectionStatus to)
@@ -455,25 +440,6 @@ namespace BlackCore
m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, enabled, maxAircraft, maxRenderedDistance, maxRenderedBoundary);
}
void CContextNetwork::ps_dataFileRead(int lines)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read VATSIM data file, %1 lines") << lines;
emit vatsimDataFileRead();
}
void CContextNetwork::ps_readAircraftIcaoCodes(int number)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read %1 aircraft ICAO codes") << number;
}
void CContextNetwork::ps_readAirlinesIcaoCodes(int number)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read %1 airline ICAO codes") << number;
}
void CContextNetwork::ps_checkForSupervisiorTextMessage(const CTextMessageList &messages)
{
if (messages.containsPrivateMessages())
@@ -493,13 +459,6 @@ namespace BlackCore
return this->getRuntime()->getCContextOwnAircraft()->getOwnAircraft();
}
void CContextNetwork::readAtcBookingsFromSource() const
{
Q_ASSERT(this->m_vatsimBookingReader);
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
this->m_vatsimBookingReader->readInBackgroundThread();
}
CAtcStationList CContextNetwork::getAtcStationsOnline() const
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
@@ -536,13 +495,6 @@ namespace BlackCore
return this->m_airspace->getAtcStationsOnline().findFirstByCallsign(callsign);
}
void CContextNetwork::ps_receivedBookings(const CAtcStationList &)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read bookings from network");
emit vatsimBookingsRead();
}
void CContextNetwork::requestDataUpdates()
{
Q_ASSERT(this->m_network);
@@ -599,6 +551,13 @@ namespace BlackCore
return c;
}
void CContextNetwork::readAtcBookingsFromSource() const
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
Q_ASSERT_X(this->m_webDataReader, Q_FUNC_INFO, "missing reader");
this->m_webDataReader->readAtcBookingsInBackground();
}
bool CContextNetwork::updateAircraftRendered(const CCallsign &callsign, bool rendered, const CIdentifier &originator)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign << rendered << originator; }

View File

@@ -21,6 +21,7 @@
#include "blackmisc/simulation/remoteaircraftprovider.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/aircraftsituationlist.h"
#include "blackmisc/setnetwork.h"
#include "blackmisc/network/clientlist.h"
#include "blackmisc/digestsignal.h"
#include "blackmisc/logmessage.h"
@@ -31,9 +32,7 @@
namespace BlackCore
{
class CAirspaceMonitor;
class CVatsimBookingReader;
class CVatsimDataFileReader;
class CIcaoDataReader;
class CWebDataReader;
//! Network context implementation
class BLACKCORE_EXPORT CContextNetwork :
@@ -232,37 +231,22 @@ namespace BlackCore
CContextNetwork *registerWithDBus(CDBusServer *server);
private:
CAirspaceMonitor *m_airspace = nullptr;
BlackCore::INetwork *m_network = nullptr;
CAirspaceMonitor *m_airspace = nullptr;
INetwork *m_network = nullptr;
CWebDataReader *m_webDataReader = nullptr; //!< web service readers
QList<QMetaObject::Connection> m_webReaderSignalConnections;
INetwork::ConnectionStatus m_currentStatus = INetwork::Disconnected; //!< used to detect pending connections
QTimer *m_dataUpdateTimer = nullptr; //!< general updates such as ATIS, frequencies, see requestDataUpdates()
// Digest signals, only sending after some time
BlackMisc::CDigestSignal m_dsAtcStationsBookedChanged { this, &IContextNetwork::changedAtcStationsBooked, &IContextNetwork::changedAtcStationsBookedDigest, 750, 2 };
BlackMisc::CDigestSignal m_dsAtcStationsOnlineChanged { this, &IContextNetwork::changedAtcStationsOnline, &IContextNetwork::changedAtcStationsOnlineDigest, 750, 4 };
BlackMisc::CDigestSignal m_dsAircraftsInRangeChanged { this, &IContextNetwork::changedAircraftInRange, &IContextNetwork::changedAircraftInRangeDigest, 750, 4 };
// for reading XML and VATSIM data files
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
CVatsimDataFileReader *m_vatsimDataFileReader = nullptr;
CIcaoDataReader *m_icaoDataReader = nullptr;
QTimer *m_dataUpdateTimer = nullptr; //!< general updates such as ATIS, frequencies, see requestDataUpdates()
//! Own aircraft from \sa CContextOwnAircraft
const BlackMisc::Simulation::CSimulatedAircraft ownAircraft() const;
private slots:
//! ATC bookings received
void ps_receivedBookings(const BlackMisc::Aviation::CAtcStationList &bookedStations);
//! Data file has been read
void ps_dataFileRead(int lines);
//! Read ICAO codes
void ps_readAircraftIcaoCodes(int number);
//! Read ICAO codes
void ps_readAirlinesIcaoCodes(int number);
//! Check if a supervisor message was received
void ps_checkForSupervisiorTextMessage(const BlackMisc::Network::CTextMessageList &messages);
@@ -272,7 +256,6 @@ namespace BlackCore
//! Render restrictions have been changed, used with analyzer
//! \sa CAirspaceAnalyzer
void ps_simulatorRenderRestrictionsChanged(bool restricted, bool enabled, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
};
} // ns

View File

@@ -96,8 +96,7 @@ namespace BlackCore
this->m_ownAircraft.setIcaoInfo(
CAircraftIcaoData(
CAircraftIcaoCode("C172", "L1P"),
CAirlineIcaoCode(),
"0000ff")
CAirlineIcaoCode())
);
}

View File

@@ -418,6 +418,7 @@ namespace BlackCore
}
Q_ASSERT_X(!listener->parent(), Q_FUNC_INFO, "Objects with parent cannot be moved to thread");
listener->setProperty("isInitialized", true);
listener->moveToThread(&m_listenersThread);
}

View File

@@ -0,0 +1,71 @@
/* 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 "databasereader.h"
#include "blackmisc/logmessage.h"
using namespace BlackMisc;
namespace BlackCore
{
CDatabaseReader::CDatabaseReader(QObject *owner, const QString &name) :
BlackMisc::CThreadedReader(owner, name)
{ }
void CDatabaseReader::readInBackgroundThread()
{
bool s = QMetaObject::invokeMethod(this, "ps_read");
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
Q_UNUSED(s);
}
QJsonArray CDatabaseReader::transformReplyIntoJsonArray(QNetworkReply *nwReply) const
{
this->threadAssertCheck();
QJsonArray array;
if (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
}
if (nwReply->error() == QNetworkReply::NoError)
{
const QString dataFileData = nwReply->readAll();
nwReply->close(); // close asap
if (dataFileData.isEmpty()) { return array; }
QJsonDocument jsonResponse = QJsonDocument::fromJson(dataFileData.toUtf8());
QJsonObject jsonObject = jsonResponse.object();
QJsonArray jsonArray = jsonObject["rows"].toArray();
return jsonArray;
}
CLogMessage(this).warning("Reading data failed %1 %2") << nwReply->errorString() << nwReply->url().toString();
nwReply->abort();
return array;
}
QString CDatabaseReader::buildUrl(const QString &protocol, const QString &server, const QString &baseUrl, const QString &serviceUrl)
{
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;
}
} // namespace

View File

@@ -0,0 +1,45 @@
/* 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_READER_H
#define BLACKCORE_DATABASE_READER_H
//! \file
#include "blackcore/blackcoreexport.h"
#include "blackmisc/threadedreader.h"
#include <QNetworkReply>
#include <QJsonArray>
namespace BlackCore
{
//! Support for threaded based reading and parsing tasks such
//! as data files via http, or file system and parsing (such as FSX models)
class BLACKCORE_EXPORT CDatabaseReader : public BlackMisc::CThreadedReader
{
Q_OBJECT
public:
//! Start reading in own thread
void readInBackgroundThread();
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);
};
} // namespace
#endif // guard

View File

@@ -18,9 +18,9 @@ using namespace BlackMisc::Aviation;
namespace BlackCore
{
CIcaoDataReader::CIcaoDataReader(QObject *owner, const QString &aircraftIcaoUrl, const QString &airlineIcaoUrl) :
CThreadedReader(owner, "CIcaoDataReader"),
m_urlAircraftIcao(aircraftIcaoUrl), m_urlAirlineIcao(airlineIcaoUrl)
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))
{
this->m_networkManagerAircraft = new QNetworkAccessManager(this);
this->m_networkManagerAirlines = new QNetworkAccessManager(this);
@@ -41,11 +41,26 @@ namespace BlackCore
return m_airlineIcaos;
}
void CIcaoDataReader::readInBackgroundThread()
int CIcaoDataReader::getAircraftIcaoCodesCount() const
{
bool s = QMetaObject::invokeMethod(this, "ps_read");
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
Q_UNUSED(s);
QReadLocker l(&m_lockAircraft);
return m_aircraftIcaos.size();
}
int CIcaoDataReader::getAirlineIcaoCodesCount() const
{
QReadLocker l(&m_lockAirline);
return m_airlineIcaos.size();
}
QString CIcaoDataReader::getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
{
return buildUrl(protocol, server, baseUrl, "service/allaircrafticao.php?rows=20000&sord=asc");
}
QString CIcaoDataReader::getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl)
{
return buildUrl(protocol, server, baseUrl, "service/allairlineicao.php?rows=20000&sord=asc");
}
void CIcaoDataReader::ps_read()
@@ -61,47 +76,12 @@ namespace BlackCore
this->m_networkManagerAirlines->get(requestAirline);
}
QJsonArray CIcaoDataReader::splitReplyIntoArray(QNetworkReply *nwReply) const
{
this->threadAssertCheck();
QJsonArray array;
if (this->isFinished())
{
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated ICAO data parsing process"); // for users
return array; // stop, terminate straight away, ending thread
}
if (nwReply->error() == QNetworkReply::NoError)
{
const QString dataFileData = nwReply->readAll();
nwReply->close(); // close asap
if (dataFileData.isEmpty()) { return array; }
QJsonDocument jsonResponse = QJsonDocument::fromJson(dataFileData.toUtf8());
QJsonObject jsonObject = jsonResponse.object();
QJsonArray jsonArray = jsonObject["rows"].toArray();
return jsonArray;
}
CLogMessage(this).warning("Reading data failed %1 %2") << nwReply->errorString() << nwReply->url().toString();
nwReply->abort();
return array;
}
bool BlackCore::CIcaoDataReader::checkIfFinished() const
{
if (!this->isFinished()) { return false; }
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated ICAO data parsing process"); // for users
return true;
}
void CIcaoDataReader::ps_parseAircraftIcaoData(QNetworkReply *nwReplyPtr)
{
// 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->splitReplyIntoArray(nwReply.data());
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
if (array.isEmpty()) { return; }
CAircraftIcaoCodeList codes = CAircraftIcaoCodeList::fromDatabaseJson(array);
@@ -113,12 +93,13 @@ namespace BlackCore
n = codes.size();
}
emit readAircraftIcaoCodes(n);
if (this->getAirlineIcaoCodesCount() > 0) { emit readAll(); }
}
void CIcaoDataReader::ps_parseAirlineIcaoData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->splitReplyIntoArray(nwReply.data());
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
if (array.isEmpty()) { return; }
CAirlineIcaoCodeList codes = CAirlineIcaoCodeList::fromDatabaseJson(array);
@@ -130,6 +111,6 @@ namespace BlackCore
n = codes.size();
}
emit readAirlinesIcaoCodes(n);
if (this->getAircraftIcaoCodesCount() > 0) { emit readAll(); }
}
} // namespace

View File

@@ -12,10 +12,10 @@
#ifndef BLACKCORE_ICAODATAREADER_H
#define BLACKCORE_ICAODATAREADER_H
#include "blackcoreexport.h"
#include "blackcore/blackcoreexport.h"
#include "blackcore/databasereader.h"
#include "blackmisc/aviation/aircrafticaocodelist.h"
#include "blackmisc/aviation/airlineicaocodelist.h"
#include "blackmisc/threadedreader.h"
#include <QObject>
#include <QTimer>
@@ -24,14 +24,14 @@
namespace BlackCore
{
//! Read bookings from VATSIM
class BLACKCORE_EXPORT CIcaoDataReader : public BlackMisc::CThreadedReader
//! Read ICAO data from Database
class BLACKCORE_EXPORT CIcaoDataReader : public CDatabaseReader
{
Q_OBJECT
public:
//! Constructor
explicit CIcaoDataReader(QObject *owner, const QString &aircraftIcaoUrl, const QString &airlineIcaoUrl);
explicit CIcaoDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl);
//! Get aircraft ICAO information
//! \threadsafe
@@ -41,8 +41,13 @@ namespace BlackCore
//! \threadsafe
BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const;
//! Start reading in own thread
void readInBackgroundThread();
//! Get aircraft ICAO information count
//! \threadsafe
int getAircraftIcaoCodesCount() const;
//! Get airline ICAO information count
//! \threadsafe
int getAirlineIcaoCodesCount() const;
signals:
//! Codes have been read
@@ -51,6 +56,9 @@ namespace BlackCore
//! Codes have been read
void readAirlinesIcaoCodes(int number);
//! Everything has been read
void readAll();
private slots:
//! Aircraft have been read
void ps_parseAircraftIcaoData(QNetworkReply *nwReply);
@@ -72,11 +80,11 @@ namespace BlackCore
mutable QReadWriteLock m_lockAirline;
mutable QReadWriteLock m_lockAircraft;
//! Check if terminated or error, otherwise split into array of objects
QJsonArray splitReplyIntoArray(QNetworkReply *nwReply) const;
//! URL
static QString getAircraftIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
//! Check if thread has been finished
bool checkIfFinished() const;
//! URL
static QString getAirlineIcaoUrl(const QString &protocol, const QString &server, const QString &baseUrl);
};
}

View File

@@ -0,0 +1,168 @@
/* 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 "blackmisc/sequence.h"
#include "blackmisc/logmessage.h"
#include "modeldatareader.h"
#include <QRegularExpression>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Simulation;
namespace BlackCore
{
CModelDataReader::CModelDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl) :
CDatabaseReader(owner, "CModelDataReader"),
m_urlLiveries(getLiveryUrl(protocol, server, baseUrl)),
m_urlDistributors(getDistributorUrl(protocol, server, baseUrl)),
m_urlModels(getModelUrl(protocol, server, baseUrl))
{
this->m_networkManagerLivery = new QNetworkAccessManager(this);
this->m_networkManagerDistributor = new QNetworkAccessManager(this);
this->m_networkManagerModel = new QNetworkAccessManager(this);
this->connect(this->m_networkManagerLivery, &QNetworkAccessManager::finished, this, &CModelDataReader::ps_parseLiveryData);
this->connect(this->m_networkManagerDistributor, &QNetworkAccessManager::finished, this, &CModelDataReader::ps_parseDistributorData);
this->connect(this->m_networkManagerModel, &QNetworkAccessManager::finished, this, &CModelDataReader::ps_parseModelData);
}
CLiveryList CModelDataReader::getLiveries() const
{
QReadLocker l(&m_lockLivery);
return m_liveries;
}
CDistributorList CModelDataReader::getDistributors() const
{
QReadLocker l(&m_lockDistributor);
return m_distributors;
}
CAircraftModelList CModelDataReader::getModels() const
{
QReadLocker l(&m_lockModels);
return m_models;
}
int CModelDataReader::getLiveriesCount() const
{
QReadLocker l(&m_lockLivery);
return m_liveries.size();
}
int CModelDataReader::getDistributorsCount() const
{
QReadLocker l(&m_lockDistributor);
return m_distributors.size();
}
int CModelDataReader::getModelsCount() const
{
QReadLocker l(&m_lockModels);
return m_models.size();
}
bool CModelDataReader::allRead() const
{
return
getLiveriesCount() > 0 &&
getModelsCount() > 0 &&
getDistributorsCount();
}
void CModelDataReader::ps_read()
{
this->threadAssertCheck();
Q_ASSERT(this->m_networkManagerLivery);
Q_ASSERT(this->m_networkManagerDistributor);
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");
}
QString CModelDataReader::getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl)
{
return buildUrl(protocol, server, baseUrl, "service/alldistributor.php?rows=20000&sord=asc");
}
QString CModelDataReader::getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl)
{
return buildUrl(protocol, server, baseUrl, "service/allaircraftmodel.php?rows=20000&sord=asc");
}
void CModelDataReader::ps_parseLiveryData(QNetworkReply *nwReplyPtr)
{
// 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; }
CLiveryList liveries = CLiveryList::fromDatabaseJson(array);
// this part needs to be synchronized
int n;
{
QWriteLocker wl(&this->m_lockLivery);
this->m_liveries = liveries;
n = liveries.size();
}
emit readLiveries(n);
if (allRead()) { emit readAll(); }
}
void CModelDataReader::ps_parseDistributorData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
if (array.isEmpty()) { return; }
CDistributorList distributors = CDistributorList::fromDatabaseJson(array);
// this part needs to be synchronized
int n;
{
QWriteLocker wl(&this->m_lockDistributor);
this->m_distributors = distributors;
n = distributors.size();
}
emit readDistributors(n);
if (allRead()) { emit readAll(); }
}
void CModelDataReader::ps_parseModelData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->transformReplyIntoJsonArray(nwReply.data());
if (array.isEmpty()) { return; }
CAircraftModelList models = CAircraftModelList::fromDatabaseJson(array);
// this part needs to be synchronized
int n;
{
QWriteLocker wl(&this->m_lockModels);
this->m_models = models;
n = models.size();
}
emit readModels(n);
if (allRead()) { emit readAll(); }
}
} // namespace

View File

@@ -0,0 +1,116 @@
/* 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_MODELDATAREADER_H
#define BLACKCORE_MODELDATAREADER_H
#include "blackcore/blackcoreexport.h"
#include "blackcore/databasereader.h"
#include "blackmisc/aviation/liverylist.h"
#include "blackmisc/simulation/distributorlist.h"
#include "blackmisc/simulation/aircraftmodellist.h"
#include <QObject>
#include <QTimer>
#include <QNetworkReply>
#include <QReadWriteLock>
namespace BlackCore
{
//! Read model related data from Database
class BLACKCORE_EXPORT CModelDataReader : public CDatabaseReader
{
Q_OBJECT
public:
//! Constructor
explicit CModelDataReader(QObject *owner, const QString &protocol, const QString &server, const QString &baseUrl);
//! Get aircraft liveries
//! \threadsafe
BlackMisc::Aviation::CLiveryList getLiveries() const;
//! Get distributors (of models)
//! \threadsafe
BlackMisc::Simulation::CDistributorList getDistributors() const;
//! Get models
//! \threadsafe
BlackMisc::Simulation::CAircraftModelList getModels() const;
//! Get aircraft liveries count
//! \threadsafe
int getLiveriesCount() const;
//! Get model distributors count
//! \threadsafe
int getDistributorsCount() const;
//! Get models count
//! \threadsafe
int getModelsCount() const;
//! All data read
bool allRead() const;
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();
private slots:
//! Liveries have been read
void ps_parseLiveryData(QNetworkReply *nwReply);
//! Distributors have been read
void ps_parseDistributorData(QNetworkReply *nwReply);
//! Models have been read
void ps_parseModelData(QNetworkReply *nwReply);
//! Read / re-read data file
void ps_read();
private:
QNetworkAccessManager *m_networkManagerLivery = nullptr;
QNetworkAccessManager *m_networkManagerDistributor = nullptr;
QNetworkAccessManager *m_networkManagerModel = nullptr;
BlackMisc::Aviation::CLiveryList m_liveries;
BlackMisc::Simulation::CDistributorList m_distributors;
BlackMisc::Simulation::CAircraftModelList m_models;
QString m_urlLiveries;
QString m_urlDistributors;
QString m_urlModels;
mutable QReadWriteLock m_lockDistributor;
mutable QReadWriteLock m_lockLivery;
mutable QReadWriteLock m_lockModels;
//! URL livery web service
static QString getLiveryUrl(const QString &protocol, const QString &server, const QString &baseUrl);
//! URL distributor web service
static QString getDistributorUrl(const QString &protocol, const QString &server, const QString &baseUrl);
//! URL model web service
static QString getModelUrl(const QString &protocol, const QString &server, const QString &baseUrl);
};
} // ns
#endif // guard

View File

@@ -69,7 +69,7 @@ namespace BlackCore
clientCapabilities |= vatCapsStealth;
}
m_net.reset(Vat_CreateNetworkSession(vatServerLegacyFsd, CProject::systemNameAndVersionChar(),
m_net.reset(Vat_CreateNetworkSession(vatServerLegacyFsd, CProject::swiftVersionChar(),
CProject::versionMajor(), CProject::versionMinor(),
"None", CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY,
clientCapabilities));
@@ -553,7 +553,7 @@ namespace BlackCore
{
const QByteArray acTypeICAObytes = toFSD(m_icaoCode.getAircraftDesignator());
const QByteArray airlineICAObytes = toFSD(m_icaoCode.getAirlineDesignator());
const QByteArray liverybytes = toFSD(m_icaoCode.getLivery());
const QByteArray liverybytes; //! \todo VATLIB: send livery
VatAircraftInfo aircraftInfo {acTypeICAObytes, airlineICAObytes, liverybytes};
Vat_SendModernPlaneInfo(m_net.data(), toFSD(callsign), &aircraftInfo);
@@ -1024,7 +1024,8 @@ namespace BlackCore
BlackMisc::Aviation::CAircraftIcaoData icao;
icao.setAircraftDesignator(aircraftInfo->aircraftType);
icao.setAirlineDesignator(aircraftInfo->airline);
icao.setLivery(aircraftInfo->livery);
//! \todo use livery: aircraftInfo->livery;
emit cbvar_cast(cbvar)->icaoCodesReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), icao);
}

View File

@@ -0,0 +1,28 @@
/* 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 "reader_settings.h"
namespace BlackCore
{
CReaderSettings::CReaderSettings() :
// m_protocolIcaoReader("http"), m_serverIcaoReader("vatrep.vatsim-germany.org"),
// m_protocolModelReader("http"), m_serverModelReader("vatrep.vatsim-germany.org"),
m_protocolIcaoReader("http"), m_serverIcaoReader("ubuntu12"), m_baseUrlIcaoReader("vatrep/public"),
m_protocolModelReader("http"), m_serverModelReader("ubuntu12"), m_baseUrlModelReader("vatrep/public"),
m_bookingsUrl("http://vatbook.euroutepro.com/xml2.php"),
m_vatsimDataFileUrls({ "http://info.vroute.net/vatsim-data.txt" })
{ }
const CReaderSettings &CReaderSettings::instance()
{
static const CReaderSettings rs;
return rs;
}
}

View File

@@ -0,0 +1,69 @@
/* 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_READERSETTINGS_H
#define BLACKCORE_READERSETTINGS_H
#include "blackcoreexport.h"
#include <QStringList>
#include <QObject>
namespace BlackCore
{
//! Settings for readers
class BLACKCORE_EXPORT CReaderSettings : public QObject
{
Q_OBJECT
public:
//! ICAO Reader protocol
const QString &protocolIcaoReader() const { return m_protocolIcaoReader; }
//! ICAO Reader server
const QString &serverIcaoReader() const { return m_serverIcaoReader; }
//! ICAO Reader base URL
const QString &baseUrlIcaoReader() const { return m_baseUrlIcaoReader; }
//! Model Reader protocol
const QString &protocolModelReader() const { return m_protocolModelReader; }
//! Model Reader server
const QString &serverModelReader() const { return m_serverModelReader; }
//! Model Reader server
const QString &baseUrlModelReader() const { return m_baseUrlModelReader; }
//! URL to read bookings
const QString &bookingsUrl() const { return m_bookingsUrl; }
//! VATSIM data file URLs
const QStringList &vatsimDataFileUrls() const { return m_vatsimDataFileUrls; }
//! Singleton
static const CReaderSettings &instance();
private:
//! Default constructor
CReaderSettings();
//! Destructor.
~CReaderSettings() {}
QString m_protocolIcaoReader;
QString m_serverIcaoReader;
QString m_baseUrlIcaoReader;
QString m_protocolModelReader;
QString m_serverModelReader;
QString m_baseUrlModelReader;
QString m_bookingsUrl;
QStringList m_vatsimDataFileUrls;
};
}
#endif // guard

View File

@@ -295,5 +295,6 @@ namespace BlackCore
Q_DECLARE_INTERFACE(BlackCore::ISimulatorFactory, "org.swift-project.blackcore.simulatorinterface")
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackCore::ISimulator::SimulatorStatus)
Q_DECLARE_INTERFACE(BlackCore::ISimulatorListener, "org.swift-project.blackcore.simulatorlistener")
#endif // guard

View File

@@ -21,8 +21,9 @@ using namespace BlackMisc::Network;
namespace BlackCore
{
CVatsimBookingReader::CVatsimBookingReader(QObject *owner) :
CThreadedReader(owner, "CVatsimBookingReader")
CVatsimBookingReader::CVatsimBookingReader(QObject *owner, const QString &url) :
CThreadedReader(owner, "CVatsimBookingReader"),
m_serviceUrl(url)
{
this->m_networkManager = new QNetworkAccessManager(this);
this->connect(this->m_networkManager, &QNetworkAccessManager::finished, this, &CVatsimBookingReader::ps_parseBookings);
@@ -39,7 +40,7 @@ namespace BlackCore
void CVatsimBookingReader::ps_read()
{
this->threadAssertCheck();
QUrl url(this->m_serviceUrl.get());
QUrl url(this->m_serviceUrl);
if (url.isEmpty()) return;
Q_ASSERT(this->m_networkManager);
QNetworkRequest request(url);

View File

@@ -13,7 +13,6 @@
#define BLACKCORE_VATSIMBOOKINGREADER_H
#include "blackcoreexport.h"
#include "blackcore/settings/network.h"
#include "blackmisc/threadedreader.h"
#include "blackmisc/aviation/atcstationlist.h"
@@ -31,7 +30,7 @@ namespace BlackCore
public:
//! Constructor
explicit CVatsimBookingReader(QObject *owner);
explicit CVatsimBookingReader(QObject *owner, const QString &url);
//! Read / re-read bookings
void readInBackgroundThread();
@@ -45,7 +44,7 @@ namespace BlackCore
void ps_read();
private:
CSetting<Settings::Network::BookingService> m_serviceUrl { this };
QString m_serviceUrl; //!< URL of the service
QNetworkAccessManager *m_networkManager = nullptr;
signals:

View File

@@ -0,0 +1,260 @@
/* 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 "icaodatareader.h"
#include "modeldatareader.h"
#include "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)
{
// 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);
}
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(); }
}
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, CReaderSettings::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, CReaderSettings::instance().vatsimDataFileUrls());
connect(this->m_vatsimDataFileReader, &CVatsimDataFileReader::dataRead, this, &CWebDataReader::ps_dataFileRead);
this->m_vatsimDataFileReader->start();
this->m_vatsimDataFileReader->setInterval(90 * 1000);
}
// 3. ICAO data reader
if (flags.testFlag(IcaoDataReader))
{
this->m_icaoDataReader = new CIcaoDataReader(this, CReaderSettings::instance().protocolIcaoReader(), CReaderSettings::instance().serverIcaoReader(), CReaderSettings::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();
}
// 4. Model reader
if (flags.testFlag(ModelReader))
{
this->m_modelDataReader = new CModelDataReader(this, CReaderSettings::instance().protocolModelReader(), CReaderSettings::instance().serverModelReader(), CReaderSettings::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_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_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

@@ -0,0 +1,173 @@
/* 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 <QObject>
namespace BlackCore
{
class CVatsimBookingReader;
class CVatsimDataFileReader;
class CIcaoDataReader;
class CModelDataReader;
/**
* 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,
IcaoDataReader = 1 << 2,
ModelReader = 1 << 3,
AllVatsimReaders = VatsimBookingReader | VatsimDataReader,
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);
//! 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; }
//! 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);
//! 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);
//! 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;
CIcaoDataReader *m_icaoDataReader = nullptr;
CModelDataReader *m_modelDataReader = nullptr;
};
} // namespace
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackCore::CWebDataReader::WebReader)
#endif