From bd7d6ac17c6c69a2faa932f5973f46e6a4f3c7d9 Mon Sep 17 00:00:00 2001 From: Mat Sutcliffe Date: Wed, 14 Jul 2021 19:19:11 +0100 Subject: [PATCH] Issue #113 Add value class for SIMDATA packet --- src/blackcore/fsd/euroscopesimdata.cpp | 98 +++++++++++++++++++ src/blackcore/fsd/euroscopesimdata.h | 88 +++++++++++++++++ src/blackcore/fsd/messagebase.h | 1 + .../fsd/testfsdmessages/testfsdmessages.cpp | 41 ++++++++ 4 files changed, 228 insertions(+) create mode 100644 src/blackcore/fsd/euroscopesimdata.cpp create mode 100644 src/blackcore/fsd/euroscopesimdata.h diff --git a/src/blackcore/fsd/euroscopesimdata.cpp b/src/blackcore/fsd/euroscopesimdata.cpp new file mode 100644 index 000000000..feb646c25 --- /dev/null +++ b/src/blackcore/fsd/euroscopesimdata.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2021 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#include "blackcore/fsd/euroscopesimdata.h" +#include "blackmisc/logmessage.h" + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; + +namespace BlackCore::Fsd +{ + EuroscopeSimData::EuroscopeSimData() = default; + + EuroscopeSimData::EuroscopeSimData(const QString &sender, const QString &model, const QString &livery, quint64 timestamp, + double latitude, double longitude, double altitude, double heading, int bank, int pitch, + int groundSpeed, bool onGround, double gearPercent, double thrustPercent, const BlackMisc::Aviation::CAircraftLights &lights) : + MessageBase(sender, {}), + m_model(model), + m_livery(livery), + m_timestamp(timestamp), + m_latitude(latitude), + m_longitude(longitude), + m_altitude(altitude), + m_heading(heading), + m_bank(bank), + m_pitch(pitch), + m_groundSpeed(groundSpeed), + m_onGround(onGround), + m_gearPercent(gearPercent), + m_thrustPercent(thrustPercent), + m_lights(lights) + {} + + QStringList EuroscopeSimData::toTokens() const + { + static constexpr auto toFlags = [](const CAircraftLights &lights) + { + int n = 0; + if (lights.isBeaconOn()) { n |= 0x002; } + if (lights.isCabinOn()) { n |= 0x400; } + if (lights.isLandingOn()) { n |= 0x020; } + if (lights.isLogoOn()) { n |= 0x200; } + if (lights.isNavOn()) { n |= 0x008; } + if (lights.isRecognitionOn()) { n |= 0x080; } + if (lights.isStrobeOn()) { n |= 0x004; } + if (lights.isTaxiOn()) { n |= 0x040; } + return n; + }; + + QStringList tokens; + tokens.push_back({}); // first token is empty + tokens.push_back(m_sender); + tokens.push_back(m_model); + tokens.push_back(m_livery); + tokens.push_back(QString::number(m_timestamp)); + tokens.push_back(QString::number(m_latitude, 'f', 7)); + tokens.push_back(QString::number(m_longitude, 'f', 7)); + tokens.push_back(QString::number(m_altitude, 'f', 1)); + tokens.push_back(QString::number(m_heading, 'f', 2)); + tokens.push_back(QString::number(m_bank)); + tokens.push_back(QString::number(m_pitch)); + tokens.push_back(QString::number(m_groundSpeed)); + tokens.push_back(m_onGround ? QStringLiteral("1") : QStringLiteral("0")); + tokens.push_back(QString::number(m_gearPercent)); + tokens.push_back(QString::number(m_thrustPercent)); + tokens.push_back(QStringLiteral("0")); // emergency flags + tokens.push_back(QStringLiteral("0.0")); // airport altitude + tokens.push_back(QString::number(toFlags(m_lights))); + return tokens; + } + + EuroscopeSimData EuroscopeSimData::fromTokens(const QStringList &tokens) + { + if (tokens.size() < 18) + { + CLogMessage(static_cast(nullptr)).debug(u"Wrong number of arguments."); + return {}; + } + + static constexpr auto fromFlags = [](int n) + { + return CAircraftLights(n & 0x4, n & 0x20, n & 0x40, n & 0x2, n & 0x8, n & 0x200, n & 0x80, n & 0x400); + }; + + // token[0,15,16] are not used + return EuroscopeSimData(tokens[1], tokens[2], tokens[3], tokens[4].toULongLong(), tokens[5].toDouble(), + tokens[6].toDouble(), tokens[7].toDouble(), tokens[8].toDouble(), tokens[9].toInt(), tokens[10].toInt(), + tokens[11].toInt(), tokens[12].toInt(), tokens[13].toDouble(), tokens[14].toDouble(), fromFlags(tokens[17].toInt())); + } +} + diff --git a/src/blackcore/fsd/euroscopesimdata.h b/src/blackcore/fsd/euroscopesimdata.h new file mode 100644 index 000000000..b94567ca8 --- /dev/null +++ b/src/blackcore/fsd/euroscopesimdata.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2021 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKCORE_FSD_EUROSCOPESIMDATA_H +#define BLACKCORE_FSD_EUROSCOPESIMDATA_H + +#include "blackcore/fsd/messagebase.h" +#include "blackcore/fsd/enums.h" +#include "blackmisc/aviation/aircraftlights.h" + +namespace BlackCore::Fsd +{ + //! Pilot data update broadcast by Euroscope Simulator every second. + class BLACKCORE_EXPORT EuroscopeSimData : public MessageBase + { + public: + //! Constructor + EuroscopeSimData(const QString &sender, const QString &model, const QString &livery, quint64 timestamp, + double latitude, double longitude, double altitude, double heading, int bank, int pitch, + int groundSpeed, bool onGround, double gearPercent, double thrustPercent, const BlackMisc::Aviation::CAircraftLights &lights); + + //! Message converted to tokens + QStringList toTokens() const; + + //! Construct from tokens + static EuroscopeSimData fromTokens(const QStringList &tokens); + + //! PDU identifier + static QString pdu() { return QStringLiteral("SIMDATA"); } + + //! Properties + //! @{ + QString m_model; + QString m_livery; + quint64 m_timestamp = 0; + double m_latitude = 0; + double m_longitude = 0; + double m_altitude = 0; + double m_heading = 0; + int m_bank = 0; + int m_pitch = 0; + int m_groundSpeed = 0; + bool m_onGround = false; + int m_gearPercent = 0; + int m_thrustPercent = 0; + BlackMisc::Aviation::CAircraftLights m_lights; + //! @} + + private: + EuroscopeSimData(); + }; + + //! Equal to operator + inline bool operator==(const EuroscopeSimData &lhs, const EuroscopeSimData &rhs) + { + return lhs.sender() == rhs.sender() && + lhs.receiver() == rhs.receiver() && + lhs.m_model == rhs.m_model && + lhs.m_livery == rhs.m_livery && + lhs.m_timestamp == rhs.m_timestamp && + qFuzzyCompare(lhs.m_latitude, rhs.m_latitude) && + qFuzzyCompare(lhs.m_longitude, rhs.m_longitude) && + qFuzzyCompare(lhs.m_altitude, rhs.m_altitude) && + qFuzzyCompare(lhs.m_heading, rhs.m_heading) && + lhs.m_bank == rhs.m_bank && + lhs.m_pitch == rhs.m_pitch && + lhs.m_groundSpeed == rhs.m_groundSpeed && + lhs.m_onGround == rhs.m_onGround && + lhs.m_gearPercent == rhs.m_gearPercent && + lhs.m_thrustPercent == rhs.m_thrustPercent && + lhs.m_lights == rhs.m_lights; + } + + //! Not equal to operator + inline bool operator!=(const EuroscopeSimData &lhs, const EuroscopeSimData &rhs) + { + return !(lhs == rhs); + } +} + +#endif // guard diff --git a/src/blackcore/fsd/messagebase.h b/src/blackcore/fsd/messagebase.h index 7b967137e..7f7486580 100644 --- a/src/blackcore/fsd/messagebase.h +++ b/src/blackcore/fsd/messagebase.h @@ -33,6 +33,7 @@ enum class MessageType ClientResponse, DeleteATC, DeletePilot, + EuroscopeSimData, // Euroscope only FlightPlan, ProController, FsdIdentification, diff --git a/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp b/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp index 2dbf1c7f3..7a0764ee8 100644 --- a/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp +++ b/tests/blackcore/fsd/testfsdmessages/testfsdmessages.cpp @@ -23,6 +23,7 @@ #include "blackcore/fsd/clientidentification.h" #include "blackcore/fsd/deleteatc.h" #include "blackcore/fsd/deletepilot.h" +#include "blackcore/fsd/euroscopesimdata.h" #include "blackcore/fsd/pbh.h" #include "blackcore/fsd/pilotdataupdate.h" #include "blackcore/fsd/ping.h" @@ -76,6 +77,7 @@ namespace BlackMiscTest void testClientResponse(); void testDeleteAtc(); void testDeletePilot(); + void testEuroscopeSimData(); void testFlightPlan(); void testFSDIdentification(); void testInterimPilotDataUpdate(); @@ -296,6 +298,45 @@ namespace BlackMiscTest } + void CTestFsdMessages::testEuroscopeSimData() + { + const EuroscopeSimData message("ABCD", "A320", "DLH", 0, 43.1257800, -72.1584100, 12000, 180, 10, -10, 250, false, 0, 50, {}); + + QCOMPARE(message.sender(), QString("ABCD")); + QCOMPARE(QString(""), message.receiver()); + QCOMPARE(43.12578, message.m_latitude); + QCOMPARE(-72.15841, message.m_longitude); + QCOMPARE(12000, message.m_altitude); + QCOMPARE(180, message.m_heading); + QCOMPARE(10, message.m_bank); + QCOMPARE(-10, message.m_pitch); + QCOMPARE(250, message.m_groundSpeed); + QCOMPARE(false, message.m_onGround); + QCOMPARE(0, message.m_gearPercent); + QCOMPARE(50, message.m_thrustPercent); + QCOMPARE(CAircraftLights(), message.m_lights); + + QString stringRef(":ABCD:A320:DLH:0:43.1257800:-72.1584100:12000.0:180.00:10:-10:250:0:0:50:0:0.0:0"); + QString str = message.toTokens().join(":"); + QCOMPARE(str, stringRef); + + QStringList tokens = QString(":ABCD:A320:DLH:0:43.1257800:-72.1584100:12000:180.00:10:-10:250:0:0:50:0:0.0:0").split(':'); + auto messageFromTokens = EuroscopeSimData::fromTokens(tokens); + QCOMPARE(QString("ABCD"), messageFromTokens.sender()); + QCOMPARE(QString(""), messageFromTokens.receiver()); + QCOMPARE(43.12578, messageFromTokens.m_latitude); + QCOMPARE(-72.15841, messageFromTokens.m_longitude); + QCOMPARE(12000, messageFromTokens.m_altitude); + QCOMPARE(180, messageFromTokens.m_heading); + QCOMPARE(10, messageFromTokens.m_bank); + QCOMPARE(-10, messageFromTokens.m_pitch); + QCOMPARE(250, messageFromTokens.m_groundSpeed); + QCOMPARE(false, messageFromTokens.m_onGround); + QCOMPARE(0, messageFromTokens.m_gearPercent); + QCOMPARE(50, messageFromTokens.m_thrustPercent); + QCOMPARE(CAircraftLights(), messageFromTokens.m_lights); + } + void CTestFsdMessages::testFlightPlan() { const FlightPlan message("ABCD", "SERVER", FlightType::VFR, "B744", 420, "EGLL", 1530, 1535, "FL350", "KORD", 8, 15,