Files
pilotclient/src/blackcore/airspacemonitor.h
Roland Winklmeier ee8af9f4c6 Filter other pilots ghost aircraft when flying in shared cockpit mode
When flying in shared cockpit mode, both pilots log into the network.
One as pilot to be visible to ATC and other pilots. The other one as
observer. For the observing user, the pilots aircraft needs to be filtered.
Filter algorithm is using the same schema as vPilot does.

ref T427
2018-11-16 02:49:54 +01:00

306 lines
16 KiB
C++

/* Copyright (C) 2013
* 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_AIRSPACE_MONITOR_H
#define BLACKCORE_AIRSPACE_MONITOR_H
#include "blackcore/blackcoreexport.h"
#include "blackcore/network.h"
#include "blackmisc/simulation/aircraftmodel.h"
#include "blackmisc/simulation/airspaceaircraftsnapshot.h"
#include "blackmisc/simulation/ownaircraftprovider.h"
#include "blackmisc/simulation/remoteaircraftprovider.h"
#include "blackmisc/simulation/simulationenvironmentprovider.h"
#include "blackmisc/simulation/simulatedaircraft.h"
#include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/network/clientprovider.h"
#include "blackmisc/network/userlist.h"
#include "blackmisc/geo/coordinategeodetic.h"
#include "blackmisc/aviation/aircraftpartslist.h"
#include "blackmisc/aviation/aircraftsituationlist.h"
#include "blackmisc/aviation/atcstation.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/callsignset.h"
#include "blackmisc/aviation/flightplan.h"
#include "blackmisc/pq/frequency.h"
#include "blackmisc/pq/length.h"
#include "blackmisc/pq/angle.h"
#include "blackmisc/identifier.h"
#include <QJsonObject>
#include <QList>
#include <QHash>
#include <QMetaObject>
#include <QObject>
#include <QReadWriteLock>
#include <QString>
#include <QTimer>
#include <QtGlobal>
#include <functional>
namespace BlackCore
{
class CAirspaceAnalyzer;
class INetwork;
//! Keeps track of other entities in the airspace: aircraft, ATC stations, etc.
//! Central instance of data for \sa IRemoteAircraftProvider.
class BLACKCORE_EXPORT CAirspaceMonitor :
public BlackMisc::Simulation::CRemoteAircraftProvider, // those data will be provided from the class CAirspaceMonitor
public BlackMisc::Simulation::COwnAircraftAware, // used to obtain in memory information about own aircraft
public BlackMisc::Simulation::CSimulationEnvironmentAware, // elevation info etc. from simulator
public BlackMisc::Network::CClientProvider // those data will be provided from the class CAirspaceMonitor
{
Q_OBJECT
Q_INTERFACES(BlackMisc::Network::IClientProvider)
Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider)
public:
//! Log categories
static const BlackMisc::CLogCategoryList &getLogCategories();
//! Constructor
CAirspaceMonitor(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraft, INetwork *network, QObject *parent);
//! Members not implenented or fully implenented by CRemoteAircraftProvider
//! \ingroup remoteaircraftprovider
//! @{
virtual QObject *asQObject() override { return this; }
virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override;
virtual bool updateFastPositionEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enableFastPositonUpdates) override;
//! @}
//! Returns the list of users we know about
BlackMisc::Network::CUserList getUsers() const;
//! Returns a list of the users corresponding to the given callsigns
BlackMisc::Network::CUserList getUsersForCallsigns(const BlackMisc::Aviation::CCallsignSet &callsigns) const;
//! Returns the loaded flight plan for the given callsign
//! \remarks only use this if a network loaded flight plan is directly needed
//! \remarks pseudo synchronous, call the async functions and waits for result
BlackMisc::Aviation::CFlightPlan loadFlightPlanFromNetwork(const BlackMisc::Aviation::CCallsign &callsign);
//! Try to get flight plan remarks
//! \remarks returns a value only if the flight plan is already cached or can be obtained from VATSIM reader
//! \threadsafe
BlackMisc::Aviation::CFlightPlanRemarks tryToGetFlightPlanRemarks(const BlackMisc::Aviation::CCallsign &callsign) const;
//! Returns the current online ATC stations (consolidated with booked stations)
BlackMisc::Aviation::CAtcStationList getAtcStationsOnline() const { return m_atcStationsOnline; }
//! Recalculate distance to own aircraft
BlackMisc::Aviation::CAtcStationList getAtcStationsOnlineRecalculated();
//! Returns the current booked ATC stations (consolidated with online stations)
BlackMisc::Aviation::CAtcStationList getAtcStationsBooked() const { return m_atcStationsBooked; }
//! Recalculate distance to own aircraft
BlackMisc::Aviation::CAtcStationList getAtcStationsBookedRecalculated();
//! Returns the closest ATC station operating on the given frequency, if any
BlackMisc::Aviation::CAtcStation getAtcStationForComUnit(const BlackMisc::Aviation::CComSystem &comSystem) const;
//! Clear the contents
void clear();
//! Request to update other clients' data from the network
void requestDataUpdates();
//! Request to update ATC stations' ATIS data from the network
void requestAtisUpdates();
//! Request updates of bookings
void requestAtcBookingsUpdate();
//! Analyzer
CAirspaceAnalyzer *analyzer() const { return m_analyzer; }
//! \copydoc CAirspaceAnalyzer::setEnabled
bool enableAnalyzer(bool enable);
//! Gracefully shut down, e.g. for thread safety
void gracefulShutdown();
//! Re-init all aircrft
int reInitializeAllAircraft();
//! Create dummy entries for performance tests
//! \private for testing purposes
void testCreateDummyOnlineAtcStations(int number);
//! Test injected aircraft parts
//! \private for testing purposes
void testAddAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts, bool incremental);
signals:
//! Online ATC stations were changed
void changedAtcStationsOnline();
//! Booked ATC stations were changed
void changedAtcStationsBooked();
//! Connection status of an ATC station was changed
void changedAtcStationOnlineConnectionStatus(const BlackMisc::Aviation::CAtcStation &station, bool isConnected);
//! Raw data as received from network
//! \remark used for statistics
//! \private
void requestedNewAircraft(const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftDesignator, const QString &airlineDesignator, const QString &livery);
//! Ready for model matching
void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft);
//! An ATIS has been received
void changedAtisReceived(const BlackMisc::Aviation::CCallsign &callsign);
private:
//! Used to temporary store FsInn data
struct FsInnPacket
{
//! Default ctor
FsInnPacket() {}
//! Constructor
FsInnPacket(const QString &aircraftIcaoDesignator, const QString &airlineDesignator, const QString &combinedCode, const QString &modelString);
QString aircraftIcaoDesignator;
QString airlineIcaoDesignator;
QString combinedCode;
QString modelString;
};
BlackMisc::Aviation::CAtcStationList m_atcStationsOnline; //!< online ATC stations
BlackMisc::Aviation::CAtcStationList m_atcStationsBooked; //!< booked ATC stations
QHash<BlackMisc::Aviation::CCallsign, FsInnPacket> m_tempFsInnPackets;
QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CFlightPlan> m_flightPlanCache; //!< flight plan information retrieved from network and cached
INetwork *m_network = nullptr; //!< corresponding network interface
CAirspaceAnalyzer *m_analyzer = nullptr; //!< owned analyzer
bool m_bookingsRequested = false; //!< bookings have been requested, it can happen we receive an BlackCore::Vatsim::CVatsimBookingReader::atcBookingsReadUnchanged signal
//! Remove ATC online stations
void removeAllOnlineAtcStations();
//! Remove all aircraft in range
//! \threadsafe
void removeAllAircraft();
//! Remove data from caches and logs
//! \threadsafe
void removeFromAircraftCachesAndLogs(const BlackMisc::Aviation::CCallsign &callsign);
//! Network queries for ATC
void sendInitialAtcQueries(const BlackMisc::Aviation::CCallsign &callsign);
//! Network queries for pilots
void sendInitialPilotQueries(const BlackMisc::Aviation::CCallsign &callsign, bool withIcaoQuery, bool withFsInn);
//! Connected with network?
bool isConnected() const;
//! Connected with server and not shutting down
bool isConnectedAndNotShuttingDown() const;
//! Get the currently connected server
const BlackMisc::Network::CServer &getConnectedServer() const;
//! Current ECO system of connected server
const BlackMisc::Network::CEcosystem &getCurrentEcosystem() const;
//! Supports VATSIM data file
//! \remark depends on currently connected Ecosystem
bool supportsVatsimDataFile() const;
//! Distance calculation
BlackMisc::PhysicalQuantities::CLength calculateDistanceToOwnAircraft(const BlackMisc::Aviation::CAircraftSituation &situation) const;
//! Angle calculation
BlackMisc::PhysicalQuantities::CAngle calculateBearingToOwnAircraft(const BlackMisc::Aviation::CAircraftSituation &situation) const;
//! Store an aircraft situation under consideration of gnd.flags/CG and elevation
//! \threadsafe
//! \remark sets gnd flag from parts if parts are available
//! \remark uses gnd elevation if found
virtual BlackMisc::Aviation::CAircraftSituation storeAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation, bool allowTestOffset = true) override;
//! Add or update aircraft
BlackMisc::Simulation::CSimulatedAircraft addOrUpdateAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftIcao, const QString &airlineIcao, const QString &livery, const QString &modelString, BlackMisc::Simulation::CAircraftModel::ModelType modelType, BlackMisc::CStatusMessageList *log);
//! Add new aircraft, ignored if aircraft already exists
//! \remark position to own aircraft set, VATSIM data file data considered
//! \threadsafe
bool addNewAircraftInRange(const BlackMisc::Simulation::CSimulatedAircraft &aircraft);
//! Asynchronously add aircraft
//! \threadsafe
//! \sa addNewAircraftInRange
void asyncAddNewAircraftInRange(const BlackMisc::Simulation::CSimulatedAircraftList &aircraft, bool readyForModelMatching);
//! Update online stations by callsign
int updateOnlineStation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &vm, bool skipEqualValues = true, bool sendSignal = true);
//! Update booked station by callsign
int updateBookedStation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &vm, bool skipEqualValues = true, bool sendSignal = true);
//! Co-pilot detected
void copilotDetected();
//! Call CAirspaceMonitor::onCustomFSInnPacketReceived with stored packet
void recallFsInnPacket(const BlackMisc::Aviation::CCallsign &callsign);
//! Send the information if aircraft and(!) client are available
//! \note it can take some time to obtain all data for model matching, so function recursively calls itself if something is still missing (trial)
//! \sa reverseLookupModelWithFlightplanData
void sendReadyForModelMatching(const BlackMisc::Aviation::CCallsign &callsign, int trial = 1);
//! Reverse lookup, if available flight plan data are considered
//! \remark this is where a model is created based on network data
//! \ingroup reverselookup
BlackMisc::Simulation::CAircraftModel reverseLookupModelWithFlightplanData(
const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftIcao,
const QString &airlineIcao, const QString &liveryString, const QString &modelString,
BlackMisc::Simulation::CAircraftModel::ModelType type, BlackMisc::CStatusMessageList *log);
bool isCopilotAircraft(const BlackMisc::Aviation::CCallsign &callsign) const;
//! Create aircraft in range, this is the only place where a new aircraft should be added
void onAircraftUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation, const BlackMisc::Aviation::CTransponder &transponder);
//! Create ATC station, this is the only place where an online ATC station should be added
void onAtcPositionUpdate(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &frequency, const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::PhysicalQuantities::CLength &range);
//! Receive FSInn packet
//! \remark This can happen even without a query before
void onCustomFSInnPacketReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineIcaoDesignator, const QString &aircraftDesignator, const QString &combinedAircraftType, const QString &modelString);
void onRealNameReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname);
void onCapabilitiesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, int clientCaps);
void onServerReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &server);
void onFlightPlanReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CFlightPlan &flightPlan);
void onAtcControllerDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
void onAtisReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atisMessage);
void onAtisVoiceRoomReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &url);
void onAtisLogoffTimeReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime);
void onIcaoCodesReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftIcaoDesignator, const QString &airlineIcaoDesignator, const QString &livery);
void onPilotDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
void onFrequencyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &frequency);
void onReceivedAtcBookings(const BlackMisc::Aviation::CAtcStationList &bookedStations);
void onReadUnchangedAtcBookings();
void onReceivedVatsimDataFile();
void onAircraftConfigReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &jsonObject, qint64 currentOffsetMs);
void onAircraftInterimUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation);
void onConnectionStatusChanged(BlackCore::INetwork::ConnectionStatus oldStatus, BlackCore::INetwork::ConnectionStatus newStatus);
};
} // namespace
#endif // guard