9 #include <QDBusServiceWatcher>
15 #include "dbus/dbus.h"
18 #include "qcompilerdetection.h"
57 using namespace swift::config;
59 using namespace swift::misc::aviation;
60 using namespace swift::misc::network;
61 using namespace swift::misc::physical_quantities;
62 using namespace swift::misc::simulation;
63 using namespace swift::misc::geo;
64 using namespace swift::misc::simulation;
65 using namespace swift::misc::weather;
70 inline const QString &fgswiftbusServiceName()
72 static const QString name(
"org.swift-project.fgswiftbus");
77 namespace swift::simplugin::flightgear
79 int FGSWIFTBUS_API_VERSION = -1;
80 QList<int> incompatibleVersions = { 1, 2 };
85 : CSimulatorPluginCommon(info, ownAircraftProvider, remoteAircraftProvider, clientProvider, parent)
87 m_watcher =
new QDBusServiceWatcher(
this);
88 m_watcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
89 m_watcher->addWatchedService(fgswiftbusServiceName());
90 m_watcher->setObjectName(
"QDBusServiceWatcher");
91 connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered,
this,
92 &CSimulatorFlightgear::onDBusServiceUnregistered, Qt::QueuedConnection);
94 m_fastTimer.setObjectName(this->objectName().append(
":m_fastTimer"));
95 m_slowTimer.setObjectName(this->objectName().append(
":m_slowTimer"));
96 m_pendingAddedTimer.setObjectName(this->objectName().append(
":m_pendingAddedTimer"));
97 connect(&m_fastTimer, &QTimer::timeout,
this, &CSimulatorFlightgear::fastTimerTimeout);
98 connect(&m_slowTimer, &QTimer::timeout,
this, &CSimulatorFlightgear::slowTimerTimeout);
99 connect(&m_pendingAddedTimer, &QTimer::timeout,
this, &CSimulatorFlightgear::addNextPendingAircraft);
100 m_fastTimer.start(100);
101 m_slowTimer.start(1000);
102 m_airportUpdater.start(60 * 1000);
103 m_pendingAddedTimer.start(5000);
106 {
"FG c172p", CAircraftModel::TypeModelMatchingDefaultModel,
"C172",
CAircraftIcaoCode(
"C172",
"L1P") });
107 this->resetFlightgearData();
117 CSimulatorPluginCommon::unload();
124 return QStringLiteral(
"Add-time: %1ms/%2ms").arg(m_statsAddCurrentTimeMs).arg(m_statsAddMaxTimeMs);
129 m_statsAddMaxTimeMs = -1;
130 m_statsAddCurrentTimeMs = -1;
138 return m_flightgearAircraftObjects[callsign].getInterpolationMessages(setup.
getInterpolatorMode());
145 if (!m_trafficProxy) {
return false; }
146 if (!m_flightgearAircraftObjects.contains(callsign)) {
return false; }
157 if (parts.
isNull() && flightgear::FGSWIFTBUS_API_VERSION >= 2)
169 m_aircraftAddedFailed.
clear();
170 CSimulatorPluginCommon::clearAllRemoteAircraftData();
176 if (ident) {
return CTransponder::StateIdent; }
177 if (transponderMode == 0 || transponderMode == 1 || transponderMode == 2) {
return CTransponder::StateStandby; }
178 return CTransponder::ModeC;
184 void CSimulatorFlightgear::fastTimerTimeout()
207 CAltitude::PressureAltitude, CLengthUnit::ft() });
210 situation.
setBank({ m_flightgearData.
rollDeg, CAngleUnit::deg() });
214 CAircraftSituation::FromProvider);
216 if (!m_simulatorPaused)
226 { 0.0, 0.0, 0.0, CSpeedUnit::m_s(), 0.0, 0.0, 0.0, CAngleUnit::rad(), CTimeUnit::s() });
243 com1.setVolumeReceive(qRound(m_flightgearData.
volumeCom1 * 100));
244 const bool changedCom1 = myAircraft.getCom1System() != com1;
248 com2.setVolumeReceive(qRound(m_flightgearData.
volumeCom2 * 100));
249 const bool changedCom2 = myAircraft.getCom2System() != com2;
251 transponder = CTransponder::getStandardTransponder(
253 const bool changedXpr = (myAircraft.getTransponder() != transponder);
255 if (changedCom1 || changedCom2 || changedXpr)
262 void CSimulatorFlightgear::slowTimerTimeout()
280 for (
int engineNumber = 0; engineNumber < m_flightgearData.
enginesN1Percentage.size(); ++engineNumber)
299 this->requestRemoteAircraftDataFromFlightgear();
302 for (CFlightgearMPAircraft &flightgearAircraft : m_flightgearAircraftObjects)
305 const CCallsign cs = flightgearAircraft.getCallsign();
312 flightgearAircraft.setSimulatedAircraft(simulatedAircraft);
317 for (
const CCallsign &cs : invalid) { this->triggerRemoveAircraft(cs, ++i * 100); }
326 QString dbusAddress = m_fgswiftbusServerSetting.
getThreadLocal().getDBusServerAddress();
328 if (CDBusServer::isSessionOrSystemAddress(dbusAddress))
330 m_dBusConnection = QDBusConnection::sessionBus();
331 m_dbusMode = Session;
333 else if (CDBusServer::isQtDBusAddress(dbusAddress))
335 m_dBusConnection = QDBusConnection::connectToPeer(dbusAddress,
"fgswiftbus");
336 if (!m_dBusConnection.isConnected()) {
return false; }
343 const bool s = m_dBusConnection.connect(QString(), DBUS_PATH_LOCAL, DBUS_INTERFACE_LOCAL,
"Disconnected",
this,
344 SLOT(onDBusServiceUnregistered()));
358 &CSimulatorFlightgear::emitOwnAircraftModelChanged);
361 &CSimulatorFlightgear::onRemoteAircraftAdded);
363 &CSimulatorFlightgear::onRemoteAircraftAddingFailed);
364 if (m_watcher) { m_watcher->setConnection(m_dBusConnection); }
375 this->disconnectFromDBus();
376 if (m_watcher) { m_watcher->setConnection(m_dBusConnection); }
377 delete m_serviceProxy;
378 delete m_trafficProxy;
379 m_serviceProxy =
nullptr;
380 m_trafficProxy =
nullptr;
385 void CSimulatorFlightgear::onDBusServiceUnregistered()
387 if (!m_serviceProxy) {
return; }
390 if (m_dbusMode == P2P) { m_dBusConnection.disconnectFromPeer(m_dBusConnection.name()); }
391 m_dBusConnection = QDBusConnection {
"default" };
392 if (m_watcher) { m_watcher->setConnection(m_dBusConnection); }
393 delete m_serviceProxy;
394 delete m_trafficProxy;
395 m_serviceProxy =
nullptr;
396 m_trafficProxy =
nullptr;
400 void CSimulatorFlightgear::emitOwnAircraftModelChanged(
const QString &path,
const QString &filename,
401 const QString &livery,
const QString &icao,
402 const QString &modelString,
const QString &name,
403 const QString &description)
405 CAircraftModel model(modelString, CAircraftModel::TypeOwnSimulatorModel, CSimulatorInfo::XPLANE, name,
407 if (!livery.isEmpty()) { model.setModelString(model.getModelString()); }
408 model.setFileName(path +
"/" + filename);
419 static bool isInFunction =
false;
420 if (isInFunction) {
return; }
424 isInFunction =
false;
435 return m_flightgearAircraftObjects.contains(callsign);
441 if (originator == this->
identifier()) {
return false; }
444 auto com1 = CComSystem::getCom1System({ m_flightgearData.
com1ActiveKhz, CFrequencyUnit::kHz() },
446 auto com2 = CComSystem::getCom2System({ m_flightgearData.
com2ActiveKhz, CFrequencyUnit::kHz() },
448 auto xpdr = CTransponder::getStandardTransponder(
478 if (originator == this->
identifier()) {
return false; }
492 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"thread");
493 Q_ASSERT_X(!newRemoteAircraft.
getCallsign().
isEmpty(), Q_FUNC_INFO,
"empty callsign");
494 Q_ASSERT_X(newRemoteAircraft.
hasModelString(), Q_FUNC_INFO,
"missing model string");
506 if (this->canAddAircraft())
510 const qint64 now = QDateTime::currentMSecsSinceEpoch();
511 m_addingInProgressAircraft.insert(newRemoteAircraft.
getCallsign(), now);
516 CLogMessage(
this).
warning(u
"Model for '%1' has no callsign, maybe using a default model") << callsign;
527 if (flightgear::FGSWIFTBUS_API_VERSION >= 2)
537 m_pendingToBeAddedAircraft.
replaceOrAdd(newRemoteAircraft);
547 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"wrong thread");
548 if (callsign.
isEmpty()) {
return false; }
551 if (!m_flightgearAircraftObjects.contains(callsign) && !m_pendingToBeAddedAircraft.
containsCallsign(callsign) &&
552 !m_addingInProgressAircraft.contains(callsign))
562 if (m_flightgearAircraftObjects.contains(callsign))
577 if (m_addingInProgressAircraft.contains(callsign))
580 QPointer<CSimulatorFlightgear> myself(
this);
582 if (!myself) {
return; }
583 m_addingInProgressAircraft.remove(callsign);
590 m_flightgearAircraftObjects.remove(callsign);
594 return CSimulatorPluginCommon::physicallyRemoveRemoteAircraft(callsign);
600 m_pendingToBeAddedAircraft.
clear();
601 m_addingInProgressAircraft.clear();
602 return CSimulatorPluginCommon::physicallyRemoveAllRemoteAircraft();
610 void CSimulatorFlightgear::updateRemoteAircraft()
612 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"thread");
615 if (remoteAircraftNo < 1) {
return; }
619 const qint64 currentTimestamp = QDateTime::currentMSecsSinceEpoch();
622 PlanesPositions planesPositions;
623 PlanesSurfaces planesSurfaces;
624 PlanesTransponders planesTransponders;
626 uint32_t aircraftNumber = 0;
629 for (
const CFlightgearMPAircraft &flightgearAircraft : std::as_const(m_flightgearAircraftObjects))
631 const CCallsign callsign(flightgearAircraft.getCallsign());
632 const bool hasCallsign = !callsign.isEmpty();
641 if (!callsignsInRange.
contains(callsign)) {
continue; }
643 planesTransponders.callsigns.push_back(callsign.asString());
644 planesTransponders.codes.push_back(flightgearAircraft.getAircraft().getTransponderCode());
646 planesTransponders.idents.push_back(transponderMode == CTransponder::StateIdent);
647 planesTransponders.modeCs.push_back(transponderMode == CTransponder::ModeC);
655 flightgearAircraft.getInterpolation(currentTimestamp, setup, aircraftNumber++);
661 if (updateAllAircraft || !this->
isEqualLastSent(interpolatedSituation))
664 planesPositions.push_back(interpolatedSituation);
679 planesSurfaces.push_back(flightgearAircraft.getCallsign(), parts);
685 if (!planesTransponders.isEmpty() && flightgear::FGSWIFTBUS_API_VERSION >= 2)
690 if (!planesPositions.isEmpty())
692 if (CBuildConfig::isLocalDeveloperDebugBuild())
694 SWIFT_VERIFY_X(planesPositions.hasSameSizes(), Q_FUNC_INFO,
"Mismatching sizes");
699 if (!planesSurfaces.isEmpty() && flightgear::FGSWIFTBUS_API_VERSION >= 2)
708 void CSimulatorFlightgear::requestRemoteAircraftDataFromFlightgear()
716 CCallsignSet callsigns = m_flightgearAircraftObjects.getAllCallsigns();
719 if (!callsigns.
isEmpty()) { this->requestRemoteAircraftDataFromFlightgear(callsigns); }
722 void CSimulatorFlightgear::requestRemoteAircraftDataFromFlightgear(
const CCallsignSet &callsigns)
724 if (callsigns.
isEmpty()) {
return; }
727 QPointer<CSimulatorFlightgear> myself(
this);
730 [=](
const QStringList &callsigns,
const QDoubleList &latitudesDeg,
const QDoubleList &longitudesDeg,
731 const QDoubleList &elevationsMeters,
const QDoubleList &verticalOffsetsMeters) {
732 if (!myself) {
return; }
733 this->updateRemoteAircraftFromSimulator(callsigns, latitudesDeg, longitudesDeg, elevationsMeters,
734 verticalOffsetsMeters);
738 void CSimulatorFlightgear::triggerRequestRemoteAircraftDataFromFlightgear(
const CCallsignSet &callsigns)
740 if (callsigns.
isEmpty()) {
return; }
741 QPointer<CSimulatorFlightgear> myself(
this);
743 if (!myself) {
return; }
744 this->requestRemoteAircraftDataFromFlightgear(callsigns);
748 void CSimulatorFlightgear::updateRemoteAircraftFromSimulator(
const QStringList &callsigns,
749 const QDoubleList &latitudesDeg,
750 const QDoubleList &longitudesDeg,
751 const QDoubleList &elevationsMeters,
752 const QDoubleList &verticalOffsetsMeters)
754 const int size = callsigns.size();
757 if (CBuildConfig::isLocalDeveloperDebugBuild())
759 Q_ASSERT_X(elevationsMeters.size() == size, Q_FUNC_INFO,
"Wrong elevations");
760 Q_ASSERT_X(latitudesDeg.size() == size, Q_FUNC_INFO,
"Wrong latitudesDeg");
761 Q_ASSERT_X(longitudesDeg.size() == size, Q_FUNC_INFO,
"Wrong longitudesDeg");
762 Q_ASSERT_X(verticalOffsetsMeters.size() == size, Q_FUNC_INFO,
"Wrong CG");
766 for (
int i = 0; i < size; i++)
768 const bool emptyCs = callsigns[i].isEmpty();
770 if (emptyCs) {
continue; }
772 if (!m_flightgearAircraftObjects.contains(cs)) {
continue; }
773 const CFlightgearMPAircraft fgAircraft = m_flightgearAircraftObjects[cs];
774 SWIFT_VERIFY_X(fgAircraft.hasCallsign(), Q_FUNC_INFO,
"Need callsign");
775 if (!fgAircraft.hasCallsign()) {
continue; }
778 if (!std::isnan(elevationsMeters[i]))
780 const CAltitude elevationAlt =
CAltitude(elevationsMeters[i], CLengthUnit::m(), CLengthUnit::ft());
782 CLongitude(longitudesDeg[i], CAngleUnit::deg()), elevationAlt,
783 CElevationPlane::singlePointRadius());
786 const double cgValue = verticalOffsetsMeters[i];
798 void CSimulatorFlightgear::disconnectFromDBus()
800 if (m_dBusConnection.isConnected())
802 if (m_trafficProxy) { m_trafficProxy->
cleanup(); }
804 if (m_dbusMode == P2P) { QDBusConnection::disconnectFromPeer(m_dBusConnection.name()); }
805 else { QDBusConnection::disconnectFromBus(m_dBusConnection.name()); }
807 m_dBusConnection = QDBusConnection {
"default" };
810 void CSimulatorFlightgear::onRemoteAircraftAdded(
const QString &callsign)
812 SWIFT_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO,
"Need callsign");
813 if (callsign.isEmpty()) {
return; }
818 bool wasPending =
false;
819 if (m_addingInProgressAircraft.contains(cs))
822 const qint64 wasStartedMs = m_addingInProgressAircraft.value(cs);
823 const qint64 deltaTimeMs = QDateTime::currentMSecsSinceEpoch() - wasStartedMs;
824 m_statsAddCurrentTimeMs = deltaTimeMs;
825 if (deltaTimeMs > m_statsAddMaxTimeMs) { m_statsAddMaxTimeMs = deltaTimeMs; }
826 m_addingInProgressAircraft.remove(cs);
831 CLogMessage(
this).
warning(u
"Aircraft '%1' no longer in range, will be removed") << callsign;
832 this->triggerRemoveAircraft(cs, TimeoutAdding);
841 CLogMessage(
this).
warning(u
"Added callsign '%1' was not in progress anymore. Timeout?") << callsign;
844 const bool rendered =
true;
847 this->triggerRequestRemoteAircraftDataFromFlightgear(cs);
848 this->triggerAddNextPendingAircraft();
850 Q_ASSERT_X(addedRemoteAircraft.
hasCallsign(), Q_FUNC_INFO,
"No callsign");
851 Q_ASSERT_X(addedRemoteAircraft.
getCallsign() == cs, Q_FUNC_INFO,
"No callsign");
852 m_flightgearAircraftObjects.insert(cs,
861 if (reference.
isNull()) {
return false; }
871 static const CAltitude alt(0, CAltitude::MeanSeaLevel, CLengthUnit::ft());
875 using namespace std::placeholders;
879 m_trafficProxy->getElevationAtPosition(callsign, pos.
latitude().
value(CAngleUnit::deg()),
886 void CSimulatorFlightgear::onRemoteAircraftAddingFailed(
const QString &callsign)
888 SWIFT_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO,
"Need callsign");
889 if (callsign.isEmpty()) {
return; }
900 CLogMessage(
this).
warning(u
"Adding '%1' failed, but aircraft no longer in range, will be removed")
904 const bool wasPending = (
static_cast<int>(m_addingInProgressAircraft.remove(cs)) > 0);
909 m_aircraftAddedFailed.
push_back(failedRemoteAircraft);
910 m_pendingToBeAddedAircraft.
replaceOrAdd(failedRemoteAircraft);
912 this->triggerAddNextPendingAircraft();
915 void CSimulatorFlightgear::addNextPendingAircraft()
917 if (m_pendingToBeAddedAircraft.
isEmpty()) {
return; }
920 this->detectTimeoutAdding();
923 if (!this->canAddAircraft()) {
return; }
928 CLogMessage(
this).
info(u
"Adding next pending aircraft '%1', pending %2, in progress %3")
930 << m_addingInProgressAircraft.size();
934 void CSimulatorFlightgear::triggerAddNextPendingAircraft()
936 QPointer<CSimulatorFlightgear> myself(
this);
938 if (!myself) {
return; }
939 this->addNextPendingAircraft();
943 int CSimulatorFlightgear::detectTimeoutAdding()
945 if (m_addingInProgressAircraft.isEmpty()) {
return 0; }
946 const qint64 timeout = QDateTime::currentMSecsSinceEpoch() + TimeoutAdding;
948 const QList<CCallsign> addingCallsigns = m_addingInProgressAircraft.keys();
949 for (
const CCallsign &cs : addingCallsigns)
951 if (m_addingInProgressAircraft.value(cs) < timeout) {
continue; }
955 for (
const CCallsign &cs : std::as_const(timeoutCallsigns))
957 m_addingInProgressAircraft.remove(cs);
961 return timeoutCallsigns.
size();
964 void CSimulatorFlightgear::triggerRemoveAircraft(
const CCallsign &callsign, qint64 deferMs)
966 QPointer<CSimulatorFlightgear> myself(
this);
968 if (!myself) {
return; }
973 QPair<qint64, qint64> CSimulatorFlightgear::minMaxTimestampsAddInProgress()
const
975 static const QPair<qint64, qint64> empty(-1, -1);
976 if (m_addingInProgressAircraft.isEmpty()) {
return empty; }
977 const QList<qint64> ts = m_addingInProgressAircraft.values();
978 const auto mm = std::minmax_element(ts.constBegin(), ts.constEnd());
979 return QPair<qint64, qint64>(*mm.first, *mm.second);
982 bool CSimulatorFlightgear::canAddAircraft()
const
984 if (this->
getModelSet().isEmpty()) {
return false; }
985 if (m_addingInProgressAircraft.isEmpty()) {
return true; }
988 const qint64 now = QDateTime::currentMSecsSinceEpoch();
989 const QPair<qint64, qint64> tsMM = this->minMaxTimestampsAddInProgress();
990 const qint64 deltaLatest = now - tsMM.second;
991 const bool canAdd = (deltaLatest > TimeoutAdding);
1000 return new CSimulatorFlightgear(info, ownAircraftProvider, remoteAircraftProvider, clientProvider,
this);
1006 constexpr
int QueryInterval = 5 * 1000;
1007 m_timer.setInterval(QueryInterval);
1008 m_timer.setObjectName(this->objectName().append(
":m_timer"));
1009 connect(&m_timer, &QTimer::timeout,
this, &CSimulatorFlightgearListener::checkConnection);
1018 if (!m_timer.isActive()) {
return; }
1022 QPointer<CSimulatorFlightgearListener> myself(
this);
1024 if (!myself) {
return; }
1029 void CSimulatorFlightgearListener::checkConnection()
1032 Q_ASSERT_X(!CThreadUtils::thisIsMainThread(), Q_FUNC_INFO,
"Expect to run in background");
1034 QString dbusAddress = m_fgSswiftBusServerSetting.
getThreadLocal().getDBusServerAddress();
1035 if (CDBusServer::isSessionOrSystemAddress(dbusAddress)) { checkConnectionViaSessionBus(); }
1036 else if (CDBusServer::isQtDBusAddress(dbusAddress)) { checkConnectionViaPeer(dbusAddress); }
1039 void CSimulatorFlightgearListener::checkConnectionViaSessionBus()
1041 m_conn = QDBusConnection::sessionBus();
1042 if (!m_conn.isConnected())
1044 m_conn.disconnectFromBus(m_conn.name());
1047 checkConnectionCommon();
1048 m_conn.disconnectFromBus(m_conn.name());
1051 void CSimulatorFlightgearListener::checkConnectionViaPeer(
const QString &address)
1053 m_conn = QDBusConnection::connectToPeer(address,
"fgswiftbus");
1054 if (!m_conn.isConnected())
1057 m_conn.disconnectFromPeer(m_conn.name());
1060 checkConnectionCommon();
1061 m_conn.disconnectFromPeer(m_conn.name());
1064 void CSimulatorFlightgearListener::checkConnectionCommon()
1066 CFGSwiftBusServiceProxy service(m_conn);
1067 CFGSwiftBusTrafficProxy traffic(m_conn);
1069 bool result = service.isValid() && traffic.isValid();
1070 if (!result) {
return; }
1072 flightgear::FGSWIFTBUS_API_VERSION = service.getVersionNumber();
1074 if (flightgear::incompatibleVersions.contains(flightgear::FGSWIFTBUS_API_VERSION))
1076 CLogMessage(
this).
error(u
"This version of swift is not compatible with this Flightgear version. For "
1077 u
"further information check http://wiki.flightgear.org/Swift.");
1080 if (!traffic.initialize())
1082 CLogMessage(
this).
error(u
"Connection to FGSwiftBus successful, but could not initialize FGSwiftBus.");
1086 const MultiplayerAcquireInfo info = traffic.acquireMultiplayerPlanes();
1087 if (!info.hasAcquired)
1089 const QString owner =
1090 info.owner.trimmed().
isEmpty() ? QStringLiteral(
"Some/this plugin/application") : info.owner.trimmed();
1092 u
"Connection to FGSwiftBus successful, but could not acquire multiplayer planes. '%1' has acquired "
1093 u
"them already. Disable '%2' or remove it if not required and reload FGSwiftBus.")
1094 << owner << owner.toLower();
1101 void CSimulatorFlightgearListener::serviceRegistered(
const QString &serviceName)
1104 m_conn.disconnectFromBus(m_conn.name());
1107 void CSimulatorFlightgearListener::fgSwiftBusServerSettingChanged()
Interface to a simulator.
virtual void callbackReceivedRequestedElevation(const swift::misc::geo::CElevationPlane &plane, const swift::misc::aviation::CCallsign &callsign, bool isWater)
A requested elevation has been received.
bool addLoopbackSituation(const swift::misc::aviation::CAircraftSituation &situation)
Add a loopback situation if logging is enabled.
bool isEqualLastSent(const swift::misc::aviation::CAircraftSituation &compare) const
Equal to last sent situation.
bool updateOwnSituationAndGroundElevation(const swift::misc::aviation::CAircraftSituation &situation)
Update own aircraft position and if suitable use it to update ground elevation.
bool isUpdateAllRemoteAircraft(qint64 currentTimestamp=-1) const
Do update all remote aircraft?
virtual bool isShuttingDown() const
Is overall (swift) application shutting down.
void requestedElevation(const swift::misc::aviation::CCallsign &callsign)
Requested elevation, call pending.
bool m_updateRemoteAircraftInProgress
currently updating remote aircraft
void rememberElevationAndSimulatorCG(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, bool likelyOnGroundElevation, const swift::misc::geo::CElevationPlane &elevation, const swift::misc::physical_quantities::CLength &simulatorCG)
Set elevation and CG in the providers and for auto publishing.
bool isAircraftInRangeOrTestMode(const swift::misc::aviation::CCallsign &callsign) const
Test version aware version of isAircraftInRange.
void finishUpdateRemoteAircraftAndSetStatistics(qint64 startTime, bool limited=false)
Update stats and flags.
void reverseLookupAndUpdateOwnAircraftModel(const swift::misc::simulation::CAircraftModel &model)
Set own model.
swift::misc::aviation::CAircraftSituationList getLastSentCanLikelySkipNearGroundInterpolation() const
Last sent situations.
swift::misc::simulation::CAircraftModelList getModelSet() const
Get the model set.
void emitSimulatorCombinedStatus(SimulatorStatus oldStatus=Unspecified)
Emit the combined status.
void logAddingAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft) const
Unified qeeing aircraft message.
swift::misc::simulation::CInterpolationAndRenderingSetupPerCallsign getInterpolationSetupConsolidated(const swift::misc::aviation::CCallsign &callsign, bool forceFullUpdate) const
Consolidate setup with other data like from swift::misc::simulation::IRemoteAircraftProvider.
swift::misc::simulation::CInterpolationLogger m_interpolationLogger
log.interpolation
void aircraftRenderingChanged(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft rendering changed.
virtual bool isShuttingDownOrDisconnected() const
Shutting down or disconnected?
virtual void initSimulatorInternals()
Init the internals info from the simulator.
QString getInvalidSituationLogMessage(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CInterpolationStatus &status, const QString &details={}) const
Info about invalid situation.
void rememberLastSent(const swift::misc::aviation::CAircraftSituation &sent)
Remember as last sent.
Interface to a simulator listener.
const swift::misc::simulation::CSimulatorPluginInfo & getPluginInfo() const
Corresponding info.
void simulatorStarted(const swift::misc::simulation::CSimulatorPluginInfo &info)
Emitted when the listener discovers the simulator running.
virtual bool isShuttingDown() const
Overall (swift) application shutting down.
void start()
Start listening for the simulator to start.
void stop()
Stops listening.
const T & getThreadLocal() const
Read the current value.
size_type size() const
Returns number of elements in the collection.
void remove(const T &object)
Efficient remove using the find and erase of the implementation container. Typically O(log n).
iterator insert(const_iterator hint, const T &value)
For compatibility with std::inserter.
bool isEmpty() const
Synonym for empty.
iterator push_back(const T &value)
Synonym for insert.
const CIdentifier & identifier() const
Get identifier.
Value object encapsulating information identifying a component of a modular distributed swift process...
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
bool contains(const T &object) const
Return true if there is an element equal to given object. Uses the most efficient implementation avai...
size_type size() const
Returns number of elements in the sequence.
void replaceOrAdd(const T &original, const T &replacement)
Replace elements matching the given element. If there is no match, push the new element on the end.
void push_back(const T &value)
Appends an element at the end of the sequence.
reference front()
Access the first element.
void clear()
Removes all elements in the sequence.
bool isEmpty() const
Synonym for empty.
void pop_front()
Removes an element at the front of the sequence.
Streamable status message, e.g.
QString getMessage() const
Message.
Status messages, e.g. from Core -> GUI.
Value object encapsulating information about aircraft's engines.
Value object encapsulating a list of aircraft engines.
Value object for ICAO classification.
const QString & getDesignator() const
Get ICAO designator, e.g. "B737".
Value object encapsulating information of aircraft's parts.
bool isNull() const
NULL parts object?
Value object encapsulating information of an aircraft's situation.
void setPressureAltitude(const CAltitude &altitude)
Set pressure altitude.
void setGroundSpeed(const physical_quantities::CSpeed &groundspeed)
Set ground speed.
bool setGroundElevation(const aviation::CAltitude &altitude, GndElevationInfo info, bool transferred=false)
Elevation of the ground directly beneath at the given situation.
void setBank(const physical_quantities::CAngle &bank)
Set bank (angle)
void setHeading(const CHeading &heading)
Set heading.
void setAltitude(const CAltitude &altitude)
Set altitude.
void setPitch(const physical_quantities::CAngle &pitch)
Set pitch.
virtual bool isNull() const
Null situation.
void setVelocity(const CAircraftVelocity &velocity)
Set 6DOF velocity.
void setPosition(const geo::CCoordinateGeodetic &position)
Set position.
const QString & getDesignator() const
Get airline, e.g. "DLH".
Altitude as used in aviation, can be AGL or MSL altitude.
Value object encapsulating information of a callsign.
const QString & asString() const
Get callsign (normalized)
bool isEmpty() const
Is empty?
Value object for a set of callsigns.
QStringList getCallsignStrings(bool sorted=false) const
The callsign strings.
const QString & getCombinedCode() const
Combined code.
swift::misc::physical_quantities::CFrequency getFrequencyStandby() const
Standby frequency.
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
Active frequency.
TransponderMode
Transponder codes.
OBJ findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound={}) const
Find the first aircraft by callsign, if none return given one.
int removeByCallsign(const CCallsign &callsign)
Remove all objects with callsign.
swift::misc::aviation::CCallsignSet getCallsigns() const
All callsigns.
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
virtual CLatitude latitude() const
Latitude.
virtual const aviation::CAltitude & geodeticHeight() const
Height, ellipsoidal or geodetic height (used in GPS)
void setGeodeticHeight(const aviation::CAltitude &height)
Set height (ellipsoidal or geodetic height)
virtual CLongitude longitude() const
Longitude.
Plane of same elevation, can be a single point or larger area (e.g. airport)
Geodetic coordinate, a position in 3D space relative to the reference geoid.
bool hasMSLGeodeticHeight() const
Geodetic height not null and aviation::CAltitude::MeanSeaLevel.
virtual bool isNull() const
Is null, means vector x, y, z == 0.
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information of a text message.
const QString & getMessage() const
Get message.
const aviation::CCallsign & getSenderCallsign() const
Get callsign (from)
Direct in memory access to client (network client) data.
Physical unit length (length)
Specialized class for distance units (meter, foot, nautical miles).
int valueInteger(MU unit) const
As integer value.
double value(MU unit) const
Value in given unit.
Aircraft model (used by another pilot, my models on disk)
const aviation::CCallsign & getCallsign() const
Corresponding callsign if applicable.
const aviation::CLivery & getLivery() const
Get livery.
void setCallsign(const aviation::CCallsign &callsign)
Corresponding callsign if applicable.
const QString & getFileName() const
File name (corresponding data for simulator, only available if representing simulator model.
InterpolatorMode getInterpolatorMode() const
Interpolator mode.
Value object for interpolator and rendering per callsign.
const CInterpolationStatus & getInterpolationStatus() const
Get status.
const CPartsStatus & getPartsStatus() const
Get status.
bool hasValidSituation() const
Is the corresponding position valid?
bool updateOwnParts(const aviation::CAircraftParts &parts)
Update own parts.
bool updateCockpit(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
CSimulatedAircraft getOwnAircraft() const
Own aircraft.
bool isSupportingParts() const
Supporting parts.
aviation::CCallsignSet getAircraftInRangeCallsigns() const
Unique callsigns for aircraft in range.
CSimulatedAircraftList getAircraftInRange() const
All remote aircraft.
int getAircraftInRangeCount() const
Count remote aircraft.
CSimulatedAircraft getAircraftInRangeForCallsign(const aviation::CCallsign &callsign) const
Aircraft for callsign.
bool updateAircraftRendered(const aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
Comprehensive information of an aircraft.
bool hasModelString() const
Has model string?
aviation::CTransponder::TransponderMode getTransponderMode() const
Get transponder mode.
const aviation::CAircraftSituation & getSituation() const
Get situation.
const aviation::CComSystem & getCom2System() const
Get COM2 system.
bool setRendered(bool rendered)
Rendered?
qint32 getTransponderCode() const
Get transponder code.
bool hasCallsign() const
Callsign not empty, no further checks.
const aviation::CCallsign & getCallsign() const
Get callsign.
const aviation::CAircraftIcaoCode & getAircraftIcaoCode() const
Get aircraft ICAO info.
bool hasChangedCockpitData(const aviation::CComSystem &com1, const aviation::CComSystem &com2, const aviation::CTransponder &transponder) const
Changed cockpit data?
const simulation::CAircraftModel & getModel() const
Get model (model used for mapping)
QString getCallsignAsString() const
Get callsign.
const aviation::CComSystem & getCom1System() const
Get COM1 system.
const aviation::CAirlineIcaoCode & getAirlineIcaoCode() const
Airline ICAO code if any.
const aviation::CAircraftParts & getParts() const
Get aircraft parts.
Q_REQUIRED_RESULT CSimulatedAircraftList findByRendered(bool rendered) const
Rendered / not rendered aircraft.
Describing a simulator plugin.
aviation::CCallsignSet getLogCallsigns() const
All callsigns marked to be logged.
Direct threadsafe in memory access to own aircraft.
Direct thread safe in memory access to remote aircraft.
void setSimulatorDetails(const QString &name, const QString &details, const QString &version)
Set version and simulator details from running simulator.
void setDefaultModel(const CAircraftModel &defaultModel)
Default model.
Proxy object connected to a real FGSwiftBus::CService object via DBus.
void getOwnAircraftSituationData(FlightgearData *o_flightgearData)
Get own aircraft situation data.
QString getAircraftModelFilename() const
Get base filename of current aircraft model.
void getGroundElevationAsync(double *o_groundElevation)
Get ground elevation [m] for current airplane position.
void cancelAllPendingAsyncCalls()
Cancel all current async slot calls.
void getAircraftModelPathAsync(QString *o_modelPath)
Get full path to current aircraft model.
void setCom2StandbyKhz(int freq)
Set the current COM2 standby frequency in kHz.
QString getAircraftModelString() const
Get canonical swift model string of current aircraft model.
QString getAircraftName() const
Get name of current aircraft model.
QString getAircraftIcaoCode() const
Get the ICAO code of the current aircraft model.
void getCom2StandbyKhzAsync(int *o_com2Standby)
Get the current COM2 standby frequency in kHz.
void getCom2VolumeAsync(double *o_com2Volume)
Get Com2 volume [0..1].
void setCom1StandbyKhz(int freq)
Set the current COM1 standby frequency in kHz.
void getStrobeLightsOnAsync(bool *o_strobeLightsOn)
Get whether strobe lights are on.
void getCom1VolumeAsync(double *o_com1Volume)
Get Com1 volume [0..1].
QString getAircraftLivery() const
Get current aircraft livery.
void getLandingLightsOnAsync(bool *o_landingLightsOn)
Get whether landing lights are on.
void getTaxiLightsOnAsync(bool *o_taxiLightsOn)
Get whether taxi lights are on.
void getTransponderModeAsync(int *o_xpdrMode)
Get the current transponder mode (depends on the aircraft, 0 and 1 usually mean standby,...
void getNavLightsOnAsync(bool *o_navLightsOn)
Get whether nav lights are on.
void getAllWheelsOnGroundAsync(bool *o_allWheels)
Get whether all wheels are on the ground.
void getCom2ActiveKhzAsync(int *o_com2Active)
Get the current COM2 active frequency in kHz.
QString getAircraftDescription() const
Get the description of the current aircraft model.
void getCom1ActiveKhzAsync(int *o_com1Active)
Get the current COM1 active frequency in kHz.
void setCom2ActiveKhz(int freq)
Set the current COM2 active frequency in kHz.
void isPausedAsync(bool *o_paused)
True if sim is paused.
void getAircraftIcaoCodeAsync(QString *o_icaoCode)
Get the ICAO code of the current aircraft model.
void getTransponderIdentAsync(bool *o_ident)
Get whether we are currently squawking ident.
void setTransponderCode(int code)
Set the current transponder code in decimal.
void getGearDeployRatioAsync(double *o_gearDeployRatio)
Get gear deploy ratio, where 0 is up and 1 is down.
void getSpeedBrakeRatioAsync(double *o_speedBrakeRatio)
Get the ratio how much the speedbrakes surfaces are extended (0.0 is fully retracted,...
void aircraftModelChanged(const QString &path, const QString &filename, const QString &livery, const QString &icao, const QString &modelString, const QString &name, const QString &description)
Own aircraft model changed.
void getBeaconLightsOnAsync(bool *o_beaconLightsOn)
Get whether beacon lights are on.
void getFlapsDeployRatioAsync(double *o_flapsDeployRatio)
Get flaps deploy ratio, where 0.0 is flaps fully retracted, and 1.0 is flaps fully extended.
void getTransponderCodeAsync(int *o_xpdrCode)
Get the current transponder code in decimal.
void getEngineN1PercentageAsync(QList< double > *o_engineN1Percentage)
Get the N1 speed as percent of max (per engine)
void getCom1StandbyKhzAsync(int *o_com1Standby)
Get the current COM1 standby frequency in kHz.
void setTransponderMode(int mode)
Set the current transponder mode (depends on the aircraft, 0 and 1 usually mean standby,...
QString getAircraftModelPath() const
Get full path to current aircraft model.
void setCom1ActiveKhz(int freq)
Set the current COM1 active frequency in kHz.
bool isValid() const
Does the remote object exist?
void getOwnAircraftVelocityData(FlightgearData *o_flightgearData)
Get own aircraft velocity data.
void addTextMessage(const QString &text)
Add a text message to the on-screen display.
Proxy object connected to a real FGSwiftBus::CTraffic object via DBus.
void remoteAircraftAdded(const QString &callsign)
Remote aircraft successfully added.
void setPlanesTransponders(const swift::simplugin::flightgear::PlanesTransponders &planesTransponders)
Set the transponders of multiple traffic aircrafts.
void setPlanesSurfaces(const swift::simplugin::flightgear::PlanesSurfaces &planesSurfaces)
Set the surfaces of multiple traffic aircrafts.
void cleanup()
Reverse the actions of initialize().
void remoteAircraftAddingFailed(const QString &callsign)
Remote aircraft adding failed.
void addPlane(const QString &callsign, const QString &modelName, const QString &aircraftIcao, const QString &airlineIcao, const QString &livery)
Introduce a new traffic aircraft.
bool isValid() const
Does the remote object exist?
void simFrame()
Simulator frame.
void getRemoteAircraftData(const QStringList &callsigns, const RemoteAircraftDataCallback &setter) const
Get remote aircrafts data (lat, lon, elevation and CG)
void removePlane(const QString &callsign)
Remove a traffic aircraft.
void setPlanesPositions(const swift::simplugin::flightgear::PlanesPositions &planesPositions)
Set the position of multiple traffic aircrafts.
void removeAllPlanes()
Remove all traffic aircraft.
Class representing a Flightgear multiplayer aircraft.
const swift::misc::simulation::CSimulatedAircraft & getAircraft() const
Simulated aircraft (as added)
virtual swift::core::ISimulator * create(const swift::misc::simulation::CSimulatorPluginInfo &info, swift::misc::simulation::IOwnAircraftProvider *ownAircraftProvider, swift::misc::simulation::IRemoteAircraftProvider *remoteAircraftProvider, swift::misc::network::IClientProvider *clientProvider)
Create a new instance of a driver.
virtual swift::misc::CStatusMessageList getInterpolationMessages(const swift::misc::aviation::CCallsign &callsign) const
Interpolation messages for callsign.
virtual bool updateOwnSimulatorSelcal(const swift::misc::aviation::CSelcal &selcal, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
virtual void displayTextMessage(const swift::misc::network::CTextMessage &message) const
Display a text message.
virtual bool physicallyAddRemoteAircraft(const swift::misc::simulation::CSimulatedAircraft &newRemoteAircraft)
Add new remote aircraft physically to the simulator.
virtual bool updateOwnSimulatorCockpit(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
virtual int physicallyRemoveAllRemoteAircraft()
Remove all remote aircraft and their data via ISimulator::clearAllRemoteAircraftData.
virtual bool requestElevation(const swift::misc::geo::ICoordinateGeodetic &reference, const swift::misc::aviation::CCallsign &callsign)
Request elevation, there is no guarantee the requested elevation will be available in the provider.
virtual bool physicallyRemoveRemoteAircraft(const swift::misc::aviation::CCallsign &callsign)
Remove remote aircraft from simulator.
virtual bool isConnected() const
Are we connected to the simulator?
CSimulatorFlightgear(const swift::misc::simulation::CSimulatorPluginInfo &info, swift::misc::simulation::IOwnAircraftProvider *ownAircraftProvider, swift::misc::simulation::IRemoteAircraftProvider *remoteAircraftProvider, swift::misc::network::IClientProvider *clientProvider, QObject *parent=nullptr)
Constructor.
virtual swift::misc::aviation::CCallsignSet physicallyRenderedAircraft() const
Physically rendered (displayed in simulator) This shall only return aircraft handled in the simulator...
virtual void resetAircraftStatistics()
Reset the statistics.
virtual ~CSimulatorFlightgear()
Dtor.
virtual void displayStatusMessage(const swift::misc::CStatusMessage &message) const
Display a status message in the simulator.
virtual QString getStatisticsSimulatorSpecific() const
Allows to print out simulator specific statistics.
virtual bool disconnectFrom()
Disconnect from simulator.
virtual bool isPhysicallyRenderedAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is the aircraft rendered (displayed in simulator)? This shall only return true if the aircraft is rea...
virtual bool connectTo()
Connect to simulator.
virtual void clearAllRemoteAircraftData()
Clear all aircraft related data, but do not physically remove the aircraft.
virtual void unload()
Driver will be unloaded.
virtual bool testSendSituationAndParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CAircraftParts &parts)
Send situation/parts for testing.
virtual void stopImpl()
Plugin specific implementation to stop listener.
CSimulatorFlightgearListener(const swift::misc::simulation::CSimulatorPluginInfo &info)
Constructor.
virtual void startImpl()
Plugin specific implementation to start listener.
virtual void checkImpl()
Plugin specific implementation to check.
Backend services of the swift project, like dealing with the network or the simulators.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
QString aircraftModelPath
Aircraft model path.
int com2StandbyKhz
COM2 standby [kHz].
double pressureAltitudeFt
Pressure altitude [inhg].
double pitchDeg
Pitch [deg].
QList< double > enginesN1Percentage
N1 per engine [%].
double longitudeDeg
Latitude [deg].
double latitudeDeg
Longitude [deg].
bool xpdrIdent
Is transponder in ident?
int com1StandbyKhz
COM1 standby [kHz].
int com1ActiveKhz
COM1 active [kHz].
double volumeCom1
Volume com1 [0..1].
double rollRateRadPerSec
Roll angular velocity [rad/s].
double groundElevation
Ground Elevation [m].
int xpdrCode
Transpondder code.
double velocityZMs
z velocity [m/s]
double pitchRateRadPerSec
Pitch angular velocity [rad/s].
double groundspeedKts
Ground speed [kts].
bool navLightsOn
NAV lights on?
bool taxiLightsOn
Taxi lights on?
double trueHeadingDeg
True heading [deg].
double gearReployRatio
Gear deployment ratio [%].
int xpdrMode
Transponder mode (off=0,stdby=1-2, >2 on)
bool landingLightsOn
Landing lights on?
bool onGroundAll
All wheels on ground?
double velocityYMs
y velocity [m/s]
QString aircraftIcaoCode
Aircraft ICAO code.
double velocityXMs
x velocity [m/s]
double speedBrakeRatio
Speed break ratio [%].
bool strobeLightsOn
Strobe lights on?
double yawRateRadPerSec
Yaw angular velocity [rad/s].
double volumeCom2
Volume com2 [0..1].
double rollDeg
Roll [deg].
int com2ActiveKhz
COM2 active [kHz].
double flapsReployRatio
Flaps deployment ratio [%].
bool beaconLightsOn
Beacon lights on?
double altitudeFt
Altitude [ft].
void push_back(const swift::misc::aviation::CAircraftSituation &situation)
Push back the latest situation.
void push_back(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftParts &parts)
Push back the latest parts.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.