mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-08-07 18:15:51 +08:00
feat: Basic configuration for an ACARS protocol
This commit is contained in:
@@ -115,6 +115,12 @@ namespace swift::core::context
|
||||
return m_ownAircraft.getParts();
|
||||
}
|
||||
|
||||
CAircraftAcars CContextOwnAircraft::getOwnAircraftAcars() const
|
||||
{
|
||||
QReadLocker l(&m_lockAircraft);
|
||||
return m_ownAircraft.getAcars();
|
||||
}
|
||||
|
||||
CAircraftModel CContextOwnAircraft::getOwnAircraftModel() const
|
||||
{
|
||||
QReadLocker l(&m_lockAircraft);
|
||||
@@ -242,6 +248,15 @@ namespace swift::core::context
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CContextOwnAircraft::updateOwnAcars(const CAircraftAcars &acars)
|
||||
{
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
const bool changed = (m_ownAircraft.getAcars() != acars);
|
||||
if (!changed) { return false; }
|
||||
m_ownAircraft.setAcars(acars);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CContextOwnAircraft::updateOwnCG(const CLength &cg)
|
||||
{
|
||||
QWriteLocker l(&m_lockAircraft);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "core/context/contextownaircraft.h"
|
||||
#include "core/corefacadeconfig.h"
|
||||
#include "core/swiftcoreexport.h"
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircraftparts.h"
|
||||
#include "misc/aviation/aircraftsituationlist.h"
|
||||
#include "misc/aviation/airlineicaocode.h"
|
||||
@@ -88,6 +89,10 @@ namespace swift::core
|
||||
//! \ingroup ownaircraftprovider
|
||||
swift::misc::aviation::CAircraftParts getOwnAircraftParts() const override;
|
||||
|
||||
//! \copydoc swift::misc::simulation::IOwnAircraftProvider::getOwnAircraftAcars
|
||||
//! \ingroup ownaircraftprovider
|
||||
swift::misc::aviation::CAircraftAcars getOwnAircraftAcars() const override;
|
||||
|
||||
//! \copydoc swift::misc::simulation::IOwnAircraftProvider::getOwnAircraftModel
|
||||
//! \ingroup ownaircraftprovider
|
||||
swift::misc::simulation::CAircraftModel getOwnAircraftModel() const override;
|
||||
@@ -110,6 +115,10 @@ namespace swift::core
|
||||
//! \ingroup ownaircraftprovider
|
||||
bool updateOwnParts(const swift::misc::aviation::CAircraftParts &parts) override;
|
||||
|
||||
//! \copydoc swift::misc::simulation::IOwnAircraftProvider::updateOwnAcars
|
||||
//! \ingroup ownaircraftprovider
|
||||
bool updateOwnAcars(const swift::misc::aviation::CAircraftAcars &acars) override;
|
||||
|
||||
//! \copydoc swift::misc::simulation::IOwnAircraftProvider::updateOwnParts
|
||||
//! \ingroup ownaircraftprovider
|
||||
bool updateOwnCG(const swift::misc::physical_quantities::CLength &cg) override;
|
||||
|
||||
@@ -81,7 +81,8 @@ namespace swift::core::fsd
|
||||
INF, /*!< Supervisor Privileged Information Request. */
|
||||
FP, /*!< Send Cached Flight Plan. Response by SERVER. */
|
||||
AircraftConfig, /*!< Aircraft Configuration */
|
||||
EuroscopeSimData /*!< Broadcast to announce we request SIMDATA packets. */
|
||||
EuroscopeSimData, /*!< Broadcast to announce we request SIMDATA packets. */
|
||||
Acars /*!< Broadcast to announce we request ACARS packets. */
|
||||
// There are many more which are only relevant to ATC clients.
|
||||
};
|
||||
|
||||
|
||||
@@ -110,6 +110,9 @@ namespace swift::core::fsd
|
||||
m_fsdSendMessageTimer.setObjectName(this->objectName().append(":m_fsdSendMessageTimer"));
|
||||
connect(&m_fsdSendMessageTimer, &QTimer::timeout, this, [this]() { this->sendQueuedMessage(); });
|
||||
|
||||
m_fsdSendAcarsTimer.setObjectName(this->objectName().append(":m_fsdSendAcarsTimer"));
|
||||
connect(&m_fsdSendAcarsTimer, &QTimer::timeout, this, [this]() { this->sendAcarsMessage(); });
|
||||
|
||||
fsdMessageSettingsChanged();
|
||||
|
||||
if (!m_statistics &&
|
||||
@@ -818,6 +821,53 @@ namespace swift::core::fsd
|
||||
}
|
||||
}
|
||||
|
||||
void CFSDClient::sendAcarsMessage()
|
||||
{
|
||||
// TODO TZ
|
||||
if (getServer().getEcosystem().isSystem(CEcosystem::VATSIM)) return;
|
||||
|
||||
if (this->getConnectionStatus().isDisconnected() && !m_unitTestMode) { return; }
|
||||
|
||||
if (m_loginMode == CLoginMode::Observer)
|
||||
{
|
||||
return; // observers don't send ACARS
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->isAcarsSendEnabled())
|
||||
{
|
||||
// TODO TZ
|
||||
const CAircraftAcars currentAcars(this->getOwnAircraftAcars());
|
||||
const QJsonObject previousAcars = m_sentAcars.toJson();
|
||||
const QJsonObject currentAcarsJson = currentAcars.toJson();
|
||||
const QJsonObject incrementalAcars = getIncrementalObject(previousAcars, currentAcarsJson);
|
||||
|
||||
m_sentAcarsCount++;
|
||||
QString dataStr = "";
|
||||
|
||||
if (m_sentAcarsCount > 59)
|
||||
{
|
||||
dataStr = convertToUnicodeEscaped(
|
||||
QJsonDocument(QJsonObject { { "full", currentAcarsJson } }).toJson(QJsonDocument::Compact));
|
||||
m_sentAcarsCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it hasn't changed, return
|
||||
if (m_sentAcars == currentAcars) { return; }
|
||||
dataStr = convertToUnicodeEscaped(QJsonDocument(QJsonObject { { "incremental", incrementalAcars } })
|
||||
.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
const QString receiver = "SERVER";
|
||||
const ClientQuery clientQuery(getOwnCallsignAsString(), receiver, ClientQueryType::Acars, { dataStr });
|
||||
sendQueuedMessage(clientQuery);
|
||||
|
||||
m_sentAcars = currentAcars;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFSDClient::sendFsdMessage(const QString &message)
|
||||
{
|
||||
// UNIT tests
|
||||
@@ -1026,6 +1076,8 @@ namespace swift::core::fsd
|
||||
|
||||
void CFSDClient::sendIncrementalAircraftConfig()
|
||||
{
|
||||
// TODO TZ hier abschreiben
|
||||
|
||||
if (!m_unitTestMode && (!this->isConnected() || !this->getSetupForServer().sendAircraftParts())) { return; }
|
||||
const CAircraftParts currentParts(this->getOwnAircraftParts());
|
||||
|
||||
@@ -1948,6 +2000,7 @@ namespace swift::core::fsd
|
||||
m_atcStations.clear();
|
||||
m_queuedFsdMessages.clear();
|
||||
m_sentAircraftConfig = CAircraftParts::null();
|
||||
m_sentAcars = CAircraftAcars::null();
|
||||
m_loginSince = -1;
|
||||
}
|
||||
|
||||
@@ -2000,6 +2053,12 @@ namespace swift::core::fsd
|
||||
return (d & CFsdSetup::SendVisualPositions);
|
||||
}
|
||||
|
||||
bool CFSDClient::isAcarsSendEnabled() const
|
||||
{
|
||||
const CFsdSetup::SendReceiveDetails d = this->getSetupForServer().getSendReceiveDetails();
|
||||
return (d & CFsdSetup::SendAcars);
|
||||
}
|
||||
|
||||
const CFsdSetup &CFSDClient::getSetupForServer() const { return m_server.getFsdSetup(); }
|
||||
|
||||
void CFSDClient::maybeHandleAtisReply(const CCallsign &sender, const CCallsign &receiver, const QString &message)
|
||||
@@ -2336,6 +2395,7 @@ namespace swift::core::fsd
|
||||
m_positionUpdateTimer.start(c_updatePositionIntervalMsec);
|
||||
m_scheduledConfigUpdate.start(c_processingIntervalMsec);
|
||||
m_fsdSendMessageTimer.start(c_sendFsdMsgIntervalMsec);
|
||||
m_fsdSendAcarsTimer.start(c_sendAcarsIntervalMsec);
|
||||
m_queuedFsdMessages.clear(); // clear everything before the timer is started
|
||||
|
||||
// interim positions
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "core/fsd/messagebase.h"
|
||||
#include "core/swiftcoreexport.h"
|
||||
#include "core/vatsim/vatsimsettings.h"
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircrafticaocode.h"
|
||||
#include "misc/aviation/atcstationlist.h"
|
||||
#include "misc/aviation/callsign.h"
|
||||
@@ -365,6 +366,7 @@ namespace swift::core::fsd
|
||||
//
|
||||
void sendMessageString(const QString &message);
|
||||
void sendQueuedMessage();
|
||||
void sendAcarsMessage();
|
||||
//! @}
|
||||
|
||||
//! @{
|
||||
@@ -394,6 +396,14 @@ namespace swift::core::fsd
|
||||
this->sendMessageString(messageToFSDString(message));
|
||||
}
|
||||
|
||||
//! Acars Message send to FSD
|
||||
template <class T>
|
||||
void sendAcarsMessage(const T &message)
|
||||
{
|
||||
if (!message.isValid()) { return; }
|
||||
this->sendMessageString(messageToFSDString(message));
|
||||
}
|
||||
|
||||
//! @{
|
||||
//! Unit test/debug functions
|
||||
void sendFsdMessage(const QString &message);
|
||||
@@ -517,6 +527,7 @@ namespace swift::core::fsd
|
||||
bool isInterimPositionSendingEnabledForServer() const;
|
||||
bool isInterimPositionReceivingEnabledForServer() const;
|
||||
bool isVisualPositionSendingEnabledForServer() const;
|
||||
bool isAcarsSendEnabled() const;
|
||||
const swift::misc::network::CFsdSetup &getSetupForServer() const;
|
||||
|
||||
//! Handles ATIS replies from non-VATSIM servers. If the conditions are not met,
|
||||
@@ -590,6 +601,9 @@ namespace swift::core::fsd
|
||||
mutable QReadWriteLock m_lockConnectionStatus { QReadWriteLock::Recursive };
|
||||
|
||||
swift::misc::aviation::CAircraftParts m_sentAircraftConfig; //!< aircraft parts sent
|
||||
swift::misc::aviation::CAircraftAcars m_sentAcars; //!< aircraft ACARS sent
|
||||
int m_sentAcarsCount = 0; //!< how many ACARS messages sent
|
||||
|
||||
swift::misc::CTokenBucket m_tokenBucket; //!< used with aircraft parts messages
|
||||
swift::misc::aviation::CCallsignSet m_interimPositionReceivers; //!< all aircraft receiving interim positions
|
||||
swift::misc::network::CTextMessageList m_textMessagesToConsolidate; //!< waiting for new messages
|
||||
@@ -633,6 +647,7 @@ namespace swift::core::fsd
|
||||
QTimer m_interimPositionUpdateTimer { this }; //!< sending interim positions
|
||||
QTimer m_visualPositionUpdateTimer { this }; //!< sending visual positions
|
||||
QTimer m_fsdSendMessageTimer { this }; //!< FSD message sending
|
||||
QTimer m_fsdSendAcarsTimer { this }; //!< ACARS message sending
|
||||
|
||||
qint64 m_additionalOffsetTime = 0; //!< additional offset time
|
||||
|
||||
@@ -696,6 +711,7 @@ namespace swift::core::fsd
|
||||
static int constexpr c_updateVisualPositionIntervalMsec =
|
||||
200; //!< interval for the VATSIM visual position updates (send our position and 6DOF velocity)
|
||||
static int constexpr c_sendFsdMsgIntervalMsec = 10; //!< interval for FSD send messages
|
||||
static int constexpr c_sendAcarsIntervalMsec = 1000; //!< interval for ACARS messages
|
||||
bool m_stoppedSendingVisualPositions = false; //!< for when velocity drops to zero
|
||||
bool m_serverWantsVisualPositions = false; //!< there are interested clients in range
|
||||
unsigned m_visualPositionUpdateSentCount = 0; //!< for choosing when to send a periodic (slowfast) packet
|
||||
|
||||
@@ -309,6 +309,7 @@ namespace swift::core::fsd
|
||||
case ClientQueryType::INF: return "INF";
|
||||
case ClientQueryType::FP: return "FP";
|
||||
case ClientQueryType::AircraftConfig: return "ACC";
|
||||
case ClientQueryType::Acars: return "ACARS";
|
||||
case ClientQueryType::EuroscopeSimData: return "SIMDATA";
|
||||
case ClientQueryType::Unknown: return "Unknown query type";
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace swift::gui::editors
|
||||
ui->cb_GndFlagSend->isChecked(), ui->cb_GndFlagReceive->isChecked(),
|
||||
ui->cb_FastPositionSend->isChecked(), ui->cb_FastPositionReceive->isChecked(),
|
||||
ui->cb_VisualPositionSend->isChecked(), ui->cb_EuroscopeSimData->isChecked(),
|
||||
ui->cb_IcaoEquipment->isChecked());
|
||||
ui->cb_IcaoEquipment->isChecked(), ui->cb_FsdSendAcars->isChecked());
|
||||
s.setForce3LetterAirlineCodes(ui->cb_3LetterAirlineICAO->isChecked());
|
||||
return s;
|
||||
}
|
||||
@@ -58,6 +58,7 @@ namespace swift::gui::editors
|
||||
ui->cb_3LetterAirlineICAO->setChecked(setup.force3LetterAirlineCodes());
|
||||
ui->cb_EuroscopeSimData->setChecked(d & CFsdSetup::ReceiveEuroscopeSimData);
|
||||
ui->cb_IcaoEquipment->setChecked(d & CFsdSetup::SendFplWithIcaoEquipment);
|
||||
ui->cb_FsdSendAcars->setChecked(d & CFsdSetup::SendAcars);
|
||||
}
|
||||
|
||||
void CFsdSetupForm::setAlwaysAllowOverride(bool allow)
|
||||
|
||||
@@ -36,6 +36,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lbl_FsdSendAcars">
|
||||
<property name="text">
|
||||
<string>send ACARS:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="cb_AircraftPartsSend">
|
||||
<property name="text">
|
||||
@@ -57,6 +66,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="cb_FsdSendAcars">
|
||||
<property name="text">
|
||||
<string>send ACARS information over private networks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="lbl_AircraftParts">
|
||||
<property name="toolTip">
|
||||
|
||||
@@ -17,6 +17,8 @@ add_library(misc SHARED
|
||||
audio/registermetadataaudio.h
|
||||
|
||||
# Aviation
|
||||
aviation/aircraftacars.cpp
|
||||
aviation/aircraftacars.h
|
||||
aviation/aircraftcategory.cpp
|
||||
aviation/aircraftcategory.h
|
||||
aviation/aircraftcategorylist.cpp
|
||||
@@ -678,7 +680,7 @@ add_library(misc SHARED
|
||||
weather/windlayer.h
|
||||
weather/windlayerlist.cpp
|
||||
weather/windlayerlist.h
|
||||
)
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
target_sources(misc PRIVATE
|
||||
|
||||
152
src/misc/aviation/aircraftacars.cpp
Normal file
152
src/misc/aviation/aircraftacars.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
// SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "QStringBuilder"
|
||||
|
||||
#include "misc/comparefunctions.h"
|
||||
#include "misc/propertyindex.h"
|
||||
#include "misc/stringutils.h"
|
||||
|
||||
SWIFT_DEFINE_VALUEOBJECT_MIXINS(swift::misc::aviation, CAircraftAcars)
|
||||
|
||||
namespace swift::misc::aviation
|
||||
{
|
||||
CAircraftAcars::CAircraftAcars(int simRate, int fuelTotalquantity)
|
||||
: m_simRate(simRate), m_fuelTotalquantity(fuelTotalquantity)
|
||||
{}
|
||||
|
||||
// CAircraftAcars::CAircraftAcars(int simRate, qint64 timestamp) : m_simRate(simRate) {}
|
||||
|
||||
CAircraftAcars::CAircraftAcars(int simRate, int fuelTotalquantity, qint64 timestamp)
|
||||
: m_simRate(simRate), m_fuelTotalquantity(fuelTotalquantity)
|
||||
{
|
||||
this->setMSecsSinceEpoch(timestamp);
|
||||
}
|
||||
|
||||
QString CAircraftAcars::convertToQString(bool i18n) const
|
||||
{
|
||||
// return QStringLiteral("CAircraftAcars"); // Platzhalter, bitte anpassen!
|
||||
|
||||
return u"ts: " % this->getFormattedTimestampAndOffset(true) % u" details: " % this->getAcarsDetailsAsString() %
|
||||
u" | simrate: " % QString::number(m_simRate);
|
||||
}
|
||||
|
||||
QJsonObject CAircraftAcars::toIncrementalJson() const
|
||||
{
|
||||
QJsonObject json = this->toJson();
|
||||
json.remove(attributeNameIsFullJson());
|
||||
json.insert(attributeNameIsFullJson(), QJsonValue(false));
|
||||
return json;
|
||||
}
|
||||
|
||||
QJsonObject CAircraftAcars::toFullJson() const
|
||||
{
|
||||
QJsonObject json = this->toJson();
|
||||
json.remove(attributeNameIsFullJson());
|
||||
json.insert(attributeNameIsFullJson(), QJsonValue(true));
|
||||
return json;
|
||||
}
|
||||
|
||||
bool CAircraftAcars::isNull() const { return this->getAcarsDetails() == NotSet && m_simRate < 0; }
|
||||
|
||||
bool CAircraftAcars::equalValues(const CAircraftAcars &other) const
|
||||
{
|
||||
// currently same as some values are diabled for comparison
|
||||
// but that could change in future
|
||||
return other == *this;
|
||||
}
|
||||
|
||||
const CAircraftAcars &CAircraftAcars::null()
|
||||
{
|
||||
static const CAircraftAcars null(1, 100);
|
||||
return null;
|
||||
}
|
||||
|
||||
const QString &CAircraftAcars::acarsDetailsToString(CAircraftAcars::AcarsDetails details)
|
||||
{
|
||||
static const QString guessed("guessed");
|
||||
static const QString notset("not set");
|
||||
static const QString fsd("FSD acars");
|
||||
|
||||
switch (details)
|
||||
{
|
||||
case GuessedAcars: return guessed;
|
||||
case FSDAircraftAcars: return fsd;
|
||||
case NotSet: break;
|
||||
default: break;
|
||||
}
|
||||
return notset;
|
||||
}
|
||||
|
||||
const QString &CAircraftAcars::attributeNameIsFullJson()
|
||||
{
|
||||
static const QString a("is_full_data");
|
||||
return a;
|
||||
}
|
||||
|
||||
QVariant CAircraftAcars::propertyByIndex(swift::misc::CPropertyIndexRef index) const
|
||||
{
|
||||
if (index.isMyself()) { return QVariant::fromValue(*this); }
|
||||
if (ITimestampWithOffsetBased::canHandleIndex(index))
|
||||
{
|
||||
return ITimestampWithOffsetBased::propertyByIndex(index);
|
||||
}
|
||||
|
||||
const auto i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexSimrate: return QVariant::fromValue(m_simRate);
|
||||
case IndexFuelTotalQuantity: return QVariant::fromValue(m_fuelTotalquantity);
|
||||
default: return CValueObject::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void CAircraftAcars::setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
|
||||
{
|
||||
if (index.isMyself())
|
||||
{
|
||||
(*this) = variant.value<CAircraftAcars>();
|
||||
return;
|
||||
}
|
||||
if (ITimestampWithOffsetBased::canHandleIndex(index))
|
||||
{
|
||||
ITimestampWithOffsetBased::setPropertyByIndex(index, variant);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexSimrate: m_simRate = variant.toInt(); break;
|
||||
case IndexFuelTotalQuantity: m_fuelTotalquantity = variant.toInt(); break;
|
||||
default: CValueObject::setPropertyByIndex(index, variant); break;
|
||||
}
|
||||
}
|
||||
|
||||
int CAircraftAcars::comparePropertyByIndex(CPropertyIndexRef index, const CAircraftAcars &compareValue) const
|
||||
{
|
||||
if (index.isMyself())
|
||||
{
|
||||
return ITimestampWithOffsetBased::comparePropertyByIndex(CPropertyIndex(), compareValue);
|
||||
}
|
||||
if (ITimestampWithOffsetBased::canHandleIndex(index))
|
||||
{
|
||||
return ITimestampWithOffsetBased::comparePropertyByIndex(index, compareValue);
|
||||
}
|
||||
|
||||
const auto i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexSimrate: return Compare::compare(m_simRate, compareValue.getSimrate());
|
||||
case IndexFuelTotalQuantity: return Compare::compare(m_fuelTotalquantity, compareValue.getFuelTotalquantity());
|
||||
default: break;
|
||||
}
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "No comparison");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace swift::misc::aviation
|
||||
136
src/misc/aviation/aircraftacars.h
Normal file
136
src/misc/aviation/aircraftacars.h
Normal file
@@ -0,0 +1,136 @@
|
||||
// SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef SWIFT_MISC_AVIATION_AIRCRAFTACARS_H
|
||||
#define SWIFT_MISC_AVIATION_AIRCRAFTACARS_H
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
// #include "misc/aviation/aircraftenginelist.h"
|
||||
// #include "misc/aviation/aircraftlights.h"
|
||||
#include "misc/metaclass.h"
|
||||
#include "misc/propertyindexref.h"
|
||||
#include "misc/swiftmiscexport.h"
|
||||
#include "misc/timestampbased.h"
|
||||
#include "misc/valueobject.h"
|
||||
|
||||
// SWIFT_DECLARE_VALUEOBJECT_MIXINS(swift::misc::aviation, CAircraftAcars)
|
||||
|
||||
namespace swift::misc::aviation
|
||||
{
|
||||
//! Value object encapsulating information of aircraft's acars
|
||||
class SWIFT_MISC_EXPORT CAircraftAcars : public CValueObject<CAircraftAcars>, public ITimestampWithOffsetBased
|
||||
{
|
||||
public:
|
||||
//! Properties by index
|
||||
enum ColumnIndex
|
||||
{
|
||||
IndexSimrate,
|
||||
IndexFuelTotalQuantity
|
||||
};
|
||||
|
||||
//! Acars Details
|
||||
enum AcarsDetails
|
||||
{
|
||||
NotSet,
|
||||
FSDAircraftAcars,
|
||||
GuessedAcars
|
||||
};
|
||||
|
||||
//! Default constructor
|
||||
CAircraftAcars() = default;
|
||||
|
||||
//! Default constructor
|
||||
CAircraftAcars(int simRate, int fuelTotalquantity);
|
||||
|
||||
//! Constructor
|
||||
CAircraftAcars(int simRate, int fuelTotalquantity, qint64 timestamp);
|
||||
//! \copydoc swift::misc::mixin::Index::propertyByIndex
|
||||
QVariant propertyByIndex(CPropertyIndexRef index) const;
|
||||
|
||||
//! \copydoc swift::misc::mixin::Index::setPropertyByIndex
|
||||
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant);
|
||||
|
||||
//! \copydoc swift::misc::mixin::Index::comparePropertyByIndex
|
||||
int comparePropertyByIndex(CPropertyIndexRef index, const CAircraftAcars &compareValue) const;
|
||||
|
||||
//! Get simrate
|
||||
int getSimrate() const { return m_simRate; }
|
||||
|
||||
//! Set simrate
|
||||
// void setSimrate(int simRate) { m_simRate = simRate; }
|
||||
|
||||
//! Get fuel total quantity
|
||||
double getFuelTotalquantity() const { return m_fuelTotalquantity; }
|
||||
|
||||
//! Set fuel total quantity
|
||||
void setFuelTotalquantity(double fuelTotalquantity) { m_fuelTotalquantity = fuelTotalquantity; }
|
||||
|
||||
//! Get acars details
|
||||
AcarsDetails getAcarsDetails() const { return static_cast<AcarsDetails>(m_acarsDetails); }
|
||||
|
||||
//! Acars details as string
|
||||
const QString &getAcarsDetailsAsString() const { return acarsDetailsToString(this->getAcarsDetails()); }
|
||||
|
||||
//! Set acars details
|
||||
void setAcarsDetails(AcarsDetails details) { m_acarsDetails = static_cast<int>(details); }
|
||||
|
||||
//! \copydoc swift::misc::mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const;
|
||||
|
||||
//! Incremental JSON object
|
||||
//! \remark same as toJson, but sets \c is_full_data to \c false
|
||||
QJsonObject toIncrementalJson() const;
|
||||
|
||||
//! Full JSON Object
|
||||
//! \remark same as toJson, but sets \c is_full_data to \c true
|
||||
QJsonObject toFullJson() const;
|
||||
|
||||
//! NULL acars object?
|
||||
bool isNull() const;
|
||||
|
||||
//! Equal values, but not comparing timestamp etc.
|
||||
bool equalValues(const CAircraftAcars &other) const;
|
||||
|
||||
//! NULL acars object
|
||||
static const CAircraftAcars &null();
|
||||
|
||||
//! Convert to QString
|
||||
static const QString &acarsDetailsToString(AcarsDetails details);
|
||||
|
||||
//! Attribute name
|
||||
static const QString &attributeNameIsFullJson();
|
||||
|
||||
//! Number of attributes for full JSON
|
||||
static constexpr int attributesCountFullJson = 2;
|
||||
|
||||
private:
|
||||
// Fuel availability : Reports on the remaining fuel quantity
|
||||
// Error messages : Reports on potential problems or
|
||||
// malfunctions in the aircraft.Engine condition
|
||||
// slid
|
||||
// simulation rate : Reports on the current simulation rate of the aircraft
|
||||
|
||||
int m_acarsDetails = static_cast<int>(NotSet);
|
||||
int m_simRate = 1;
|
||||
double m_fuelTotalquantity = -1;
|
||||
|
||||
// QString m_guessingDetails; //!< just for debugging, not via DBus ...
|
||||
|
||||
SWIFT_METACLASS(
|
||||
CAircraftAcars,
|
||||
SWIFT_METAMEMBER_NAMED(simRate, "simrate"),
|
||||
SWIFT_METAMEMBER_NAMED(fuelTotalquantity, "fueltotalquantity"),
|
||||
SWIFT_METAMEMBER(acarsDetails, 0, DisabledForJson | DisabledForComparison),
|
||||
SWIFT_METAMEMBER(timestampMSecsSinceEpoch, 0, DisabledForJson | DisabledForComparison),
|
||||
SWIFT_METAMEMBER(timeOffsetMs, 0, DisabledForJson | DisabledForComparison));
|
||||
};
|
||||
|
||||
} // namespace swift::misc::aviation
|
||||
|
||||
Q_DECLARE_METATYPE(swift::misc::aviation::CAircraftAcars)
|
||||
|
||||
#endif // SWIFT_MISC_AVIATION_AIRCRAFTACARS_H
|
||||
@@ -13,12 +13,12 @@ namespace swift::misc::aviation
|
||||
{
|
||||
CAircraftEngine::CAircraftEngine(int number, bool on) : m_number(number), m_on(on)
|
||||
{
|
||||
Q_ASSERT_X(number > 0, "CAircraftEngine", "Engine numbers have to be >= 1");
|
||||
Q_ASSERT_X(number > 0, "CAircraftEngine", "Engine numbers have to be > 1");
|
||||
}
|
||||
|
||||
void CAircraftEngine::setNumber(int number)
|
||||
{
|
||||
Q_ASSERT_X(number > 0, "setNumber", "Engine numbers have to be >= 1");
|
||||
Q_ASSERT_X(number > 0, "setNumber", "Engine numbers have to be > 1");
|
||||
m_number = number;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace swift::misc::network
|
||||
|
||||
void CFsdSetup::setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive,
|
||||
bool interimSend, bool interimReceive, bool visualSend,
|
||||
bool euroscopeSimDataReceive, bool icaoEquipment)
|
||||
bool euroscopeSimDataReceive, bool icaoEquipment, bool sendAcars)
|
||||
{
|
||||
SendReceiveDetails s = Nothing;
|
||||
if (partsSend) { s |= SendAircraftParts; }
|
||||
@@ -63,6 +63,7 @@ namespace swift::misc::network
|
||||
if (visualSend) { s |= SendVisualPositions; }
|
||||
if (euroscopeSimDataReceive) { s |= ReceiveEuroscopeSimData; }
|
||||
if (icaoEquipment) { s |= SendFplWithIcaoEquipment; }
|
||||
if (sendAcars) { s |= SendAcars; }
|
||||
this->setSendReceiveDetails(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace swift::misc::network
|
||||
SendVisualPositions = 1 << 7, //!< visual positions out
|
||||
ReceiveEuroscopeSimData = 1 << 8, //!< euroscope SIMDATA in
|
||||
SendFplWithIcaoEquipment = 1 << 9, //!< send flightplan with ICAO equipment code instead of FAA code
|
||||
SendAcars = 1 << 10, //!< send ACARS information over private networks
|
||||
AllSending = SendAircraftParts | SendInterimPositions | SendVisualPositions | SendGndFlag, //!< all out
|
||||
AllReceive = ReceiveAircraftParts | ReceiveInterimPositions | ReceiveGndFlag, //!< all in
|
||||
All = AllReceive | AllSending, //!< all
|
||||
@@ -94,7 +95,7 @@ namespace swift::misc::network
|
||||
//! Set send / receive details
|
||||
void setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive, bool interimSend,
|
||||
bool interimReceive, bool visualSend, bool euroscopeSimDataReceive,
|
||||
bool icaoEquipment);
|
||||
bool icaoEquipmentm, bool sendAcars);
|
||||
|
||||
//! @{
|
||||
//! FSD setup flags
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace swift::misc
|
||||
GlobalIndexCComSystem = 3100,
|
||||
GlobalIndexCModulator = 3200,
|
||||
GlobalIndexCTransponder = 3300,
|
||||
GlobalIndexCAircraftAcars = 3400,
|
||||
GlobalIndexCAircraftCategory = 3500,
|
||||
GlobalIndexCAircraftIcaoCode = 3600,
|
||||
GlobalIndexCAirlineIcaoCode = 3700,
|
||||
|
||||
@@ -62,6 +62,12 @@ namespace swift::misc::simulation
|
||||
return this->provider()->getOwnAircraftParts();
|
||||
}
|
||||
|
||||
CAircraftAcars COwnAircraftAware::getOwnAircraftAcars() const
|
||||
{
|
||||
Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available");
|
||||
return this->provider()->getOwnAircraftAcars();
|
||||
}
|
||||
|
||||
CAircraftModel COwnAircraftAware::getOwnAircraftModel() const
|
||||
{
|
||||
Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available");
|
||||
@@ -118,6 +124,12 @@ namespace swift::misc::simulation
|
||||
return this->provider()->updateOwnParts(parts);
|
||||
}
|
||||
|
||||
bool COwnAircraftAware::updateOwnAcars(const CAircraftAcars &acars)
|
||||
{
|
||||
Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available");
|
||||
return this->provider()->updateOwnAcars(acars);
|
||||
}
|
||||
|
||||
bool COwnAircraftAware::updateOwnCG(const CLength &cg)
|
||||
{
|
||||
Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available");
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircraftparts.h"
|
||||
#include "misc/aviation/airlineicaocode.h"
|
||||
#include "misc/aviation/callsign.h"
|
||||
@@ -65,6 +66,10 @@ namespace swift::misc
|
||||
//! \threadsafe
|
||||
virtual aviation::CAircraftParts getOwnAircraftParts() const = 0;
|
||||
|
||||
//! Own aircraft's parts
|
||||
//! \threadsafe
|
||||
virtual aviation::CAircraftAcars getOwnAircraftAcars() const = 0;
|
||||
|
||||
//! Own aircraft model
|
||||
//! \threadsafe
|
||||
virtual swift::misc::simulation::CAircraftModel getOwnAircraftModel() const = 0;
|
||||
@@ -93,6 +98,9 @@ namespace swift::misc
|
||||
//! Update own parts
|
||||
virtual bool updateOwnParts(const aviation::CAircraftParts &parts) = 0;
|
||||
|
||||
//! Update own acars
|
||||
virtual bool updateOwnAcars(const aviation::CAircraftAcars &acars) = 0;
|
||||
|
||||
//! Update own aircraft's CG (aka vertical offset)
|
||||
virtual bool updateOwnCG(const physical_quantities::CLength &cg) = 0;
|
||||
|
||||
@@ -153,6 +161,9 @@ namespace swift::misc
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftParts
|
||||
aviation::CAircraftParts getOwnAircraftParts() const;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftAcars
|
||||
aviation::CAircraftAcars getOwnAircraftAcars() const;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftModel
|
||||
swift::misc::simulation::CAircraftModel getOwnAircraftModel() const;
|
||||
|
||||
@@ -196,6 +207,9 @@ namespace swift::misc
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnParts
|
||||
bool updateOwnParts(const aviation::CAircraftParts &parts);
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnAcars
|
||||
bool updateOwnAcars(const aviation::CAircraftAcars &acars);
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnCG
|
||||
bool updateOwnCG(const physical_quantities::CLength &cg);
|
||||
|
||||
|
||||
@@ -52,6 +52,13 @@ namespace swift::misc::simulation
|
||||
return m_ownAircraft.getParts();
|
||||
}
|
||||
|
||||
CAircraftAcars COwnAircraftProviderDummy::getOwnAircraftAcars() const
|
||||
{
|
||||
// TODO TZ: implement this properly, for now just return parts as a placeholder
|
||||
QReadLocker l(&m_lock);
|
||||
return m_ownAircraft.getAcars();
|
||||
}
|
||||
|
||||
CAircraftModel COwnAircraftProviderDummy::getOwnAircraftModel() const
|
||||
{
|
||||
QReadLocker l(&m_lock);
|
||||
@@ -117,6 +124,13 @@ namespace swift::misc::simulation
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COwnAircraftProviderDummy::updateOwnAcars(const CAircraftAcars &acars)
|
||||
{
|
||||
QWriteLocker l(&m_lock);
|
||||
m_ownAircraft.setAcars(acars);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool COwnAircraftProviderDummy::updateOwnCG(const CLength &cg)
|
||||
{
|
||||
QWriteLocker l(&m_lock);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QObject>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircraftparts.h"
|
||||
#include "misc/aviation/airlineicaocode.h"
|
||||
#include "misc/aviation/comsystem.h"
|
||||
@@ -67,6 +68,9 @@ namespace swift::misc
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftParts
|
||||
swift::misc::aviation::CAircraftParts getOwnAircraftParts() const override;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftAcars
|
||||
swift::misc::aviation::CAircraftAcars getOwnAircraftAcars() const override;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::getOwnAircraftModel
|
||||
swift::misc::simulation::CAircraftModel getOwnAircraftModel() const override;
|
||||
|
||||
@@ -106,6 +110,9 @@ namespace swift::misc
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnParts
|
||||
bool updateOwnParts(const swift::misc::aviation::CAircraftParts &parts) override;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnAcars
|
||||
bool updateOwnAcars(const swift::misc::aviation::CAircraftAcars &acars) override;
|
||||
|
||||
//! \copydoc IOwnAircraftProvider::updateOwnCG
|
||||
bool updateOwnCG(const swift::misc::physical_quantities::CLength &cg) override;
|
||||
|
||||
|
||||
@@ -280,6 +280,8 @@ namespace swift::misc::simulation
|
||||
|
||||
void CSimulatedAircraft::setParts(const CAircraftParts &parts) { m_parts = parts; }
|
||||
|
||||
void CSimulatedAircraft::setAcars(const CAircraftAcars &acars) { m_acars = acars; }
|
||||
|
||||
void CSimulatedAircraft::setLights(CAircraftLights &lights) { m_parts.setLights(lights); }
|
||||
|
||||
void CSimulatedAircraft::setAllLightsOn() { m_parts.setAllLightsOn(); }
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <QVector3D>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircraftlights.h"
|
||||
#include "misc/aviation/aircraftparts.h"
|
||||
#include "misc/aviation/aircraftsituation.h"
|
||||
@@ -349,6 +350,9 @@ namespace swift::misc
|
||||
//! Get aircraft parts
|
||||
const aviation::CAircraftParts &getParts() const { return m_parts; }
|
||||
|
||||
//! Get aircraft acars
|
||||
const aviation::CAircraftAcars &getAcars() const { return m_acars; }
|
||||
|
||||
//! Number of engines
|
||||
int getEnginesCount() const;
|
||||
|
||||
@@ -358,6 +362,9 @@ namespace swift::misc
|
||||
//! Set aircraft parts
|
||||
void setParts(const aviation::CAircraftParts &parts);
|
||||
|
||||
//! Set aircraft acars
|
||||
void setAcars(const aviation::CAircraftAcars &acars);
|
||||
|
||||
//! Set aircraft lights
|
||||
void setLights(aviation::CAircraftLights &lights);
|
||||
|
||||
@@ -493,6 +500,7 @@ namespace swift::misc
|
||||
aviation::CComSystem m_com2system;
|
||||
aviation::CTransponder m_transponder;
|
||||
aviation::CAircraftParts m_parts;
|
||||
aviation::CAircraftAcars m_acars;
|
||||
aviation::CSelcal m_selcal;
|
||||
CAircraftModelList m_models = {
|
||||
{ CAircraftModel(), CAircraftModel() }
|
||||
@@ -515,6 +523,7 @@ namespace swift::misc
|
||||
SWIFT_METAMEMBER(com2system),
|
||||
SWIFT_METAMEMBER(transponder),
|
||||
SWIFT_METAMEMBER(parts),
|
||||
SWIFT_METAMEMBER(acars),
|
||||
SWIFT_METAMEMBER(selcal),
|
||||
SWIFT_METAMEMBER(models),
|
||||
SWIFT_METAMEMBER(enabled),
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "../fscommon/simulatorfscommonfunctions.h"
|
||||
#include "simconnectsymbols.h"
|
||||
|
||||
#include "misc/aviation/aircraftacars.h"
|
||||
#include "misc/aviation/aircraftenginelist.h"
|
||||
#include "misc/aviation/aircraftparts.h"
|
||||
#include "misc/logmessage.h"
|
||||
@@ -185,6 +186,13 @@ namespace swift::simplugin::fsxcommon
|
||||
|
||||
hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraftTitle, "TITLE",
|
||||
nullptr, SIMCONNECT_DATATYPE_STRING256);
|
||||
|
||||
hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft,
|
||||
"FUEL TOTAL QUANTITY", "Gallons");
|
||||
|
||||
hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SIMULATION RATE",
|
||||
"Number");
|
||||
|
||||
if (isFailure(hr))
|
||||
{
|
||||
CLogMessage(static_cast<CSimConnectDefinitions *>(nullptr)).error(u"SimConnect error: initOwnAircraft %1")
|
||||
|
||||
@@ -79,6 +79,10 @@ namespace swift::simplugin::fsxcommon
|
||||
// 44
|
||||
double altitudeCalibratedFt; //!< Altitude without temperature effect (ft, FS2020)
|
||||
// 45
|
||||
double fuelTotalCapacity; //!< Altitude without temperature effect (ft, FS2020)
|
||||
// 46
|
||||
double simulationRate; //!< Simulation rate (FS2020)
|
||||
// 47
|
||||
};
|
||||
|
||||
//! Data struct of aircraft position
|
||||
|
||||
@@ -754,9 +754,14 @@ namespace swift::simplugin::fsxcommon
|
||||
dtb(simulatorOwnAircraft.spoilersHandlePosition), engines,
|
||||
dtb(simulatorOwnAircraft.simOnGround), ts);
|
||||
|
||||
// TODO TZ s
|
||||
const CAircraftAcars acars(qRound(simulatorOwnAircraft.simulationRate),
|
||||
qRound(simulatorOwnAircraft.fuelTotalCapacity * 100), ts);
|
||||
|
||||
// set values
|
||||
this->updateOwnSituationAndGroundElevation(aircraftSituation);
|
||||
this->updateOwnParts(parts);
|
||||
this->updateOwnAcars(acars);
|
||||
|
||||
// When I change cockpit values in the sim (from GUI to simulator, not originating from simulator)
|
||||
// it takes a little while before these values are set in the simulator.
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace swift::simplugin::fsxcommon
|
||||
{
|
||||
case CSimConnectDefinitions::RequestOwnAircraft:
|
||||
{
|
||||
static_assert(sizeof(DataDefinitionOwnAircraft) == 45 * sizeof(double),
|
||||
static_assert(sizeof(DataDefinitionOwnAircraft) == 47 * sizeof(double),
|
||||
"DataDefinitionOwnAircraft has an incorrect size.");
|
||||
const DataDefinitionOwnAircraft *ownAircaft =
|
||||
reinterpret_cast<const DataDefinitionOwnAircraft *>(&pObjData->dwData);
|
||||
|
||||
Reference in New Issue
Block a user