diff --git a/src/blackmisc/nwaircraftmodel.h b/src/blackmisc/nwaircraftmodel.h index 43d9b99ee..8a672431a 100644 --- a/src/blackmisc/nwaircraftmodel.h +++ b/src/blackmisc/nwaircraftmodel.h @@ -56,6 +56,9 @@ namespace BlackMisc //! Queried model string const QString &getModelString() const { return this->m_modelString; } + //! Queried model string + void setModelString(const QString &modelString) { this->m_modelString = modelString; } + //! Set queried model string void setQueriedModelString(const QString &model) { this->m_modelString = model; } diff --git a/src/plugins/simulator/fsx/fsuipc.cpp b/src/plugins/simulator/fsx/fsuipc.cpp index e835220b0..2d6871f55 100644 --- a/src/plugins/simulator/fsx/fsuipc.cpp +++ b/src/plugins/simulator/fsx/fsuipc.cpp @@ -3,19 +3,33 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef NOMINMAX +#define NOMINMAX +#endif + #include "fsuipc.h" #include // bug in FSUIPC_User.h, windows.h not included, so we have to import it first #include "FSUIPC/FSUIPC_User.h" + +#include "blacksim/fscommon/bcdconversions.h" #include #include +#include + +using namespace BlackSim::FsCommon; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Network; +using namespace BlackMisc::Geo; +using namespace BlackMisc::PhysicalQuantities; namespace BlackSimPlugin { namespace Fsx { - CFsuipc::CFsuipc() : m_connected(false) + CFsuipc::CFsuipc() : m_connected(false), m_validReadValues(false) { } CFsuipc::~CFsuipc() @@ -28,10 +42,10 @@ namespace BlackSimPlugin DWORD result; this->m_lastErrorMessage = ""; if (this->m_connected) return this->m_connected; // already connected + this->m_validReadValues = false; if (FSUIPC_Open(SIM_ANY, &result)) { this->m_connected = true; - // KB_REMOVE: Remove this later int simIndex = static_cast(FSUIPC_FS_Version); QString sim( (simIndex >= 0 && simIndex < CFsuipc::simulators().size()) ? @@ -44,6 +58,7 @@ namespace BlackSimPlugin .arg(QLatin1Char(48 + (0x0f & (FSUIPC_Version >> 16)))) .arg((FSUIPC_Version & 0xffff) ? "a" + (FSUIPC_Version & 0xff) - 1 : ""); this->m_fsuipcVersion = QString("FSUIPC %1 (%2)").arg(ver).arg(sim); + // KB_REMOVE: Remove this later qDebug() << "FSUIPC connected" << this->m_fsuipcVersion; } else @@ -61,6 +76,152 @@ namespace BlackSimPlugin { FSUIPC_Close(); // Closing when it wasn't open is okay, so this is safe here this->m_connected = false; + this->m_validReadValues = false; + } + + void CFsuipc::process() + { + if (!this->m_connected) return; + this->read(); + } + + void CFsuipc::read() + { + DWORD dwResult; + char localFsTimeRaw[3]; + char modelNameRaw[256]; + qint16 com1ActiveRaw; + qint16 com2ActiveRaw; + qint16 com1StandbyRaw; + qint16 com2StandbyRaw; + qint16 transponderCodeRaw; + qint8 xpdrModeSb3Raw; + qint8 xpdrIdentSb3Raw; + qint32 groundspeedRaw; + qint32 pitchRaw; + qint32 bankRaw; + qint32 headingRaw; + qint64 altitudeRaw; + qint32 groundAltitudeRaw; + qint64 latitudeRaw; + qint64 longitudeRaw; + + // http://www.projectmagenta.com/all-fsuipc-offsets/ + // https://www.ivao.aero/softdev/ivap/fsuipc_sdk.asp + // http://squawkbox.ca/doc/sdk/fsuipc.php + + if (FSUIPC_Read(0x0238, 3, localFsTimeRaw, &dwResult) && + + // COM settings + FSUIPC_Read(0x034e, 2, &com1ActiveRaw, &dwResult) && + FSUIPC_Read(0x3118, 2, &com2ActiveRaw, &dwResult) && + FSUIPC_Read(0x311a, 2, &com1StandbyRaw, &dwResult) && + FSUIPC_Read(0x311c, 2, &com2StandbyRaw, &dwResult) && + FSUIPC_Read(0x0354, 2, &transponderCodeRaw, &dwResult) && + + // COM Settings, transponder, SB3 + FSUIPC_Read(0x7b91, 1, &xpdrModeSb3Raw, &dwResult) && + FSUIPC_Read(0x7b92, 1, &xpdrIdentSb3Raw, &dwResult) && + + // Speeds, situation + FSUIPC_Read(0x02b4, 4, &groundspeedRaw, &dwResult) && + FSUIPC_Read(0x0578, 4, &pitchRaw, &dwResult) && + FSUIPC_Read(0x057c, 4, &bankRaw, &dwResult) && + FSUIPC_Read(0x0580, 4, &headingRaw, &dwResult) && + FSUIPC_Read(0x0570, 8, &altitudeRaw, &dwResult) && + + // Position + FSUIPC_Read(0x0560, 8, &latitudeRaw, &dwResult) && + FSUIPC_Read(0x0568, 8, &longitudeRaw, &dwResult) && + FSUIPC_Read(0x0020, 4, &groundAltitudeRaw, &dwResult) && + + // model name + FSUIPC_Read(0x3d00, 256, &modelNameRaw, &dwResult) && + + // If we wanted other reads/writes at the same time, we could put them here + FSUIPC_Process(&dwResult)) + { + this->m_validReadValues = true; + + // time, basically as a heartbeat + QString fsTime; + fsTime.sprintf("%02d:%02d:%02d", localFsTimeRaw[0], localFsTimeRaw[1], localFsTimeRaw[2]); + + // model + const QString modelName = QString(modelNameRaw); // to be used to distinguish offsets for different models + m_model.setModelString(modelName); + + // COMs + CComSystem com1 = this->m_aircraft.getCom1System(); + CComSystem com2 = this->m_aircraft.getCom2System(); + CTransponder xpdr = this->m_aircraft.getTransponder(); + + // 2710 => 12710 => / 100.0 => 127.1 + com1ActiveRaw = (10000 + CBcdConversions::bcd2Dec(com1ActiveRaw)); + com2ActiveRaw = (10000 + CBcdConversions::bcd2Dec(com2ActiveRaw)); + com1StandbyRaw = (10000 + CBcdConversions::bcd2Dec(com1StandbyRaw)); + com2StandbyRaw = (10000 + CBcdConversions::bcd2Dec(com2StandbyRaw)); + com1.setFrequencyActiveMHz(com1ActiveRaw / 100.0); + com2.setFrequencyActiveMHz(com2ActiveRaw / 100.0); + com1.setFrequencyStandbyMHz(com1StandbyRaw / 100.0); + com2.setFrequencyStandbyMHz(com2StandbyRaw / 100.0); + + transponderCodeRaw = CBcdConversions::bcd2Dec(transponderCodeRaw); + xpdr.setTransponderCode(transponderCodeRaw); + // Mode by SB3 + if (xpdrIdentSb3Raw > 0) + { + // TODO: Reset value + xpdr.setTransponderMode(CTransponder::StateIdent); + } + else + { + xpdr.setTransponderMode( + xpdrModeSb3Raw == 0 ? CTransponder::ModeC : CTransponder::StateStandby + ); + } + this->m_aircraft.setCockpit(com1, com2, xpdr); + + // position + const double latCorrectionFactor = 90.0 / (10001750.0 * 65536.0 * 65536.0); + const double lonCorrectionFactor = 360.0 / (65536.0 * 65536.0 * 65536.0 * 65536.0); + CAircraftSituation situation = this->m_aircraft.getSituation(); + CCoordinateGeodetic position = situation.getPosition(); + CLatitude lat(latitudeRaw * latCorrectionFactor, CAngleUnit::deg()); + CLongitude lon(longitudeRaw * lonCorrectionFactor, CAngleUnit::deg()); + CLength groundAltitude(groundAltitudeRaw / 256.0, CLengthUnit::m()); + position.setLatitude(lat); + position.setLongitude(lon); + position.setHeight(groundAltitude); + situation.setPosition(position); + + // speeds, situation + const double angleCorrectionFactor = 360.0 / 65536.0 / 65536.0; // see FSUIPC docu + CAngle pitch = CAngle(pitchRaw * angleCorrectionFactor, CAngleUnit::deg()); + CAngle bank = CAngle(bankRaw * angleCorrectionFactor, CAngleUnit::deg()); + CHeading heading = CHeading(headingRaw * angleCorrectionFactor, CHeading::True, CAngleUnit::deg()); + CSpeed groundspeed(groundspeedRaw / 65536.0, CSpeedUnit::m_s()); + CAltitude altitude(altitudeRaw / (65536.0 * 65536.0), CAltitude::MeanSeaLevel, CLengthUnit::m()); + situation.setBank(bank); + situation.setHeading(heading); + situation.setPitch(pitch); + situation.setGroundspeed(groundspeed); + situation.setAltitude(altitude); + this->m_aircraft.setSituation(situation); + + // qDebug() << m_aircraft; + } + else + { + this->m_validReadValues = false; + } + } + + double CFsuipc::intToFractional(double fractional) + { + double f = fractional / 10.0; + if (f < 1.0) return f; + return intToFractional(f); } } } diff --git a/src/plugins/simulator/fsx/fsuipc.h b/src/plugins/simulator/fsx/fsuipc.h index 3f934951a..e3afb51f3 100644 --- a/src/plugins/simulator/fsx/fsuipc.h +++ b/src/plugins/simulator/fsx/fsuipc.h @@ -6,12 +6,10 @@ #ifndef BLACKSIMPLUGIN_FSUIPC_H #define BLACKSIMPLUGIN_FSUIPC_H +#include "blackmisc/avaircraft.h" +#include "blackmisc/nwaircraftmodel.h" #include -// SB offsets -// http://board.vacc-sag.org/32/7945/#post75582 -// http://squawkbox.ca/doc/sdk/fsuipc.php - namespace BlackSimPlugin { namespace Fsx @@ -36,6 +34,12 @@ namespace BlackSimPlugin //! Is connected? bool isConnected() const { return m_connected; } + //! Valid read values + bool validReadValues() const { return m_validReadValues; } + + //! Process reading and writing variables + void process(); + //! Error messages static const QStringList &errorMessages() { @@ -75,8 +79,18 @@ namespace BlackSimPlugin private: bool m_connected; + bool m_validReadValues; QString m_lastErrorMessage; QString m_fsuipcVersion; + BlackMisc::Aviation::CAircraft m_aircraft; //!< FSUIPC read aircraft + BlackMisc::Network::CAircraftModel m_model; //!< FSUIPC read model + + //! Read data from FSUIPC + void read(); + + //! Integer representing fractional + static double intToFractional(double fractional); + }; } } diff --git a/src/plugins/simulator/fsx/simulator_fsx.cpp b/src/plugins/simulator/fsx/simulator_fsx.cpp index 7cd4b5d79..24d9eb6cd 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx.cpp @@ -478,6 +478,7 @@ namespace BlackSimPlugin void CSimulatorFsx::dispatch() { SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this); + if (this->m_fsuipc) this->m_fsuipc->process(); } void CSimulatorFsx::connectToFinished()