mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 20:15:35 +08:00
Add methods to receive and write raw FSD messages
This commit adds methods to register for live FSD message reception. The amount of traffic can be quite high, therefore no normal signal is used - which would be available via DBus. Instead one has to connect manually by passing a functor. This guarantees that we communicate only in-process. If someone tries to connect on the proxy side, the connection will fail. This needs to be handled properly in client code. This commit also adds a method to write the FSD message to a selected file. Maniphest Tasks: T222
This commit is contained in:
@@ -40,6 +40,8 @@
|
||||
#include "blackmisc/statusmessage.h"
|
||||
#include "blackmisc/weather/metar.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
//! \addtogroup dbus
|
||||
//! @{
|
||||
|
||||
@@ -302,6 +304,13 @@ namespace BlackCore
|
||||
//! Request parts for callsign (from another client)
|
||||
virtual void testRequestAircraftConfig(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
public:
|
||||
//! Raw FSD message receiver functor
|
||||
using RawFsdMessageReceivedSlot = std::function<void(const BlackMisc::Network::CRawFsdMessage &)>;
|
||||
|
||||
//! Connect to receive raw fsd messages
|
||||
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) = 0;
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
IContextNetwork(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime) : CContext(mode, runtime) {}
|
||||
|
||||
@@ -385,6 +385,16 @@ namespace BlackCore
|
||||
logEmptyContextWarning(Q_FUNC_INFO);
|
||||
Q_UNUSED(enabled);
|
||||
}
|
||||
|
||||
public:
|
||||
//! \copydoc IContextNetwork::connectRawFsdMessageSignal
|
||||
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) override
|
||||
{
|
||||
logEmptyContextWarning(Q_FUNC_INFO);
|
||||
Q_UNUSED(receiver);
|
||||
Q_UNUSED(rawFsdMessageReceivedSlot);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -751,5 +751,16 @@ namespace BlackCore
|
||||
rooms.push_back(s2.getVoiceRoom());
|
||||
return rooms;
|
||||
}
|
||||
|
||||
QMetaObject::Connection CContextNetwork::connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
|
||||
{
|
||||
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 c = rawFsdMessageReceivedSlot ? connect(m_network, &INetwork::rawFsdMessageReceived, receiver, rawFsdMessageReceivedSlot) : uc;
|
||||
Q_ASSERT_X(c || !rawFsdMessageReceivedSlot, Q_FUNC_INFO, "connect failed");
|
||||
return c;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -191,6 +191,10 @@ namespace BlackCore
|
||||
//! Gracefully shut down, e.g. for thread safety
|
||||
void gracefulShutdown();
|
||||
|
||||
public:
|
||||
//! \copydoc IContextNetwork::connectRawFsdMessageSignal
|
||||
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) override;
|
||||
|
||||
protected:
|
||||
//! Constructor, with link to runtime
|
||||
CContextNetwork(CCoreFacadeConfig::ContextMode, CCoreFacade *runtime);
|
||||
|
||||
@@ -93,6 +93,7 @@ namespace BlackCore
|
||||
s = connection.connect(serviceName, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName(),
|
||||
"removedAircraft", this, SIGNAL(removedAircraft(BlackMisc::Aviation::CCallsign)));
|
||||
Q_ASSERT(s);
|
||||
|
||||
Q_UNUSED(s);
|
||||
this->relayBaseClassSignals(serviceName, connection, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName());
|
||||
}
|
||||
@@ -331,5 +332,12 @@ namespace BlackCore
|
||||
{
|
||||
return m_dBusInterface->callDBusRet<BlackMisc::Weather::CMetar>(QLatin1String("getMetarForAirport"), airportIcaoCode);
|
||||
}
|
||||
|
||||
QMetaObject::Connection CContextNetworkProxy::connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
|
||||
{
|
||||
Q_UNUSED(receiver);
|
||||
Q_UNUSED(rawFsdMessageReceivedSlot);
|
||||
return {};
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -124,6 +124,10 @@ namespace BlackCore
|
||||
virtual void testRequestAircraftConfig(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
//! @}
|
||||
|
||||
public:
|
||||
//! \copydoc IContextNetwork::connectRawFsdMessageSignal
|
||||
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot) override;
|
||||
|
||||
private:
|
||||
BlackMisc::CGenericDBusInterface *m_dBusInterface; /*!< DBus interface */
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "blackmisc/simulation/simulatorplugininfo.h"
|
||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||
#include "blackmisc/geo/coordinategeodetic.h"
|
||||
#include "blackmisc/network/rawfsdmessage.h"
|
||||
#include "blackmisc/network/serverlist.h"
|
||||
#include "blackmisc/network/textmessagelist.h"
|
||||
#include "blackmisc/aviation/informationmessage.h"
|
||||
@@ -526,6 +527,11 @@ namespace BlackCore
|
||||
*/
|
||||
void aircraftConfigPacketReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &incremental, bool isFull);
|
||||
|
||||
/*!
|
||||
* We received a raw message for debugging purposes
|
||||
*/
|
||||
void rawFsdMessageReceived(const BlackMisc::Network::CRawFsdMessage &rawFsdMessage);
|
||||
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Weather signals
|
||||
|
||||
@@ -49,5 +49,6 @@ namespace BlackCore
|
||||
Data::CVatsimSetup::registerMetadata();
|
||||
Data::CLauncherSetup::registerMetadata();
|
||||
Vatsim::CReaderSettings::registerMetadata();
|
||||
Vatsim::CRawFsdMessageSettings::registerMetadata();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <QList>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
#include <QVector>
|
||||
#include <Qt>
|
||||
#include <QtDebug>
|
||||
@@ -158,6 +159,7 @@ namespace BlackCore
|
||||
Vat_SetAircraftInfoHandler(m_net.data(), onPilotInfoReceived, this);
|
||||
Vat_SetCustomPilotPacketHandler(m_net.data(), onCustomPacketReceived, this);
|
||||
Vat_SetAircraftConfigHandler(m_net.data(), onAircraftConfigReceived, this);
|
||||
Vat_SetFsdMessageHandler(m_net.data(), onRawFsdMessage, this);
|
||||
}
|
||||
|
||||
CNetworkVatlib::~CNetworkVatlib()
|
||||
@@ -983,6 +985,11 @@ namespace BlackCore
|
||||
cbvar_cast(cbvar)->customPacketDispatcher(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(packetId), cbvar_cast(cbvar)->fromFSD(data, dataSize));
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onRawFsdMessage(VatFsdClient *, const char *message, void *cbvar)
|
||||
{
|
||||
cbvar_cast(cbvar)->handleRawFsdMessage(cbvar_cast(cbvar)->fromFSD(message));
|
||||
}
|
||||
|
||||
void CNetworkVatlib::customPacketDispatcher(const CCallsign &callsign, const QString &packetId, const QStringList &data)
|
||||
{
|
||||
if (packetId.compare("FSIPI", Qt::CaseInsensitive) == 0)
|
||||
@@ -1022,6 +1029,47 @@ namespace BlackCore
|
||||
}
|
||||
}
|
||||
|
||||
void CNetworkVatlib::handleRawFsdMessage(const QString &fsdMessage)
|
||||
{
|
||||
CRawFsdMessage rawFsdMessage(fsdMessage);
|
||||
if (m_rawFsdMessageLogFile.isOpen())
|
||||
{
|
||||
QTextStream stream(&m_rawFsdMessageLogFile);
|
||||
stream << rawFsdMessage.toQString() << endl;
|
||||
}
|
||||
emit rawFsdMessageReceived(rawFsdMessage);
|
||||
}
|
||||
|
||||
void CNetworkVatlib::fsdMessageSettingsChanged()
|
||||
{
|
||||
if (m_rawFsdMessageLogFile.isOpen()) { m_rawFsdMessageLogFile.close(); }
|
||||
const CRawFsdMessageSettings setting = m_fsdMessageSetting.get();
|
||||
if (!setting.isFileWritingEnabled() || setting.getFileDir().isEmpty()) { return; }
|
||||
|
||||
if (setting.getFileWriteMode() == CRawFsdMessageSettings::Truncate)
|
||||
{
|
||||
QString filePath = CFileUtils::appendFilePaths(setting.getFileDir(), "rawfsdmessages.log");
|
||||
m_rawFsdMessageLogFile.setFileName(filePath);
|
||||
m_rawFsdMessageLogFile.open(QIODevice::Text | QIODevice::WriteOnly);
|
||||
}
|
||||
else if (setting.getFileWriteMode() == CRawFsdMessageSettings::Append)
|
||||
{
|
||||
QString filePath = CFileUtils::appendFilePaths(setting.getFileDir(), "rawfsdmessages.log");
|
||||
m_rawFsdMessageLogFile.setFileName(filePath);
|
||||
m_rawFsdMessageLogFile.open(QIODevice::Text | QIODevice::WriteOnly | QIODevice::Append);
|
||||
}
|
||||
else if (setting.getFileWriteMode() == CRawFsdMessageSettings::Timestamped)
|
||||
{
|
||||
QString filename("rawfsdmessages");
|
||||
filename += QLatin1String("_");
|
||||
filename += QDateTime::currentDateTime().toString(QStringLiteral("yyMMddhhmmss"));
|
||||
filename += QLatin1String(".log");
|
||||
QString filePath = CFileUtils::appendFilePaths(setting.getFileDir(), filename);
|
||||
m_rawFsdMessageLogFile.setFileName(filePath);
|
||||
m_rawFsdMessageLogFile.open(QIODevice::Text | QIODevice::WriteOnly);
|
||||
}
|
||||
}
|
||||
|
||||
void CNetworkVatlib::consolidateTextMessage(const CTextMessage &textMessage)
|
||||
{
|
||||
if (textMessage.isSupervisorMessage())
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <vatlib/vatlib.h>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
@@ -165,6 +166,7 @@ namespace BlackCore
|
||||
static void onPilotPositionUpdate(VatFsdClient *, const char *callsign, const VatPilotPosition *position, void *cbvar);
|
||||
static void onAircraftConfigReceived(VatFsdClient *, const char *callsign, const char *aircraftConfig, void *cbvar);
|
||||
static void onCustomPacketReceived(VatFsdClient *, const char *callsign, const char *packetId, const char **data, int dataSize, void *cbvar);
|
||||
static void onRawFsdMessage(VatFsdClient *, const char *message, void *cbvar);
|
||||
//! @}
|
||||
|
||||
QByteArray toFSD(const QString &qstr) const;
|
||||
@@ -198,6 +200,8 @@ namespace BlackCore
|
||||
void sendPositionUpdate();
|
||||
void sendInterimPositions();
|
||||
void customPacketDispatcher(const BlackMisc::Aviation::CCallsign &callsign, const QString &packetId, const QStringList &data);
|
||||
void handleRawFsdMessage(const QString &fsdMessage);
|
||||
void fsdMessageSettingsChanged();
|
||||
|
||||
signals:
|
||||
void terminate(); //!< \private
|
||||
@@ -251,10 +255,11 @@ namespace BlackCore
|
||||
{
|
||||
QDateTime m_queryTime = QDateTime::currentDateTimeUtc();
|
||||
QStringList m_atisMessage;
|
||||
|
||||
};
|
||||
|
||||
QHash<BlackMisc::Aviation::CCallsign, PendingAtisQuery> m_pendingAtisQueries;
|
||||
|
||||
BlackMisc::CSettingReadOnly<BlackCore::Vatsim::TRawFsdMessageSetting> m_fsdMessageSetting { this, &CNetworkVatlib::fsdMessageSettingsChanged };
|
||||
QFile m_rawFsdMessageLogFile;
|
||||
};
|
||||
} //namespace
|
||||
} //namespace
|
||||
|
||||
@@ -74,5 +74,47 @@ namespace BlackCore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CRawFsdMessageSettings::CRawFsdMessageSettings()
|
||||
{ }
|
||||
|
||||
CRawFsdMessageSettings::CRawFsdMessageSettings(bool enabled, const QString &FileDir) :
|
||||
m_fileWritingEnabled(enabled), m_FileDir(FileDir)
|
||||
{ }
|
||||
|
||||
QString CRawFsdMessageSettings::convertToQString(bool i18n) const
|
||||
{
|
||||
Q_UNUSED(i18n);
|
||||
QString s("CRawFsdMessageSettings");
|
||||
s.append(" enabled: ").append(boolToYesNo(m_fileWritingEnabled));
|
||||
s.append(" dir: ").append(m_FileDir);
|
||||
return s;
|
||||
}
|
||||
|
||||
CVariant CRawFsdMessageSettings::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
|
||||
{
|
||||
if (index.isMyself()) { return CVariant::from(*this); }
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexWriteEnabled: return CVariant::fromValue(this->m_fileWritingEnabled);
|
||||
case IndexFileDir: return CVariant::fromValue(this->m_FileDir);
|
||||
case IndexFileWriteMode: return CVariant::fromValue(this->m_fileWriteMode);
|
||||
default: return CValueObject::propertyByIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void CRawFsdMessageSettings::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant)
|
||||
{
|
||||
if (index.isMyself()) { (*this) = variant.to<CRawFsdMessageSettings>(); return; }
|
||||
ColumnIndex i = index.frontCasted<ColumnIndex>();
|
||||
switch (i)
|
||||
{
|
||||
case IndexWriteEnabled: this->m_fileWritingEnabled = variant.toBool(); break;
|
||||
case IndexFileDir: this->m_FileDir = variant.toQString(); break;
|
||||
case IndexFileWriteMode: this->m_fileWriteMode = variant.to<FileWriteMode>(); break;
|
||||
default: CValueObject::setPropertyByIndex(index, variant); break;
|
||||
}
|
||||
}
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "blackmisc/valueobject.h"
|
||||
#include "blackmisc/pq/time.h"
|
||||
#include "blackmisc/network/serverlist.h"
|
||||
#include "blackmisc/directoryutils.h"
|
||||
#include "blackmisc/fileutils.h"
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
@@ -164,11 +166,94 @@ namespace BlackCore
|
||||
return reader;
|
||||
}
|
||||
};
|
||||
|
||||
//! FSD Message settings
|
||||
class BLACKCORE_EXPORT CRawFsdMessageSettings : public BlackMisc::CValueObject<BlackCore::Vatsim::CRawFsdMessageSettings>
|
||||
{
|
||||
public:
|
||||
//! File writing mode
|
||||
enum FileWriteMode
|
||||
{
|
||||
Truncate,
|
||||
Append,
|
||||
Timestamped
|
||||
};
|
||||
|
||||
//! Properties by index
|
||||
enum ColumnIndex
|
||||
{
|
||||
IndexWriteEnabled = BlackMisc::CPropertyIndex::GlobalIndexRawFsdMessageSettings,
|
||||
IndexFileDir,
|
||||
IndexFileWriteMode
|
||||
};
|
||||
|
||||
//! Default constructor.
|
||||
CRawFsdMessageSettings();
|
||||
|
||||
//! Simplified constructor
|
||||
CRawFsdMessageSettings(bool enabled, const QString &fileDir);
|
||||
|
||||
//! Is file writing enabled?
|
||||
bool isFileWritingEnabled() const { return m_fileWritingEnabled; }
|
||||
|
||||
//! Get file directory
|
||||
QString getFileDir() const { return m_FileDir; }
|
||||
|
||||
//! Get file write mode
|
||||
FileWriteMode getFileWriteMode () const { return m_fileWriteMode; }
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
|
||||
BlackMisc::CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
|
||||
void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const BlackMisc::CVariant &variant);
|
||||
|
||||
//! \copydoc BlackMisc::Mixin::String::toQString
|
||||
QString convertToQString(bool i18n = false) const;
|
||||
|
||||
private:
|
||||
bool m_fileWritingEnabled = false;
|
||||
QString m_FileDir;
|
||||
FileWriteMode m_fileWriteMode = Truncate;
|
||||
|
||||
BLACK_METACLASS(
|
||||
CRawFsdMessageSettings,
|
||||
BLACK_METAMEMBER(fileWritingEnabled),
|
||||
BLACK_METAMEMBER(FileDir),
|
||||
BLACK_METAMEMBER(fileWriteMode)
|
||||
);
|
||||
};
|
||||
|
||||
//! Raw FSD message settings
|
||||
struct TRawFsdMessageSetting : public BlackMisc::TSettingTrait<CRawFsdMessageSettings>
|
||||
{
|
||||
//! \copydoc BlackCore::TSettingTrait::key
|
||||
static const char *key() { return "network/rawfsdmessagelog"; }
|
||||
|
||||
//! \copydoc BlackCore::TSettingTrait::humanReadable
|
||||
static const QString &humanReadable() { static const QString name("FSD message Logging"); return name; }
|
||||
|
||||
//! \copydoc BlackCore::TSettingTrait::isValid
|
||||
static bool isValid(const CRawFsdMessageSettings &setting)
|
||||
{
|
||||
if (setting.isFileWritingEnabled()) { return !setting.getFileDir().isEmpty(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
//! \copydoc BlackCore::TSettingTrait::defaultValue
|
||||
static const CRawFsdMessageSettings &defaultValue()
|
||||
{
|
||||
static const CRawFsdMessageSettings setting { false, BlackMisc::CDirectoryUtils::logDirectory() };
|
||||
return setting;
|
||||
}
|
||||
};
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
Q_DECLARE_METATYPE(BlackCore::Vatsim::CReaderSettings)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CCollection<BlackCore::Vatsim::CReaderSettings>)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CSequence<BlackCore::Vatsim::CReaderSettings>)
|
||||
Q_DECLARE_METATYPE(BlackCore::Vatsim::CRawFsdMessageSettings)
|
||||
Q_DECLARE_METATYPE(BlackCore::Vatsim::CRawFsdMessageSettings::FileWriteMode)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -158,6 +158,7 @@ namespace BlackMisc
|
||||
GlobalIndexCGeneralGuiSettings = 14600,
|
||||
GlobalIndexCTextMessageSettings = 14700,
|
||||
GlobalIndexCAtcStationsSettings = 14800,
|
||||
GlobalIndexRawFsdMessageSettings = 14900,
|
||||
GlobalIndexCInterpolatioRenderingSetup = 16000,
|
||||
GlobalIndexCInterpolationHints = 16100,
|
||||
GlobalIndexSwiftPilotClient = 17000,
|
||||
|
||||
Reference in New Issue
Block a user