diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 00c03713a..490237399 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -7,21 +7,21 @@ * contained in the LICENSE file. */ +#include "blackcore/vatsim/networkvatlib.h" +#include "blackcore/vatsim/vatsimbookingreader.h" +#include "blackcore/vatsim/vatsimdatafilereader.h" #include "blackcore/airspaceanalyzer.h" #include "blackcore/airspacemonitor.h" #include "blackcore/aircraftmatcher.h" #include "blackcore/application.h" -#include "blackcore/vatsim/networkvatlib.h" -#include "blackcore/vatsim/vatsimbookingreader.h" -#include "blackcore/vatsim/vatsimdatafilereader.h" #include "blackcore/webdataservices.h" -#include "blackmisc/audio/voiceroom.h" #include "blackmisc/simulation/matchingutils.h" #include "blackmisc/aviation/aircraftparts.h" #include "blackmisc/aviation/aircraftsituation.h" #include "blackmisc/aviation/comsystem.h" #include "blackmisc/aviation/modulator.h" #include "blackmisc/aviation/transponder.h" +#include "blackmisc/audio/voiceroom.h" #include "blackmisc/geo/elevationplane.h" #include "blackmisc/network/user.h" #include "blackmisc/network/voicecapabilities.h" @@ -29,12 +29,10 @@ #include "blackmisc/test/testing.h" #include "blackmisc/compare.h" #include "blackmisc/iterator.h" -#include "blackmisc/json.h" #include "blackmisc/logmessage.h" #include "blackmisc/propertyindexvariantmap.h" #include "blackmisc/range.h" #include "blackmisc/sequence.h" -#include "blackmisc/statusmessage.h" #include "blackmisc/statusmessagelist.h" #include "blackmisc/threadutils.h" #include "blackmisc/variant.h" @@ -66,14 +64,13 @@ using namespace BlackCore::Vatsim; namespace BlackCore { CAirspaceMonitor::CAirspaceMonitor(IOwnAircraftProvider *ownAircraftProvider, INetwork *network, QObject *parent) - : QObject(parent), + : CRemoteAircraftProvider(parent), COwnAircraftAware(ownAircraftProvider), - CIdentifiable(this), m_network(network), m_analyzer(new CAirspaceAnalyzer(ownAircraftProvider, this, network, this)) { this->setObjectName("CAirspaceMonitor"); - m_enableReverseLookupMsgs = sApp->isDeveloperFlagSet(); + this->enableReverseLookupMessages(sApp->isDeveloperFlagSet()); connect(m_network, &INetwork::atcPositionUpdate, this, &CAirspaceMonitor::onAtcPositionUpdate); connect(m_network, &INetwork::atisReplyReceived, this, &CAirspaceMonitor::onAtisReceived); @@ -116,174 +113,32 @@ namespace BlackCore connect(m_analyzer, &CAirspaceAnalyzer::timeoutAtc, this, &CAirspaceMonitor::onAtcControllerDisconnected, Qt::QueuedConnection); } + bool CAirspaceMonitor::updateFastPositionEnabled(const Aviation::CCallsign &callsign, bool enableFastPositonUpdates) + { + const bool r = CRemoteAircraftProvider::updateFastPositionEnabled(callsign, enableFastPositonUpdates); + if (m_network && sApp && !sApp->isShuttingDown()) + { + // thread safe update of m_network + QTimer::singleShot(0, m_network, [ = ] + { + if (m_network) { m_network->addInterimPositionReceiver(callsign); } + }); + } + return r; + } + const CLogCategoryList &CAirspaceMonitor::getLogCategories() { - static const BlackMisc::CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() }; + static const CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() }; return cats; } - CSimulatedAircraftList CAirspaceMonitor::getAircraftInRange() const - { - QReadLocker l(&m_lockAircraft); - return m_aircraftInRange; - } - - CCallsignSet CAirspaceMonitor::getAircraftInRangeCallsigns() const - { - return this->getAircraftInRange().getCallsigns(); - } - - CSimulatedAircraft CAirspaceMonitor::getAircraftInRangeForCallsign(const CCallsign &callsign) const - { - const CSimulatedAircraft aircraft = this->getAircraftInRange().findFirstByCallsign(callsign); - return aircraft; - } - - CAircraftModel CAirspaceMonitor::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const - { - const CSimulatedAircraft aircraft(getAircraftInRangeForCallsign(callsign)); // threadsafe - return aircraft.getModel(); - } - - int CAirspaceMonitor::getAircraftInRangeCount() const - { - return this->getAircraftInRange().size(); - } - CAirspaceAircraftSnapshot CAirspaceMonitor::getLatestAirspaceAircraftSnapshot() const { Q_ASSERT_X(m_analyzer, Q_FUNC_INFO, "No analyzer"); return m_analyzer->getLatestAirspaceAircraftSnapshot(); } - CAircraftSituationList CAirspaceMonitor::remoteAircraftSituations(const CCallsign &callsign) const - { - QReadLocker l(&m_lockSituations); - static const CAircraftSituationList empty; - if (!m_situationsByCallsign.contains(callsign)) { return empty; } - return m_situationsByCallsign[callsign]; - } - - int CAirspaceMonitor::remoteAircraftSituationsCount(const CCallsign &callsign) const - { - QReadLocker l(&m_lockSituations); - if (!m_situationsByCallsign.contains(callsign)) { return -1; } - return m_situationsByCallsign[callsign].size(); - } - - CAircraftPartsList CAirspaceMonitor::remoteAircraftParts(const CCallsign &callsign, qint64 cutoffTimeValuesBefore) const - { - QReadLocker l(&m_lockParts); - static const CAircraftPartsList empty; - if (!m_partsByCallsign.contains(callsign)) { return empty; } - if (cutoffTimeValuesBefore < 0) - { - return m_partsByCallsign[callsign]; - } - else - { - return m_partsByCallsign[callsign].findBefore(cutoffTimeValuesBefore); - } - } - - bool CAirspaceMonitor::isRemoteAircraftSupportingParts(const CCallsign &callsign) const - { - QReadLocker l(&m_lockParts); - return m_aircraftWithParts.contains(callsign); - } - - int CAirspaceMonitor::getRemoteAircraftSupportingPartsCount() const - { - QReadLocker l(&m_lockParts); - return m_aircraftWithParts.size(); - } - - CCallsignSet CAirspaceMonitor::remoteAircraftSupportingParts() const - { - QReadLocker l(&m_lockParts); - return m_aircraftWithParts; - } - - QList CAirspaceMonitor::connectRemoteAircraftProviderSignals( - QObject *receiver, - std::function situationFunction, - std::function partsFunction, - std::function removedAircraftFunction, - std::function aircraftSnapshotFunction - ) - { - Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver"); - - // bind does not allow to define connection type, so we use receiver as workaround - const QMetaObject::Connection uc; // unconnected - const QMetaObject::Connection c1 = situationFunction ? connect(this, &CAirspaceMonitor::addedAircraftSituation, receiver, situationFunction) : uc; - Q_ASSERT_X(c1 || !situationFunction, Q_FUNC_INFO, "connect failed"); - const QMetaObject::Connection c2 = partsFunction ? connect(this, &CAirspaceMonitor::addedAircraftParts, receiver, partsFunction) : uc; - Q_ASSERT_X(c2 || !partsFunction, Q_FUNC_INFO, "connect failed"); - const QMetaObject::Connection c3 = removedAircraftFunction ? connect(this, &CAirspaceMonitor::removedAircraft, receiver, removedAircraftFunction) : uc; - Q_ASSERT_X(c3 || !removedAircraftFunction, Q_FUNC_INFO, "connect failed"); - // trick is to use the Qt::QueuedConnection signal here - // analyzer (own thread) -> airspaceAircraftSnapshot -> AirspaceMonitor -> airspaceAircraftSnapshot queued in main thread - const QMetaObject::Connection c4 = aircraftSnapshotFunction ? connect(m_analyzer, &CAirspaceAnalyzer::airspaceAircraftSnapshot, receiver, aircraftSnapshotFunction, Qt::QueuedConnection) : uc; - Q_ASSERT_X(c4 || !aircraftSnapshotFunction, Q_FUNC_INFO, "connect failed"); - return QList({ c1, c2, c3, c4}); - } - - bool CAirspaceMonitor::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRedering) - { - const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRedering)); - const int c = this->updateAircraftInRange(callsign, vm); - return c > 0; - } - - bool CAirspaceMonitor::updateAircraftModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) - { - if (CIdentifiable::isMyIdentifier(originator)) { return false; } - const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexModel, CVariant::from(model)); - const int c = this->updateAircraftInRange(callsign, vm); - return c > 0; - } - - bool CAirspaceMonitor::updateAircraftNetworkModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) - { - if (CIdentifiable::isMyIdentifier(originator)) { return false; } - const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexNetworkModel, CVariant::from(model)); - const int c = this->updateAircraftInRange(callsign, vm); - return c > 0; - } - - bool CAirspaceMonitor::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates) - { - const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexFastPositionUpdates, CVariant::fromValue(enableFastPositonUpdates)); - const int c = this->updateAircraftInRange(callsign, vm); - { - QReadLocker l(&m_lockAircraft); - const CSimulatedAircraftList enabledAircraft = m_aircraftInRange.findBy(&CSimulatedAircraft::fastPositionUpdates, true); - m_network->setInterimPositionReceivers(enabledAircraft.getCallsigns()); - } - return c > 0; - } - - bool CAirspaceMonitor::updateAircraftRendered(const CCallsign &callsign, bool rendered) - { - const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexRendered, CVariant::fromValue(rendered)); - const int c = this->updateAircraftInRange(callsign, vm); - return c > 0; - } - - bool CAirspaceMonitor::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation) - { - QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setGroundElevationChecked(callsign, elevation); - return c > 0; - } - - void CAirspaceMonitor::updateMarkAllAsNotRendered() - { - QWriteLocker l(&m_lockAircraft); - m_aircraftInRange.markAllAsNotRendered(); - } - CFlightPlan CAirspaceMonitor::loadFlightPlanFromNetwork(const CCallsign &callsign) { CFlightPlan plan; @@ -400,20 +255,6 @@ namespace BlackCore return users; } - bool CAirspaceMonitor::isAircraftInRange(const CCallsign &callsign) const - { - if (callsign.isEmpty()) { return false; } - QReadLocker l(&m_lockAircraft); - return m_aircraftInRange.containsCallsign(callsign); - } - - bool CAirspaceMonitor::isVtolAircraft(const CCallsign &callsign) const - { - if (callsign.isEmpty()) { return false; } - const CSimulatedAircraft aircraft = this->getAircraftInRangeForCallsign(callsign); - return aircraft.isVtol(); - } - CAtcStation CAirspaceMonitor::getAtcStationForComUnit(const CComSystem &comSystem) { CAtcStation station; @@ -423,42 +264,6 @@ namespace BlackCore return stations.front(); } - void CAirspaceMonitor::enableReverseLookupMessages(bool enabled) - { - QWriteLocker l(&m_lockMessages); - m_enableReverseLookupMsgs = enabled; - } - - bool CAirspaceMonitor::isReverseLookupMessagesEnabled() const - { - QReadLocker l(&m_lockMessages); - return m_enableReverseLookupMsgs; - } - - CStatusMessageList CAirspaceMonitor::getReverseLookupMessages(const CCallsign &callsign) const - { - QReadLocker l(&m_lockMessages); - return m_reverseLookupMessages.value(callsign); - } - - CStatusMessageList CAirspaceMonitor::getAircraftPartsHistory(const CCallsign &callsign) const - { - QReadLocker l(&m_lockPartsHistory); - return m_aircraftPartsHistory.value(callsign); - } - - bool CAirspaceMonitor::isAircraftPartsHistoryEnabled() const - { - QReadLocker l(&m_lockPartsHistory); - return m_enableAircraftPartsHistory; - } - - void CAirspaceMonitor::enableAircraftPartsHistory(bool enabled) - { - QWriteLocker l(&m_lockPartsHistory); - m_enableAircraftPartsHistory = enabled; - } - void CAirspaceMonitor::requestDataUpdates() { if (!this->isConnected()) { return; } @@ -545,9 +350,9 @@ namespace BlackCore } // Client - const CVoiceCapabilities caps = sApp->getWebDataServices()->getVoiceCapabilityForCallsign(callsign); + const CVoiceCapabilities voiceCaps = sApp->getWebDataServices()->getVoiceCapabilityForCallsign(callsign); CPropertyIndexVariantMap vm = CPropertyIndexVariantMap({CClient::IndexUser, CUser::IndexRealName}, realname); - vm.addValue({ CClient::IndexVoiceCapabilities }, caps); + vm.addValue({ CClient::IndexVoiceCapabilities }, voiceCaps); this->updateOrAddClient(callsign, vm, false); } @@ -585,17 +390,7 @@ namespace BlackCore void CAirspaceMonitor::removeAllAircraft() { - for (const CSimulatedAircraft &aircraft : getAircraftInRange()) - { - const CCallsign cs(aircraft.getCallsign()); - emit removedAircraft(cs); - } - - // locked members - { QWriteLocker l(&m_lockParts); m_partsByCallsign.clear(); m_aircraftWithParts.clear(); } - { QWriteLocker l(&m_lockSituations); m_situationsByCallsign.clear(); } - { QWriteLocker l(&m_lockMessages); m_reverseLookupMessages.clear(); } - { QWriteLocker l(&m_lockAircraft); m_aircraftInRange.clear(); } + CRemoteAircraftProvider::removeAllAircraft(); // non thread safe parts m_flightPlanCache.clear(); @@ -605,9 +400,7 @@ namespace BlackCore { if (callsign.isEmpty()) { return; } m_flightPlanCache.remove(callsign); - - QWriteLocker l(&m_lockMessages); - m_reverseLookupMessages.remove(callsign); + this->removeReverseLookupMessages(callsign); } void CAirspaceMonitor::onReceivedAtcBookings(const CAtcStationList &bookedStations) @@ -819,7 +612,7 @@ namespace BlackCore if (!callsign.isValid()) { return; } if (!this->isConnected()) { return; } - const bool isAircraft = m_aircraftInRange.containsCallsign(callsign); + const bool isAircraft = this->isAircraftInRange(callsign); const bool isAtc = m_atcStationsOnline.containsCallsign(callsign); if (!isAircraft && !isAtc) { @@ -867,38 +660,6 @@ namespace BlackCore emit this->requestedNewAircraft(callsign, aircraftIcaoDesignator, airlineIcaoDesignator, livery); } - void CAirspaceMonitor::addReverseLookupMessages(const CCallsign &callsign, const CStatusMessageList &messages) - { - if (callsign.isEmpty()) { return; } - if (messages.isEmpty()) { return; } - QWriteLocker l(&m_lockMessages); - if (!m_enableReverseLookupMsgs) { return; } - if (m_reverseLookupMessages.contains(callsign)) - { - CStatusMessageList &msgs = m_reverseLookupMessages[callsign]; - msgs.push_back(messages); - } - else - { - m_reverseLookupMessages.insert(callsign, messages); - } - } - - void CAirspaceMonitor::addReverseLookupMessage(const CCallsign &callsign, const CStatusMessage &message) - { - if (callsign.isEmpty()) { return; } - if (message.isEmpty()) { return; } - this->addReverseLookupMessages(callsign, CStatusMessageList({ message })); - } - - void CAirspaceMonitor::addReverseLookupMessage(const CCallsign &callsign, const QString &message, CStatusMessage::StatusSeverity severity) - { - if (callsign.isEmpty()) { return; } - if (message.isEmpty()) { return; } - const CStatusMessage m = CMatchingUtils::logMessage(callsign, message, getLogCategories(), severity); - this->addReverseLookupMessage(callsign, m); - } - CAircraftModel CAirspaceMonitor::reverseLookupModelWithFlightplanData( const CCallsign &callsign, const QString &aircraftIcaoString, const QString &airlineIcaoString, const QString &livery, const QString &modelString, @@ -960,7 +721,6 @@ namespace BlackCore const CCallsign callsign = aircraft.getCallsign(); Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "Missing callsign"); - if (this->isAircraftInRange(callsign)) { return false; } if (!sApp || sApp->isShuttingDown()) { return false; } CSimulatedAircraft newAircraft(aircraft); @@ -969,29 +729,7 @@ namespace BlackCore Q_ASSERT_X(sApp->hasWebDataServices(), Q_FUNC_INFO, "No web services"); sApp->getWebDataServices()->updateWithVatsimDataFileData(newAircraft); - // store - { - QWriteLocker l(&m_lockAircraft); - m_aircraftInRange.push_back(newAircraft); - } - emit this->addedAircraft(aircraft); - emit this->changedAircraftInRange(); - return true; - } - - int CAirspaceMonitor::updateAircraftInRange(const CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues) - { - Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "Missing callsign"); - int c = 0; - { - QWriteLocker l(&m_lockAircraft); - c = m_aircraftInRange.applyIfCallsign(callsign, vm, skipEqualValues); - } - if (c > 0) - { - emit this->changedAircraftInRange(); - } - return c; + return CRemoteAircraftProvider::addNewAircraftInRange(newAircraft); } int CAirspaceMonitor::updateOnlineStation(const CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues, bool sendSignal) @@ -1057,7 +795,6 @@ namespace BlackCore // store situation history CAircraftSituation fullSituation(situation); this->storeAircraftSituation(fullSituation); - emit this->addedAircraftSituation(fullSituation); const bool existsInRange = this->isAircraftInRange(callsign); const bool hasFsInnPacket = m_tempFsInnPackets.contains(callsign); @@ -1100,11 +837,7 @@ namespace BlackCore // Interim packets do not have groundspeed, hence set the last known value. // If there is no full position available yet, throw this interim position away. CAircraftSituation interimSituation(situation); - CAircraftSituationList history; - { - QReadLocker l(&m_lockSituations); - history = m_situationsByCallsign[callsign]; - } + CAircraftSituationList history = this->remoteAircraftSituations(callsign); if (history.empty()) { return; } // we need one full situation at least const CAircraftSituation lastSituation = history.latestObject(); if (lastSituation.getPosition() == interimSituation.getPosition()) { return; } // same position, ignore @@ -1115,7 +848,6 @@ namespace BlackCore // store situation history this->storeAircraftSituation(interimSituation); - emit this->addedAircraftSituation(interimSituation); // if we have not aircraft in range yer, we stop here if (!this->isAircraftInRange(callsign)) { return; } @@ -1152,19 +884,9 @@ namespace BlackCore // in case of inconsistencies I always remove here this->removeFromAircraftCachesAndLogs(callsign); - - { QWriteLocker l1(&m_lockParts); m_partsByCallsign.remove(callsign); m_aircraftWithParts.remove(callsign); } - { QWriteLocker l2(&m_lockSituations); m_situationsByCallsign.remove(callsign); } - { QWriteLocker l4(&m_lockPartsHistory); m_aircraftPartsHistory.remove(callsign); } + const bool removed = CRemoteAircraftProvider::removeAircraft(callsign); this->removeClient(callsign); - - bool removedCallsign = false; - { - QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.removeByCallsign(callsign); - removedCallsign = c > 0; - } - if (removedCallsign) { emit this->removedAircraft(callsign); } + if (removed) { emit this->removedAircraft(callsign); } } void CAirspaceMonitor::onFrequencyReceived(const CCallsign &callsign, const CFrequency &frequency) @@ -1179,62 +901,7 @@ namespace BlackCore void CAirspaceMonitor::onAircraftConfigReceived(const CCallsign &callsign, const QJsonObject &jsonObject, int currentOffset) { Q_ASSERT(CThreadUtils::isCurrentThreadObjectThread(this)); - const CSimulatedAircraft remoteAircraft(getAircraftInRangeForCallsign(callsign)); - const bool isFull = jsonObject.value("is_full_data").toBool(); - - // If we are not yet synchronized, we throw away any incremental packet - if (!remoteAircraft.hasValidCallsign()) { return; } - if (!remoteAircraft.isPartsSynchronized() && !isFull) { return; } - - CAircraftParts parts; - try - { - if (isFull) - { - parts.convertFromJson(jsonObject); - } - else - { - // incremental update - parts = this->remoteAircraftParts(callsign).frontOrDefault(); - const QJsonObject config = applyIncrementalObject(parts.toJson(), jsonObject); - parts.convertFromJson(config); - } - } - catch (const CJsonException &ex) - { - CStatusMessage message = ex.toStatusMessage(this, "Invalid parts packet"); - message.setSeverity(CStatusMessage::SeverityDebug); - CLogMessage::preformatted(message); - } - - // make sure in any case right time - parts.setCurrentUtcTime(); - parts.setTimeOffsetMs(currentOffset); - - // store part history (parts always absolute) - this->storeAircraftParts(callsign, parts); - emit this->addedAircraftParts(callsign, parts); - - if (m_enableAircraftPartsHistory) - { - const QJsonDocument doc(jsonObject); - const QString partsAsString = doc.toJson(QJsonDocument::Compact); - const CStatusMessage message(getLogCategories(), CStatusMessage::SeverityInfo, callsign.isEmpty() ? callsign.toQString() + ": " + partsAsString.trimmed() : partsAsString.trimmed()); - if (m_aircraftPartsHistory.contains(callsign)) - { - CStatusMessageList &msgs = m_aircraftPartsHistory[callsign]; - msgs.push_back(message); - } - else - { - m_aircraftPartsHistory.insert(callsign, message); - } - } - - // here I expect always a changed value - QWriteLocker l(&m_lockAircraft); - m_aircraftInRange.setAircraftParts(callsign, parts); + this->storeAircraftParts(callsign, jsonObject, currentOffset); } void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation) @@ -1273,47 +940,7 @@ namespace BlackCore correctedSituation.guessOnGround(vtol, cg); } - // list from new to old - QWriteLocker lock(&m_lockSituations); - CAircraftSituationList &situationList = m_situationsByCallsign[callsign]; - situationList.push_frontKeepLatestFirstAdjustOffset(correctedSituation, IRemoteAircraftProvider::MaxSituationsPerCallsign); - - // check sort order - Q_ASSERT_X(situationList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order"); - Q_ASSERT_X(situationList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size"); - } - - void CAirspaceMonitor::storeAircraftParts(const CCallsign &callsign, const CAircraftParts &parts) - { - BLACK_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); - if (callsign.isEmpty()) { return; } - - // list sorted from new to old - CAircraftPartsList correctiveParts; - { - QWriteLocker lock(&m_lockParts); - CAircraftPartsList &partsList = m_partsByCallsign[callsign]; - partsList.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxPartsPerCallsign); - - // remove outdated parts (but never remove the most recent one) - IRemoteAircraftProvider::removeOutdatedParts(partsList); - correctiveParts = partsList; - - // aircraft supporting parts - m_aircraftWithParts.insert(callsign); // mark as callsign which supports parts - - // check sort order - Q_ASSERT_X(partsList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order"); - Q_ASSERT_X(partsList.size() <= IRemoteAircraftProvider::MaxPartsPerCallsign, Q_FUNC_INFO, "Wrong size"); - } - - // adjust gnd.flag from parts - if (!correctiveParts.isEmpty()) - { - QWriteLocker lock(&m_lockSituations); - CAircraftSituationList &situationList = m_situationsByCallsign[callsign]; - situationList.adjustGroundFlag(parts); - } + CRemoteAircraftProvider::storeAircraftSituation(correctedSituation); } void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign) diff --git a/src/blackcore/airspacemonitor.h b/src/blackcore/airspacemonitor.h index f44161253..7e10b1f03 100644 --- a/src/blackcore/airspacemonitor.h +++ b/src/blackcore/airspacemonitor.h @@ -12,6 +12,29 @@ #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 #include #include @@ -23,43 +46,6 @@ #include #include -#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/aviation/aircraftpartslist.h" -#include "blackmisc/aviation/aircraftsituationlist.h" -#include "blackmisc/aviation/atcstation.h" -#include "blackmisc/aviation/atcstationlist.h" -#include "blackmisc/aviation/callsign.h" -#include "blackmisc/aviation/callsignset.h" -#include "blackmisc/aviation/flightplan.h" -#include "blackmisc/network/clientprovider.h" -#include "blackmisc/network/userlist.h" -#include "blackmisc/geo/coordinategeodetic.h" -#include "blackmisc/pq/frequency.h" -#include "blackmisc/pq/length.h" -#include "blackmisc/pq/angle.h" -#include "blackmisc/identifiable.h" -#include "blackmisc/identifier.h" - -namespace BlackMisc -{ - namespace Aviation - { - class CAircraftParts; - class CAircraftSituation; - class CComSystem; - class CInformationMessage; - class CTransponder; - } -} - namespace BlackCore { class CAirspaceAnalyzer; @@ -68,12 +54,10 @@ namespace BlackCore //! Keeps track of other entities in the airspace: aircraft, ATC stations, etc. //! Central instance of data for \sa IRemoteAircraftProvider. class BLACKCORE_EXPORT CAirspaceMonitor : - public QObject, - public BlackMisc::Network::IClientProvider, // those data will be provided from the class CAirspaceMonitor - public BlackMisc::Simulation::IRemoteAircraftProvider, // 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::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. - public BlackMisc::CIdentifiable + public BlackMisc::Network::IClientProvider // those data will be provided from the class CAirspaceMonitor { Q_OBJECT Q_INTERFACES(BlackMisc::Network::IClientProvider) @@ -86,44 +70,13 @@ namespace BlackCore //! Constructor CAirspaceMonitor(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraft, INetwork *network, QObject *parent); + //! Members not implenented or fully implenented by CRemoteAircraftProvider //! \ingroup remoteaircraftprovider //! @{ - virtual BlackMisc::Simulation::CSimulatedAircraftList getAircraftInRange() const override; - virtual BlackMisc::Aviation::CCallsignSet getAircraftInRangeCallsigns() const override; - virtual BlackMisc::Simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Simulation::CAircraftModel getAircraftInRangeModelForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual int getAircraftInRangeCount() const override; - virtual bool isAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual bool isVtolAircraft(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override; - virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeValuesBefore = -1) const override; - virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual int getRemoteAircraftSupportingPartsCount() const override; - virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; - virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering) override; - virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) override; - virtual bool updateAircraftNetworkModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) override; - virtual bool updateFastPositionEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enableFastPositonUpdates) override; - virtual bool updateAircraftRendered(const BlackMisc::Aviation::CCallsign &callsign, bool rendered) override; - virtual bool updateAircraftGroundElevation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation) override; - virtual void updateMarkAllAsNotRendered() override; - virtual BlackMisc::CStatusMessageList getAircraftPartsHistory(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual bool isAircraftPartsHistoryEnabled() const override; - virtual void enableAircraftPartsHistory(bool enabled) override; - //! @} - - //! \ingroup remoteaircraftprovider - //! \ingroup reverselookup - //! @{ - virtual void enableReverseLookupMessages(bool enabled) override; - virtual bool isReverseLookupMessagesEnabled() const override; - virtual BlackMisc::CStatusMessageList getReverseLookupMessages(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! @} - - //! \copydoc BlackMisc::IProvider::asQObject 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; @@ -168,15 +121,6 @@ namespace BlackCore //! Test injected aircraft parts void testAddAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts, bool incremental); - //! \copydoc BlackMisc::Simulation::IRemoteAircraftProvider::connectRemoteAircraftProviderSignals - virtual QList connectRemoteAircraftProviderSignals( - QObject *receiver, - std::function situationFunction, - std::function partsFunction, - std::function removedAircraftFunction, - std::function aircraftSnapshotFunction - ) override; - //! Analyzer CAirspaceAnalyzer *analyzer() const { return m_analyzer; } @@ -193,30 +137,12 @@ namespace BlackCore //! Connection status of an ATC station was changed void changedAtcStationOnlineConnectionStatus(const BlackMisc::Aviation::CAtcStation &station, bool isConnected); - //! Aircraft were changed - void changedAircraftInRange(); - //! Raw data as received from network void requestedNewAircraft(const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftDesignator, const QString &airlineDesignator, const QString &livery); - //! A new aircraft appeared - void addedAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); - - //! Parts added - void addedAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts); - - //! Situation added - void addedAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - //! Read for model matching void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); - //! An aircraft disappeared - void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign); - - //! \copydoc CAirspaceAnalyzer::airspaceAircraftSnapshot - void airspaceAircraftSnapshot(const BlackMisc::Simulation::CAirspaceAircraftSnapshot &snapshot); - private: //! Used to temporary store FsInn data struct FsInnPacket @@ -235,31 +161,14 @@ namespace BlackCore BlackMisc::Aviation::CAtcStationList m_atcStationsOnline; //!< online ATC stations BlackMisc::Aviation::CAtcStationList m_atcStationsBooked; //!< booked ATC stations - BlackMisc::Simulation::CSimulatedAircraftList m_aircraftInRange; //!< aircraft, thread safe access required - QMap m_reverseLookupMessages; - QMap m_aircraftPartsHistory; QMap m_tempFsInnPackets; - // hashs, because not sorted by key but keeping order - CSituationsPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign, thread safe access required - CPartsPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign, thread safe access required - BlackMisc::Aviation::CCallsignSet m_aircraftWithParts; //!< aircraft supporting parts, thread safe access required - QMap 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_enableReverseLookupMsgs = false; //!< shall we log. information about the matching process - bool m_enableAircraftPartsHistory = true; //!< shall we keep a history of aircraft parts bool m_bookingsRequested = false; //!< bookings have been requested, it can happen we receive an BlackCore::Vatsim::CVatsimBookingReader::atcBookingsReadUnchanged signal - // locks - mutable QReadWriteLock m_lockSituations; //!< lock for situations: m_situationsByCallsign - mutable QReadWriteLock m_lockParts; //!< lock for parts: m_partsByCallsign, m_aircraftSupportingParts - mutable QReadWriteLock m_lockAircraft; //!< lock aircraft: m_aircraftInRange - mutable QReadWriteLock m_lockMessages; //!< lock for messages - mutable QReadWriteLock m_lockPartsHistory; //!< lock for aircraft parts - //! Remove ATC online stations void removeAllOnlineAtcStations(); @@ -297,27 +206,14 @@ namespace BlackCore //! \remark sets gnd flag from parts if parts are available void storeAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - //! Store an aircraft part - //! \threadsafe - void storeAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts); + //! 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); - //! Init a new aircraft and add it or update model of existing aircraft - //! \threadsafe - 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 = nullptr); - - //! Update aircraft - //! \threadsafe - int updateAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &vm, bool skipEqualValues = true); - //! Update online stations by callsign int updateOnlineStation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CPropertyIndexVariantMap &vm, bool skipEqualValues = true, bool sendSignal = true); @@ -332,17 +228,6 @@ namespace BlackCore //! \sa reverseLookupModelWithFlightplanData void sendReadyForModelMatching(const BlackMisc::Aviation::CCallsign &callsign, int trial = 1); - //! Reverse lookup messages - //! \threadsafe - //! \ingroup reverselookup - //! @{ - void addReverseLookupMessages(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CStatusMessageList &messages); - void addReverseLookupMessage(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::CStatusMessage &message); - void addReverseLookupMessage( - const BlackMisc::Aviation::CCallsign &callsign, const QString &message, - BlackMisc::CStatusMessage::StatusSeverity severity = BlackMisc::CStatusMessage::SeverityInfo); - //! @} - //! Reverse lookup, if available flight plan data are considered //! \remark this is where a model is created based on network data //! \ingroup reverselookup diff --git a/src/blackcore/network.h b/src/blackcore/network.h index ad4d0bd8c..a2504f40a 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -348,6 +348,16 @@ namespace BlackCore */ virtual void setInterimPositionReceivers(const BlackMisc::Aviation::CCallsignSet &receiver) = 0; + /*! + * Add callsign receiving regular interim position updates. + */ + virtual void addInterimPositionReceiver(const BlackMisc::Aviation::CCallsign &receiver) + { + BlackMisc::Aviation::CCallsignSet set = this->getInterimPositionReceivers(); + set.push_back(receiver); + this->setInterimPositionReceivers(set); + } + /*! * Get the group of callsigns receiving regular interim position updates. */ diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index c14f228ff..ef9cf8acf 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -8,14 +8,459 @@ */ #include "blackmisc/simulation/remoteaircraftprovider.h" +#include "blackmisc/simulation/matchingutils.h" +#include "blackmisc/logmessage.h" +#include "blackmisc/json.h" +#include "blackmisc/verify.h" using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; +using namespace BlackMisc::Json; namespace BlackMisc { namespace Simulation { + const CLogCategoryList &CRemoteAircraftProvider::getLogCategories() + { + static const CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() }; + return cats; + } + + CRemoteAircraftProvider::CRemoteAircraftProvider(QObject *parent) : QObject(parent), CIdentifiable(this) + { } + + CSimulatedAircraftList CRemoteAircraftProvider::getAircraftInRange() const + { + QReadLocker l(&m_lockAircraft); + return m_aircraftInRange; + } + + CCallsignSet CRemoteAircraftProvider::getAircraftInRangeCallsigns() const + { + return this->getAircraftInRange().getCallsigns(); + } + + CSimulatedAircraft CRemoteAircraftProvider::getAircraftInRangeForCallsign(const CCallsign &callsign) const + { + const CSimulatedAircraft aircraft = this->getAircraftInRange().findFirstByCallsign(callsign); + return aircraft; + } + + CAircraftModel CRemoteAircraftProvider::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const + { + const CSimulatedAircraft aircraft(getAircraftInRangeForCallsign(callsign)); // threadsafe + return aircraft.getModel(); + } + + CAircraftSituationList CRemoteAircraftProvider::remoteAircraftSituations(const CCallsign &callsign) const + { + QReadLocker l(&m_lockSituations); + static const CAircraftSituationList empty; + if (!m_situationsByCallsign.contains(callsign)) { return empty; } + return m_situationsByCallsign[callsign]; + } + + int CRemoteAircraftProvider::remoteAircraftSituationsCount(const CCallsign &callsign) const + { + QReadLocker l(&m_lockSituations); + if (!m_situationsByCallsign.contains(callsign)) { return -1; } + return m_situationsByCallsign[callsign].size(); + } + + CAircraftPartsList CRemoteAircraftProvider::remoteAircraftParts(const CCallsign &callsign, qint64 cutoffTimeValuesBefore) const + { + static const CAircraftPartsList empty; + QReadLocker l(&m_lockParts); + if (!m_partsByCallsign.contains(callsign)) { return empty; } + if (cutoffTimeValuesBefore < 0) + { + return m_partsByCallsign[callsign]; + } + else + { + return m_partsByCallsign[callsign].findBefore(cutoffTimeValuesBefore); + } + } + + int CRemoteAircraftProvider::remoteAircraftPartsCount(const CCallsign &callsign, qint64 cutoffTimeValuesBefore) const + { + const int s = this->remoteAircraftParts(callsign, cutoffTimeValuesBefore).size(); + return s; + } + + bool CRemoteAircraftProvider::isRemoteAircraftSupportingParts(const CCallsign &callsign) const + { + QReadLocker l(&m_lockParts); + return m_aircraftWithParts.contains(callsign); + } + + int CRemoteAircraftProvider::getRemoteAircraftSupportingPartsCount() const + { + QReadLocker l(&m_lockParts); + return m_aircraftWithParts.size(); + } + + CCallsignSet CRemoteAircraftProvider::remoteAircraftSupportingParts() const + { + QReadLocker l(&m_lockParts); + return m_aircraftWithParts; + } + + int CRemoteAircraftProvider::getAircraftInRangeCount() const + { + return this->getAircraftInRange().size(); + } + + void CRemoteAircraftProvider::removeAllAircraft() + { + for (const CSimulatedAircraft &aircraft : getAircraftInRange()) + { + const CCallsign cs(aircraft.getCallsign()); + emit this->removedAircraft(cs); + } + + // locked members + { QWriteLocker l(&m_lockParts); m_partsByCallsign.clear(); m_aircraftWithParts.clear(); } + { QWriteLocker l(&m_lockSituations); m_situationsByCallsign.clear(); } + { QWriteLocker l(&m_lockPartsHistory); m_aircraftPartsHistory.clear(); } + { QWriteLocker l(&m_lockMessages); m_reverseLookupMessages.clear(); } + { QWriteLocker l(&m_lockAircraft); m_aircraftInRange.clear(); } + } + + void CRemoteAircraftProvider::removeReverseLookupMessages(const CCallsign &callsign) + { + QWriteLocker l(&m_lockMessages); + m_reverseLookupMessages.remove(callsign); + } + + bool CRemoteAircraftProvider::addNewAircraftInRange(const CSimulatedAircraft &aircraft) + { + if (this->isAircraftInRange(aircraft.getCallsign())) { return false; } + // store + { + QWriteLocker l(&m_lockAircraft); + m_aircraftInRange.push_back(aircraft); + } + emit this->addedAircraft(aircraft); + emit this->changedAircraftInRange(); + return true; + } + + int CRemoteAircraftProvider::updateAircraftInRange(const CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues) + { + Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "Missing callsign"); + int c = 0; + { + QWriteLocker l(&m_lockAircraft); + c = m_aircraftInRange.applyIfCallsign(callsign, vm, skipEqualValues); + } + if (c > 0) + { + emit this->changedAircraftInRange(); + } + return c; + } + + void CRemoteAircraftProvider::storeAircraftSituation(const CAircraftSituation &situation) + { + // list from new to old + QWriteLocker lock(&m_lockSituations); + CAircraftSituationList &situationList = m_situationsByCallsign[situation.getCallsign()]; + situationList.push_frontKeepLatestFirstAdjustOffset(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign); + + // check sort order + Q_ASSERT_X(situationList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order"); + Q_ASSERT_X(situationList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size"); + } + + void CRemoteAircraftProvider::storeAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool removeOutdated) + { + BLACK_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); + if (callsign.isEmpty()) { return; } + + // list sorted from new to old + CAircraftPartsList correctiveParts; + { + QWriteLocker lock(&m_lockParts); + CAircraftPartsList &partsList = m_partsByCallsign[callsign]; + partsList.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxPartsPerCallsign); + + // remove outdated parts (but never remove the most recent one) + if (removeOutdated) { IRemoteAircraftProvider::removeOutdatedParts(partsList); } + correctiveParts = partsList; + + // check sort order + Q_ASSERT_X(partsList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order"); + Q_ASSERT_X(partsList.size() <= IRemoteAircraftProvider::MaxPartsPerCallsign, Q_FUNC_INFO, "Wrong size"); + } + + // adjust gnd.flag from parts + if (!correctiveParts.isEmpty()) + { + QWriteLocker lock(&m_lockSituations); + CAircraftSituationList &situationList = m_situationsByCallsign[callsign]; + situationList.adjustGroundFlag(parts); + } + } + + void CRemoteAircraftProvider::storeAircraftParts(const CCallsign &callsign, const QJsonObject &jsonObject, int currentOffset) + { + const CSimulatedAircraft remoteAircraft(this->getAircraftInRangeForCallsign(callsign)); + const bool isFull = jsonObject.value("is_full_data").toBool(); + + // If we are not yet synchronized, we throw away any incremental packet + if (!remoteAircraft.hasValidCallsign()) { return; } + if (!remoteAircraft.isPartsSynchronized() && !isFull) { return; } + + CAircraftParts parts; + try + { + if (isFull) + { + parts.convertFromJson(jsonObject); + } + else + { + // incremental update + parts = this->remoteAircraftParts(callsign).frontOrDefault(); // latest + const QJsonObject config = applyIncrementalObject(parts.toJson(), jsonObject); + parts.convertFromJson(config); + } + } + catch (const CJsonException &ex) + { + CStatusMessage message = ex.toStatusMessage(this, "Invalid parts packet"); + message.setSeverity(CStatusMessage::SeverityDebug); + CLogMessage::preformatted(message); + } + + // make sure in any case right time + parts.setCurrentUtcTime(); + parts.setTimeOffsetMs(currentOffset); + + // store part history (parts always absolute) + this->storeAircraftParts(callsign, parts, false); + + // update aircraft + { + QWriteLocker l(&m_lockAircraft); + const int c = m_aircraftInRange.setAircraftPartsSynchronized(callsign, parts); + Q_UNUSED(c); + } + + // update parts + { + // aircraft supporting parts + QWriteLocker l(&m_lockParts); + m_aircraftWithParts.insert(callsign); // mark as callsign which supports parts + } + emit this->addedAircraftParts(callsign, parts); + + // history + if (this->isAircraftPartsHistoryEnabled()) + { + const QJsonDocument doc(jsonObject); + const QString partsAsString = doc.toJson(QJsonDocument::Compact); + const CStatusMessage message(getLogCategories(), CStatusMessage::SeverityInfo, callsign.isEmpty() ? callsign.toQString() + ": " + partsAsString.trimmed() : partsAsString.trimmed()); + + QReadLocker l(&m_lockPartsHistory); + if (m_aircraftPartsHistory.contains(callsign)) + { + CStatusMessageList &msgs = m_aircraftPartsHistory[callsign]; + msgs.push_back(message); + } + else + { + m_aircraftPartsHistory.insert(callsign, message); + } + } + } + + bool CRemoteAircraftProvider::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRedering) + { + const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRedering)); + const int c = this->updateAircraftInRange(callsign, vm); + return c > 0; + } + + bool CRemoteAircraftProvider::updateAircraftModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) + { + if (CIdentifiable::isMyIdentifier(originator)) { return false; } + const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexModel, CVariant::from(model)); + const int c = this->updateAircraftInRange(callsign, vm); + return c > 0; + } + + bool CRemoteAircraftProvider::updateAircraftNetworkModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) + { + if (CIdentifiable::isMyIdentifier(originator)) { return false; } + const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexNetworkModel, CVariant::from(model)); + const int c = this->updateAircraftInRange(callsign, vm); + return c > 0; + } + + bool CRemoteAircraftProvider::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates) + { + QWriteLocker l(&m_lockAircraft); + const int c = m_aircraftInRange.setFastPositionUpdates(callsign, enableFastPositonUpdates); + return c > 0; + } + + bool CRemoteAircraftProvider::updateAircraftRendered(const CCallsign &callsign, bool rendered) + { + QWriteLocker l(&m_lockAircraft); + const int c = m_aircraftInRange.setRendered(callsign, rendered); + return c > 0; + } + + bool CRemoteAircraftProvider::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation) + { + if (!this->isAircraftInRange(callsign)) { return false; } + + // update aircraft situation + CAircraftSituationList situations = this->remoteAircraftSituations(callsign); + const int updated = situations.setGroundElevationChecked(elevation); + if (updated < 1) { return false; } + { + QWriteLocker l(&m_lockSituations); + m_situationsByCallsign[callsign] = situations; + } + + QWriteLocker l(&m_lockAircraft); + const int c = m_aircraftInRange.setGroundElevationChecked(callsign, elevation); + return c > 0; + } + + void CRemoteAircraftProvider::updateMarkAllAsNotRendered() + { + QWriteLocker l(&m_lockAircraft); + m_aircraftInRange.markAllAsNotRendered(); + } + + void CRemoteAircraftProvider::enableReverseLookupMessages(bool enabled) + { + QWriteLocker l(&m_lockMessages); + m_enableReverseLookupMsgs = enabled; + } + + bool CRemoteAircraftProvider::isReverseLookupMessagesEnabled() const + { + QReadLocker l(&m_lockMessages); + return m_enableReverseLookupMsgs; + } + + CStatusMessageList CRemoteAircraftProvider::getReverseLookupMessages(const CCallsign &callsign) const + { + QReadLocker l(&m_lockMessages); + return m_reverseLookupMessages.value(callsign); + } + + void CRemoteAircraftProvider::addReverseLookupMessages(const CCallsign &callsign, const CStatusMessageList &messages) + { + if (callsign.isEmpty()) { return; } + if (messages.isEmpty()) { return; } + QWriteLocker l(&m_lockMessages); + if (!m_enableReverseLookupMsgs) { return; } + if (m_reverseLookupMessages.contains(callsign)) + { + CStatusMessageList &msgs = m_reverseLookupMessages[callsign]; + msgs.push_back(messages); + } + else + { + m_reverseLookupMessages.insert(callsign, messages); + } + } + + void CRemoteAircraftProvider::addReverseLookupMessage(const CCallsign &callsign, const CStatusMessage &message) + { + if (callsign.isEmpty()) { return; } + if (message.isEmpty()) { return; } + this->addReverseLookupMessages(callsign, CStatusMessageList({ message })); + } + + void CRemoteAircraftProvider::addReverseLookupMessage(const CCallsign &callsign, const QString &message, CStatusMessage::StatusSeverity severity) + { + if (callsign.isEmpty()) { return; } + if (message.isEmpty()) { return; } + const CStatusMessage m = CMatchingUtils::logMessage(callsign, message, getLogCategories(), severity); + this->addReverseLookupMessage(callsign, m); + } + + void CRemoteAircraftProvider::clear() + { + this->removeAllAircraft(); + } + + CStatusMessageList CRemoteAircraftProvider::getAircraftPartsHistory(const CCallsign &callsign) const + { + QReadLocker l(&m_lockPartsHistory); + return m_aircraftPartsHistory.value(callsign); + } + + bool CRemoteAircraftProvider::isAircraftPartsHistoryEnabled() const + { + QReadLocker l(&m_lockPartsHistory); + return m_enableAircraftPartsHistory; + } + + void CRemoteAircraftProvider::enableAircraftPartsHistory(bool enabled) + { + QWriteLocker l(&m_lockPartsHistory); + m_enableAircraftPartsHistory = enabled; + } + + bool CRemoteAircraftProvider::isAircraftInRange(const CCallsign &callsign) const + { + if (callsign.isEmpty()) { return false; } + QReadLocker l(&m_lockAircraft); + return m_aircraftInRange.containsCallsign(callsign); + } + + bool CRemoteAircraftProvider::isVtolAircraft(const CCallsign &callsign) const + { + if (callsign.isEmpty()) { return false; } + const CSimulatedAircraft aircraft = this->getAircraftInRangeForCallsign(callsign); + return aircraft.isVtol(); + } + + QList CRemoteAircraftProvider::connectRemoteAircraftProviderSignals( + QObject *receiver, + std::function addedSituationFunction, + std::function addedPartsFunction, + std::function removedAircraftFunction, + std::function aircraftSnapshotSlot) + { + Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver"); + + // bind does not allow to define connection type, so we use receiver as workaround + const QMetaObject::Connection uc; // unconnected + const QMetaObject::Connection c1 = addedSituationFunction ? connect(this, &CRemoteAircraftProvider::addedAircraftSituation, receiver, addedSituationFunction, Qt::QueuedConnection) : uc; + Q_ASSERT_X(c1 || !addedSituationFunction, Q_FUNC_INFO, "connect failed"); + const QMetaObject::Connection c2 = addedPartsFunction ? connect(this, &CRemoteAircraftProvider::addedAircraftParts, receiver, addedPartsFunction, Qt::QueuedConnection) : uc; + Q_ASSERT_X(c2 || !addedPartsFunction, Q_FUNC_INFO, "connect failed"); + const QMetaObject::Connection c3 = removedAircraftFunction ? connect(this, &CRemoteAircraftProvider::removedAircraft, receiver, removedAircraftFunction, Qt::QueuedConnection) : uc; + Q_ASSERT_X(c3 || !removedAircraftFunction, Q_FUNC_INFO, "connect failed"); + const QMetaObject::Connection c4 = aircraftSnapshotSlot ? connect(this, &CRemoteAircraftProvider::airspaceAircraftSnapshot, receiver, aircraftSnapshotSlot, Qt::QueuedConnection) : uc; + Q_ASSERT_X(c4 || !aircraftSnapshotSlot, Q_FUNC_INFO, "connect failed"); + return QList({ c1, c2, c3, c4 }); + } + + bool CRemoteAircraftProvider::removeAircraft(const CCallsign &callsign) + { + { QWriteLocker l1(&m_lockParts); m_partsByCallsign.remove(callsign); m_aircraftWithParts.remove(callsign); } + { QWriteLocker l2(&m_lockSituations); m_situationsByCallsign.remove(callsign); } + { QWriteLocker l4(&m_lockPartsHistory); m_aircraftPartsHistory.remove(callsign); } + bool removedCallsign = false; + { + QWriteLocker l(&m_lockAircraft); + const int c = m_aircraftInRange.removeByCallsign(callsign); + removedCallsign = c > 0; + } + return removedCallsign; + } + CSimulatedAircraftList CRemoteAircraftAware::getAircraftInRange() const { Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available"); diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index b3980d2b7..668e00607 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -21,23 +21,19 @@ #include "blackmisc/aviation/callsignset.h" #include "blackmisc/provider.h" #include "blackmisc/blackmiscexport.h" -#include "blackmisc/identifier.h" +#include "blackmisc/identifiable.h" #include #include #include #include +#include #include +#include #include namespace BlackMisc { - namespace Aviation - { - class CAircraftParts; - class CAircraftSituation; - class CCallsign; - } namespace Geo { class CElevationPlane; } namespace Simulation { @@ -54,14 +50,14 @@ namespace BlackMisc static constexpr int DefaultOffsetTimeMs = 6000; //!< \fixme copied from CNetworkVatlib::c_positionTimeOffsetMsec //! Situations per callsign - using CSituationsPerCallsign = QHash; + using CSituationsPerCallsign = QHash; //! Parts per callsign - using CPartsPerCallsign = QHash; + using CPartsPerCallsign = QHash; //! All remote aircraft //! \threadsafe - virtual BlackMisc::Simulation::CSimulatedAircraftList getAircraftInRange() const = 0; + virtual CSimulatedAircraftList getAircraftInRange() const = 0; //! Count remote aircraft //! \threadsafe @@ -69,51 +65,51 @@ namespace BlackMisc //! Unique callsigns for aircraft in range //! \threadsafe - virtual BlackMisc::Aviation::CCallsignSet getAircraftInRangeCallsigns() const = 0; + virtual Aviation::CCallsignSet getAircraftInRangeCallsigns() const = 0; //! Is aircraft in range? //! \threadsafe - virtual bool isAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual bool isAircraftInRange(const Aviation::CCallsign &callsign) const = 0; //! Is VTOL aircraft? //! \threadsafe - virtual bool isVtolAircraft(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual bool isVtolAircraft(const Aviation::CCallsign &callsign) const = 0; //! Current snapshot //! \threadsafe - virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const = 0; + virtual CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const = 0; //! Aircraft for callsign //! \threadsafe - virtual BlackMisc::Simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual CSimulatedAircraft getAircraftInRangeForCallsign(const Aviation::CCallsign &callsign) const = 0; //! Aircraft model for callsign //! \threadsafe - virtual BlackMisc::Simulation::CAircraftModel getAircraftInRangeModelForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual CAircraftModel getAircraftInRangeModelForCallsign(const Aviation::CCallsign &callsign) const = 0; //! Rendered aircraft situations (per callsign, time history) //! \threadsafe - virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual Aviation::CAircraftSituationList remoteAircraftSituations(const Aviation::CCallsign &callsign) const = 0; //! Number of remote aircraft situations for callsign //! \threadsafe - virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual int remoteAircraftSituationsCount(const Aviation::CCallsign &callsign) const = 0; //! All parts (per callsign, time history) //! \threadsafe - virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const = 0; + virtual Aviation::CAircraftPartsList remoteAircraftParts(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const = 0; //! All parts (per callsign, time history) //! \threadsafe - virtual int remoteAircraftPartsCount(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const = 0; + virtual int remoteAircraftPartsCount(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const = 0; //! Is remote aircraft supporting parts? //! \threadsafe - virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const = 0; //! Get the latest aircraft parts (if any, otherwise default) //! \threadsafe - BlackMisc::Aviation::CAircraftParts getLatestAircraftParts(const BlackMisc::Aviation::CCallsign &callsign) const; + Aviation::CAircraftParts getLatestAircraftParts(const Aviation::CCallsign &callsign) const; //! Number of aircraft supporting parts //! \threadsafe @@ -121,15 +117,15 @@ namespace BlackMisc //! Remote aircraft supporting parts. //! \threadsafe - virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const = 0; + virtual Aviation::CCallsignSet remoteAircraftSupportingParts() const = 0; //! Enable/disable rendering //! \threadsafe - virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRendering) = 0; + virtual bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRendering) = 0; //! Rendered? //! \threadsafe - virtual bool updateAircraftRendered(const BlackMisc::Aviation::CCallsign &callsign, bool rendered) = 0; + virtual bool updateAircraftRendered(const Aviation::CCallsign &callsign, bool rendered) = 0; //! Mark all as not rendered //! \threadsafe @@ -137,23 +133,23 @@ namespace BlackMisc //! Change model //! \threadsafe - virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) = 0; + virtual bool updateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) = 0; //! Change network model //! \threadsafe - virtual bool updateAircraftNetworkModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) = 0; + virtual bool updateAircraftNetworkModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) = 0; //! Change fast position updates //! \threadsafe - virtual bool updateFastPositionEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enableFastPositonUpdates) = 0; + virtual bool updateFastPositionEnabled(const Aviation::CCallsign &callsign, bool enableFastPositonUpdates) = 0; //! Ground elevation of aircraft //! \threadsafe - virtual bool updateAircraftGroundElevation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation) = 0; + virtual bool updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const Geo::CElevationPlane &elevation) = 0; //! Get reverse lookup meesages //! \threadsafe - virtual BlackMisc::CStatusMessageList getReverseLookupMessages(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual CStatusMessageList getReverseLookupMessages(const Aviation::CCallsign &callsign) const = 0; //! Enabled reverse lookup logging? //! \threadsafe @@ -165,7 +161,7 @@ namespace BlackMisc //! Get aircraft parts history //! \threadsafe - virtual BlackMisc::CStatusMessageList getAircraftPartsHistory(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + virtual CStatusMessageList getAircraftPartsHistory(const Aviation::CCallsign &callsign) const = 0; //! Is storing aircraft parts history enabled? //! \threadsafe @@ -180,82 +176,247 @@ namespace BlackMisc //! Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly. //! In order to disconnect a list of connections is provided, which have to be disconnected manually. - //! \note receiver is required for connection type + //! \note all connections are normally Qt::QueuedConnection receiver is required for connection type virtual QList connectRemoteAircraftProviderSignals( QObject *receiver, - std::function addedSituationSlot, - std::function addedPartsSlot, - std::function removedAircraftSlot, - std::function aircraftSnapshot + std::function addedSituationSlot, + std::function addedPartsSlot, + std::function removedAircraftSlot, + std::function aircraftSnapshot ) = 0; //! Remove outdated aircraft parts, but never the most recent one static void removeOutdatedParts(Aviation::CAircraftPartsList &partsList); }; + } //s +} // ns + +Q_DECLARE_INTERFACE(BlackMisc::Simulation::IRemoteAircraftProvider, "org.swift-project.iremoteaircraftprovider") + +namespace BlackMisc +{ + namespace Simulation + { + //! Implementaion of the interface, which can also be used for testing + class BLACKMISC_EXPORT CRemoteAircraftProvider : + public QObject, + public IRemoteAircraftProvider, + public CIdentifiable + { + Q_OBJECT + Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider) + + public: + //! Log categories + static const CLogCategoryList &getLogCategories(); + + //! Constructor + CRemoteAircraftProvider(QObject *parent); + + //! \ingroup remoteaircraftprovider + //! @{ + virtual CSimulatedAircraftList getAircraftInRange() const override; + virtual Aviation::CCallsignSet getAircraftInRangeCallsigns() const override; + virtual CSimulatedAircraft getAircraftInRangeForCallsign(const Aviation::CCallsign &callsign) const override; + virtual CAircraftModel getAircraftInRangeModelForCallsign(const Aviation::CCallsign &callsign) const override; + virtual int getAircraftInRangeCount() const override; + virtual bool isAircraftInRange(const Aviation::CCallsign &callsign) const override; + virtual bool isVtolAircraft(const Aviation::CCallsign &callsign) const override; + virtual Aviation::CAircraftSituationList remoteAircraftSituations(const Aviation::CCallsign &callsign) const override; + virtual int remoteAircraftSituationsCount(const Aviation::CCallsign &callsign) const override; + virtual Aviation::CAircraftPartsList remoteAircraftParts(const Aviation::CCallsign &callsign, qint64 cutoffTimeValuesBefore = -1) const override; + virtual int remoteAircraftPartsCount(const Aviation::CCallsign &callsign, qint64 cutoffTimeValuesBefore = -1) const override; + virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const override; + virtual int getRemoteAircraftSupportingPartsCount() const override; + virtual Aviation::CCallsignSet remoteAircraftSupportingParts() const override; + virtual bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRedering) override; + virtual bool updateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) override; + virtual bool updateAircraftNetworkModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) override; + virtual bool updateFastPositionEnabled(const Aviation::CCallsign &callsign, bool enableFastPositonUpdates) override; + virtual bool updateAircraftRendered(const Aviation::CCallsign &callsign, bool rendered) override; + virtual bool updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const Geo::CElevationPlane &elevation) override; + virtual void updateMarkAllAsNotRendered() override; + virtual CStatusMessageList getAircraftPartsHistory(const Aviation::CCallsign &callsign) const override; + virtual bool isAircraftPartsHistoryEnabled() const override; + virtual void enableAircraftPartsHistory(bool enabled) override; + virtual QList connectRemoteAircraftProviderSignals( + QObject *receiver, + std::function addedSituationSlot, + std::function addedPartsSlot, + std::function removedAircraftSlot, + std::function aircraftSnapshotSlot + ) override; + //! @} + + //! \ingroup remoteaircraftprovider + //! \ingroup reverselookup + //! @{ + virtual void enableReverseLookupMessages(bool enabled) override; + virtual bool isReverseLookupMessagesEnabled() const override; + virtual BlackMisc::CStatusMessageList getReverseLookupMessages(const BlackMisc::Aviation::CCallsign &callsign) const override; + //! @} + + //! Reverse lookup messages + //! \threadsafe + //! \ingroup reverselookup + //! @{ + void addReverseLookupMessages(const Aviation::CCallsign &callsign, const CStatusMessageList &messages); + void addReverseLookupMessage(const Aviation::CCallsign &callsign, const CStatusMessage &message); + void addReverseLookupMessage( + const Aviation::CCallsign &callsign, const QString &message, + CStatusMessage::StatusSeverity severity = CStatusMessage::SeverityInfo); + //! @} + + //! \copydoc BlackMisc::IProvider::asQObject + virtual QObject *asQObject() override { return this; } + + //! Clear all data + void clear(); + + signals: + //! A new aircraft appeared + void addedAircraft(const CSimulatedAircraft &remoteAircraft); + + //! Parts added + void addedAircraftParts(const Aviation::CCallsign &callsign, const Aviation::CAircraftParts &parts); + + //! Situation added + void addedAircraftSituation(const Aviation::CAircraftSituation &situation); + + //! Aircraft were changed + void changedAircraftInRange(); + + //! An aircraft disappeared + void removedAircraft(const Aviation::CCallsign &callsign); + + //! \copydoc BlackCore::CAirspaceAnalyzer::airspaceAircraftSnapshot + void airspaceAircraftSnapshot(const BlackMisc::Simulation::CAirspaceAircraftSnapshot &snapshot); + + protected: + //! Remove all aircraft in range + //! \threadsafe + bool removeAircraft(const Aviation::CCallsign &callsign); + + //! Remove all aircraft in range + //! \threadsafe + void removeAllAircraft(); + + //! Remove the lookup messages + //! \threadsafe + void removeReverseLookupMessages(const Aviation::CCallsign &callsign); + + //! Add new aircraft, ignored if aircraft already exists + //! \threadsafe + bool addNewAircraftInRange(const CSimulatedAircraft &aircraft); + + //! Init a new aircraft and add it or update model of existing aircraft + //! \threadsafe + CSimulatedAircraft addOrUpdateAircraftInRange( + const Aviation::CCallsign &callsign, + const QString &aircraftIcao, const QString &airlineIcao, const QString &livery, const QString &modelString, + CAircraftModel::ModelType modelType, + CStatusMessageList *log = nullptr); + + //! Update aircraft + //! \threadsafe + int updateAircraftInRange(const Aviation::CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues = true); + + //! Store an aircraft situation + //! \threadsafe + void storeAircraftSituation(const Aviation::CAircraftSituation &situation); + + //! Store an aircraft part + //! \threadsafe + void storeAircraftParts(const Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts, bool removeOutdated); + + //! Store an aircraft part + //! \threadsafe + void storeAircraftParts(const Aviation::CCallsign &callsign, const QJsonObject &jsonObject, int currentOffset); + + private: + // hashs, because not sorted by key but keeping order + CSituationsPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign, thread safe access required + CPartsPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign, thread safe access required + Aviation::CCallsignSet m_aircraftWithParts; //!< aircraft supporting parts, thread safe access required + + CSimulatedAircraftList m_aircraftInRange; //!< aircraft, thread safe access required + QMap m_reverseLookupMessages; + QMap m_aircraftPartsHistory; + + bool m_enableReverseLookupMsgs = false; //!< shall we log. information about the matching process + bool m_enableAircraftPartsHistory = true; //!< shall we keep a history of aircraft parts + + // locks + mutable QReadWriteLock m_lockSituations; //!< lock for situations: m_situationsByCallsign + mutable QReadWriteLock m_lockParts; //!< lock for parts: m_partsByCallsign, m_aircraftSupportingParts + mutable QReadWriteLock m_lockAircraft; //!< lock aircraft: m_aircraftInRange + mutable QReadWriteLock m_lockMessages; //!< lock for messages + mutable QReadWriteLock m_lockPartsHistory; //!< lock for aircraft parts + }; //! Class which can be directly used to access an \sa IRemoteAircraftProvider object class BLACKMISC_EXPORT CRemoteAircraftAware : public IProviderAware { public: //! \copydoc IRemoteAircraftProvider::getAircraftInRange - BlackMisc::Simulation::CSimulatedAircraftList getAircraftInRange() const; + CSimulatedAircraftList getAircraftInRange() const; //! \copydoc IRemoteAircraftProvider::isAircraftInRange - bool isAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign) const; + bool isAircraftInRange(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::isVtolAircraft - bool isVtolAircraft(const BlackMisc::Aviation::CCallsign &callsign) const; + bool isVtolAircraft(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::getAircraftInRangeCount int getAircraftInRangeCount() const; //! \copydoc IRemoteAircraftProvider::getAircraftInRangeCallsigns - BlackMisc::Aviation::CCallsignSet getAircraftInRangeCallsigns() const; + Aviation::CCallsignSet getAircraftInRangeCallsigns() const; //! \copydoc IRemoteAircraftProvider::getAircraftInRangeForCallsign - BlackMisc::Simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const Aviation::CCallsign &callsign) const; + CSimulatedAircraft getAircraftInRangeForCallsign(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::getAircraftInRangeModelForCallsign - BlackMisc::Simulation::CAircraftModel getAircraftInRangeModelForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; + CAircraftModel getAircraftInRangeModelForCallsign(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::getLatestAirspaceAircraftSnapshot - BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const; + CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const; //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations - BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const; + Aviation::CAircraftSituationList remoteAircraftSituations(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationsCount - int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const; + int remoteAircraftSituationsCount(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::remoteAircraftParts - BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const; + Aviation::CAircraftPartsList remoteAircraftParts(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const; //! \copydoc IRemoteAircraftProvider::remoteAircraftPartsCount - int remoteAircraftPartsCount(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const; + int remoteAircraftPartsCount(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const; //! \copydoc IRemoteAircraftProvider::remoteAircraftSupportingParts - BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const; + Aviation::CCallsignSet remoteAircraftSupportingParts() const; //! \copydoc IRemoteAircraftProvider::isRemoteAircraftSupportingParts - bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const; + bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::getRemoteAircraftSupportingPartsCount int getRemoteAircraftSupportingPartsCount() const; //! \copydoc IRemoteAircraftProvider::updateAircraftEnabled - bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering); + bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRedering); //! \copydoc IRemoteAircraftProvider::updateAircraftModel - bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator); + bool updateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator); //! \copydoc IRemoteAircraftProvider::updateAircraftNetworkModel - bool updateAircraftNetworkModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator); + bool updateAircraftNetworkModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator); //! \copydoc IRemoteAircraftProvider::updateAircraftRendered - bool updateAircraftRendered(const BlackMisc::Aviation::CCallsign &callsign, bool rendered); + bool updateAircraftRendered(const Aviation::CCallsign &callsign, bool rendered); //! \copydoc IRemoteAircraftProvider::updateAircraftGroundElevation - bool updateAircraftGroundElevation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation); + bool updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const Geo::CElevationPlane &elevation); //! \copydoc IRemoteAircraftProvider::updateMarkAllAsNotRendered void updateMarkAllAsNotRendered(); @@ -273,6 +434,4 @@ namespace BlackMisc } // namespace } // namespace -Q_DECLARE_INTERFACE(BlackMisc::Simulation::IRemoteAircraftProvider, "org.swift-project.blackmisc::simulation::iremoteaircraftprovider") - #endif // guard diff --git a/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp b/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp index 2d907d5b0..836957aac 100644 --- a/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp +++ b/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp @@ -10,13 +10,6 @@ #include "blackmisc/aviation/callsign.h" #include "blackmisc/geo/elevationplane.h" #include "blackmisc/simulation/remoteaircraftproviderdummy.h" -#include "blackmisc/collection.h" -#include "blackmisc/compare.h" -#include "blackmisc/dictionary.h" -#include "blackmisc/propertyindexvariantmap.h" -#include "blackmisc/variant.h" -#include -#include using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; @@ -25,227 +18,38 @@ namespace BlackMisc { namespace Simulation { - CRemoteAircraftProviderDummy::CRemoteAircraftProviderDummy(QObject *parent) : QObject(parent) + CRemoteAircraftProviderDummy::CRemoteAircraftProviderDummy(QObject *parent) : CRemoteAircraftProvider(parent) { } - CSimulatedAircraftList CRemoteAircraftProviderDummy::getAircraftInRange() const - { - return m_aircraft; - } - - int CRemoteAircraftProviderDummy::getAircraftInRangeCount() const - { - return m_aircraft.size(); - } - - CCallsignSet CRemoteAircraftProviderDummy::getAircraftInRangeCallsigns() const - { - return m_aircraft.getCallsigns(); - } - - CSimulatedAircraft CRemoteAircraftProviderDummy::getAircraftInRangeForCallsign(const CCallsign &callsign) const - { - return m_aircraft.findFirstByCallsign(callsign); - } - - CAircraftModel CRemoteAircraftProviderDummy::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const - { - return getAircraftInRangeForCallsign(callsign).getModel(); - } - - bool CRemoteAircraftProviderDummy::isAircraftInRange(const CCallsign &callsign) const - { - return m_aircraft.containsCallsign(callsign); - } - - bool CRemoteAircraftProviderDummy::isVtolAircraft(const CCallsign &callsign) const - { - return m_aircraft.findFirstByCallsign(callsign).isVtol(); - } - - CAirspaceAircraftSnapshot CRemoteAircraftProviderDummy::getLatestAirspaceAircraftSnapshot() const - { - return CAirspaceAircraftSnapshot(m_aircraft); - } - - CAircraftPartsList CRemoteAircraftProviderDummy::remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore) const - { - if (cutoffTimeBefore < 0) { return m_parts.value(callsign); } - return m_parts.value(callsign).findBefore(cutoffTimeBefore); - } - - int CRemoteAircraftProviderDummy::remoteAircraftPartsCount(const CCallsign &callsign, qint64 cutoffTimeBefore) const - { - return this->remoteAircraftParts(callsign, cutoffTimeBefore).size(); - } - - CAircraftSituationList CRemoteAircraftProviderDummy::remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const - { - return m_situations.findByCallsign(callsign); - } - - int CRemoteAircraftProviderDummy::remoteAircraftSituationsCount(const CCallsign &callsign) const - { - return remoteAircraftSituations(callsign).size(); - } - - int CRemoteAircraftProviderDummy::getRemoteAircraftSupportingPartsCount() const - { - return m_parts.keys().size(); - } - - CCallsignSet CRemoteAircraftProviderDummy::remoteAircraftSupportingParts() const - { - return CCollection(m_parts.keys()); - } - - bool CRemoteAircraftProviderDummy::isRemoteAircraftSupportingParts(const CCallsign &callsign) const - { - return remoteAircraftParts(callsign).size() > 0; - } - - QList CRemoteAircraftProviderDummy::connectRemoteAircraftProviderSignals( - QObject *receiver, - std::function situationSlot, - std::function partsSlot, - std::function removedAircraftSlot, - std::function aircraftSnapshotSlot - ) - { - Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver"); - QList c( - { - connect(this, &CRemoteAircraftProviderDummy::addedRemoteAircraftSituation, receiver, situationSlot), - connect(this, &CRemoteAircraftProviderDummy::addedRemoteAircraftParts, receiver, partsSlot), - connect(this, &CRemoteAircraftProviderDummy::removedRemoteAircraft, receiver, removedAircraftSlot), - connect(this, &CRemoteAircraftProviderDummy::airspaceAircraftSnapshot, receiver, aircraftSnapshotSlot) - }); - return c; - } - - bool CRemoteAircraftProviderDummy::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering) - { - CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRendering)); - const int n = m_aircraft.applyIfCallsign(callsign, vm); - return n > 0; - } - - bool CRemoteAircraftProviderDummy::updateAircraftModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) - { - Q_UNUSED(originator); - CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexModel, CVariant::from(model)); - const int n = m_aircraft.applyIfCallsign(callsign, vm); - return n > 0; - } - - bool CRemoteAircraftProviderDummy::updateAircraftNetworkModel(const CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) - { - Q_UNUSED(originator); - CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexNetworkModel, CVariant::from(model)); - const int n = m_aircraft.applyIfCallsign(callsign, vm); - return n > 0; - } - - bool CRemoteAircraftProviderDummy::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositionUpdates) - { - CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexFastPositionUpdates, CVariant::fromValue(enableFastPositionUpdates)); - const int n = m_aircraft.applyIfCallsign(callsign, vm); - return n > 0; - } - - bool CRemoteAircraftProviderDummy::updateAircraftRendered(const CCallsign &callsign, bool rendered) - { - CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexRendered, CVariant::fromValue(rendered)); - const int n = m_aircraft.applyIfCallsign(callsign, vm); - return n > 0; - } - - bool CRemoteAircraftProviderDummy::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation) - { - CPropertyIndexVariantMap vm({ CSimulatedAircraft::IndexSituation, CAircraftSituation::IndexGroundElevationPlane }, CVariant::fromValue(elevation)); - const int c = m_aircraft.applyIfCallsign(callsign, vm); - return c > 0; - } - - void CRemoteAircraftProviderDummy::updateMarkAllAsNotRendered() - { - m_aircraft.markAllAsNotRendered(); - } - - CStatusMessageList CRemoteAircraftProviderDummy::getReverseLookupMessages(const CCallsign &callsign) const - { - Q_UNUSED(callsign); - return CStatusMessageList(); - } - - bool CRemoteAircraftProviderDummy::isReverseLookupMessagesEnabled() const - { - return false; - } - - void CRemoteAircraftProviderDummy::enableReverseLookupMessages(bool enabled) - { - Q_UNUSED(enabled); - } - - CStatusMessageList CRemoteAircraftProviderDummy::getAircraftPartsHistory(const CCallsign &callsign) const - { - Q_UNUSED(callsign); - return CStatusMessageList(); - } - - bool CRemoteAircraftProviderDummy::isAircraftPartsHistoryEnabled() const - { - return false; - } - - void CRemoteAircraftProviderDummy::enableAircraftPartsHistory(bool enabled) - { - Q_UNUSED(enabled); - } - void CRemoteAircraftProviderDummy::insertNewSituation(const CAircraftSituation &situation) { - m_situations.push_frontKeepLatestAdjustedFirst(situation); - emit addedRemoteAircraftSituation(situation); + this->storeAircraftSituation(situation); } void CRemoteAircraftProviderDummy::insertNewSituations(const CAircraftSituationList &situations) { for (const CAircraftSituation &situation : situations) { - m_situations.push_frontKeepLatestAdjustedFirst(situation); - QTimer::singleShot(0, this, [ = ] - { - emit this->addedRemoteAircraftSituation(situation); - }); + this->storeAircraftSituation(situation); } } - void CRemoteAircraftProviderDummy::insertNewAircraftParts(const CCallsign &callsign, const CAircraftParts &parts) + void CRemoteAircraftProviderDummy::insertNewAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool removeOutdatedParts) { - m_parts[callsign].push_frontKeepLatestAdjustedFirst(parts); - emit addedRemoteAircraftParts(callsign, parts); + this->storeAircraftParts(callsign, parts, removeOutdatedParts); } - void CRemoteAircraftProviderDummy::insertNewAircraftParts(const CCallsign &callsign, const CAircraftPartsList &partsList) + void CRemoteAircraftProviderDummy::insertNewAircraftParts(const CCallsign &callsign, const CAircraftPartsList &partsList, bool removeOutdatedParts) { - CAircraftPartsList &pl = m_parts[callsign]; for (const CAircraftParts &parts : partsList) { - pl.push_frontKeepLatestAdjustedFirst(parts); - QTimer::singleShot(0, this, [ = ] - { - emit this->addedRemoteAircraftParts(callsign, parts); - }); + this->storeAircraftParts(callsign, parts, removeOutdatedParts); } } - void CRemoteAircraftProviderDummy::clear() + CAirspaceAircraftSnapshot CRemoteAircraftProviderDummy::getLatestAirspaceAircraftSnapshot() const { - m_situations.clear(); - m_parts.clear(); - m_aircraft.clear(); + return CAirspaceAircraftSnapshot(); } } // namespace } // namespace diff --git a/src/blackmisc/simulation/remoteaircraftproviderdummy.h b/src/blackmisc/simulation/remoteaircraftproviderdummy.h index 9585d4831..dbd8ea404 100644 --- a/src/blackmisc/simulation/remoteaircraftproviderdummy.h +++ b/src/blackmisc/simulation/remoteaircraftproviderdummy.h @@ -12,109 +12,39 @@ #ifndef BLACKMISC_SIMULATION_REMOTEAIRCRAFTPROVIDERDUMMY_H #define BLACKMISC_SIMULATION_REMOTEAIRCRAFTPROVIDERDUMMY_H +#include "blackmisc/simulation/airspaceaircraftsnapshot.h" +#include "blackmisc/simulation/remoteaircraftprovider.h" +#include "blackmisc/simulation/simulatedaircraftlist.h" #include "blackmisc/aviation/aircraftpartslist.h" #include "blackmisc/aviation/aircraftsituationlist.h" #include "blackmisc/aviation/callsignset.h" #include "blackmisc/blackmiscexport.h" -#include "blackmisc/identifiable.h" -#include "blackmisc/identifier.h" -#include "blackmisc/simulation/aircraftmodel.h" -#include "blackmisc/simulation/airspaceaircraftsnapshot.h" -#include "blackmisc/simulation/remoteaircraftprovider.h" -#include "blackmisc/simulation/simulatedaircraft.h" -#include "blackmisc/simulation/simulatedaircraftlist.h" - -#include -#include -#include -#include -#include namespace BlackMisc { namespace Simulation { - //! Dummy implementation for testing purpose, not thread safe - class BLACKMISC_EXPORT CRemoteAircraftProviderDummy : - public QObject, - public IRemoteAircraftProvider + //! Dummy implementation for testing purpose + class BLACKMISC_EXPORT CRemoteAircraftProviderDummy : public CRemoteAircraftProvider { - Q_OBJECT - Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider) - public: //! Constructor CRemoteAircraftProviderDummy(QObject *parent = nullptr); //! For testing, add new situation and fire signals - void insertNewSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + //! @{ + void insertNewSituation(const Aviation::CAircraftSituation &situation); + void insertNewSituations(const Aviation::CAircraftSituationList &situations); + void insertNewAircraftParts(const Aviation::CCallsign &callsign, const Aviation::CAircraftParts &parts, bool removeOutdatedParts); + void insertNewAircraftParts(const Aviation::CCallsign &callsign, const Aviation::CAircraftPartsList &partsList, bool removeOutdatedParts); + //! @} - //! For testing, add new situation and fire signals - void insertNewSituations(const BlackMisc::Aviation::CAircraftSituationList &situations); - - //! For testing, add new parts and fire signals - void insertNewAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts); - - //! For testing, add new parts and fire signals - void insertNewAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftPartsList &partsList); - - //! Clear all data - void clear(); - - // Interface overrides - virtual CSimulatedAircraftList getAircraftInRange() const override; - virtual int getAircraftInRangeCount() const override; - virtual Aviation::CCallsignSet getAircraftInRangeCallsigns() const override; - virtual BlackMisc::Simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Simulation::CAircraftModel getAircraftInRangeModelForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual bool isAircraftInRange(const Aviation::CCallsign &callsign) const override; - virtual bool isVtolAircraft(const Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override; - virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const override; - virtual int remoteAircraftPartsCount(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore) const override; - virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const Aviation::CCallsign &callsign) const override; - virtual int remoteAircraftSituationsCount(const Aviation::CCallsign &callsign) const override; - virtual int getRemoteAircraftSupportingPartsCount() const override; - virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; - virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const override; - virtual QList connectRemoteAircraftProviderSignals( - QObject *receiver, - std::function addedSituationSlot, - std::function addedPartsSlot, - std::function removedAircraftSlot, - std::function aircraftSnapshotSlot - ) override; - virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRendering) override; - virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) override; - virtual bool updateAircraftNetworkModel(const Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const BlackMisc::CIdentifier &originator) override; - virtual bool updateFastPositionEnabled(const Aviation::CCallsign &callsign, bool enableFastPositionUpdates) override; - virtual bool updateAircraftRendered(const Aviation::CCallsign &callsign, bool rendered) override; - virtual bool updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation) override; - virtual void updateMarkAllAsNotRendered() override; - virtual BlackMisc::CStatusMessageList getReverseLookupMessages(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual bool isReverseLookupMessagesEnabled() const override; - virtual void enableReverseLookupMessages(bool enabled) override; - virtual BlackMisc::CStatusMessageList getAircraftPartsHistory(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual bool isAircraftPartsHistoryEnabled() const override; - virtual void enableAircraftPartsHistory(bool enabled) override; - - signals: - //! Added situation - void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - - //! Added parts - void addedRemoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts); - - //! Added aircraft - void removedRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign); - - //! New aircraft snapshot - void airspaceAircraftSnapshot(const BlackMisc::Simulation::CAirspaceAircraftSnapshot &snapshot); - - private: - BlackMisc::Simulation::CSimulatedAircraftList m_aircraft; - BlackMisc::Aviation::CAircraftSituationList m_situations; - CPartsPerCallsign m_parts; + //! Members not implenented or fully implenented by CRemoteAircraftProvider + //! \ingroup remoteaircraftprovider + //! @{ + virtual QObject *asQObject() override { return this; } + virtual CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override; + //! @} }; } // namespace } // namespace diff --git a/tests/blackmisc/testinterpolatorlinear.cpp b/tests/blackmisc/testinterpolatorlinear.cpp index 268f73abc..c762bc5ca 100644 --- a/tests/blackmisc/testinterpolatorlinear.cpp +++ b/tests/blackmisc/testinterpolatorlinear.cpp @@ -77,7 +77,7 @@ namespace BlackMiscTest for (int i = partsCount - 1; i >= 0; i--) { CAircraftParts p(getTestParts(i, ts, deltaT)); - provider.insertNewAircraftParts(cs, p); + provider.insertNewAircraftParts(cs, p, false); } // make sure signals are processed, if the interpolator depends on those signals diff --git a/tests/blackmisc/testinterpolatorparts.cpp b/tests/blackmisc/testinterpolatorparts.cpp index 9c406b8fa..7e4cd0200 100644 --- a/tests/blackmisc/testinterpolatorparts.cpp +++ b/tests/blackmisc/testinterpolatorparts.cpp @@ -49,15 +49,17 @@ namespace BlackMiscTest const CAircraftParts p = createTestParts(i, ts, deltaT, true); parts.push_back(p); } + QVERIFY2(parts.size() == number, "Wrong parts size of list"); // interpolation functional check CPartsStatus status; const CInterpolationAndRenderingSetupPerCallsign setup; - qint64 oldestTs = parts.oldestTimestampMsecsSinceEpoch(); + const qint64 oldestTs = parts.oldestTimestampMsecsSinceEpoch(); // Testing for a time >> last time // all on ground flags true - provider.insertNewAircraftParts(cs, parts); // we work with 0 offsets here + provider.insertNewAircraftParts(cs, parts, false); // we work with 0 offsets here + QVERIFY2(provider.remoteAircraftPartsCount(cs) == parts.size(), "Wrong parts size"); CAircraftParts p = interpolator.getInterpolatedParts(farFuture, setup, status); qint64 pTs = p.getAdjustedMSecsSinceEpoch(); QVERIFY2(status.isSupportingParts(), "Should support parts"); @@ -75,7 +77,7 @@ namespace BlackMiscTest provider.clear(); parts.setOnGround(false); - provider.insertNewAircraftParts(cs, parts); // we work with 0 offsets here + provider.insertNewAircraftParts(cs, parts, false); // we work with 0 offsets here p = interpolator.getInterpolatedParts(farFuture, setup, status); pTs = p.getAdjustedMSecsSinceEpoch(); QVERIFY2(status.isSupportingParts(), "Should support parts");