diff --git a/samples/blackcore/sample_blackcore.pro b/samples/blackcore/sample_blackcore.pro index 92c88bad2..f73fa5137 100644 --- a/samples/blackcore/sample_blackcore.pro +++ b/samples/blackcore/sample_blackcore.pro @@ -12,7 +12,7 @@ DEPENDPATH += . ../../src/blackmisc ../../src/blacksound ../../src/blackcore INCLUDEPATH += . ../../src LIBS += -L../../lib -lblackcore -lblacksound -lblackmisc -LIBS += -lvatlib +LIBS += -lvatlib -lSimConnect win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \ ../../lib/blacksound.lib \ diff --git a/samples/blackgui/sample_blackgui.pro b/samples/blackgui/sample_blackgui.pro index 3d822429d..6b70c7f47 100644 --- a/samples/blackgui/sample_blackgui.pro +++ b/samples/blackgui/sample_blackgui.pro @@ -18,6 +18,7 @@ DESTDIR = ../../bin LIBS += -L../../lib -lblackcore -lblackgui -lblacksound -lblackmisc LIBS += -lvatlib +LIBS += -lSimConnect win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \ ../../lib/blackgui.lib \ diff --git a/src/blackcore/blackcore.pro b/src/blackcore/blackcore.pro index 9ec5f444f..f426f0817 100644 --- a/src/blackcore/blackcore.pro +++ b/src/blackcore/blackcore.pro @@ -11,7 +11,7 @@ CONFIG += staticlib c++11 INCLUDEPATH += .. DEPENDPATH += . .. -LIBS += -L../../lib -lblacksound -lblackmisc +LIBS += -L../../lib -lblacksound -lblackmisc -lSimConnect # linux-g++* { QMAKE_CXXFLAGS += -std=c++0x } # PRECOMPILED_HEADER = stdpch.h @@ -37,6 +37,10 @@ DEFINES += LOG_IN_FILE HEADERS += *.h SOURCES += *.cpp +HEADERS += $$PWD/fsx/*.h +SOURCES += $$PWD/fsx/*.cpp + + win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib ../../lib/blacksound.lib else: PRE_TARGETDEPS += ../../lib/libblackmisc.a ../../lib/libblacksound.a diff --git a/src/blackcore/fsx/simconnect_datadefinition.cpp b/src/blackcore/fsx/simconnect_datadefinition.cpp new file mode 100644 index 000000000..db6e63f4a --- /dev/null +++ b/src/blackcore/fsx/simconnect_datadefinition.cpp @@ -0,0 +1,45 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "simconnect_datadefinition.h" +#include "simconnect/SimConnect.h" + +namespace BlackCore +{ + namespace FSX + { + + CSimConnectDataDefinition::CSimConnectDataDefinition() + { + } + + HRESULT CSimConnectDataDefinition::initDataDefinitions(const HANDLE hSimConnect) + { + HRESULT hr = S_OK; + hr = initOwnAircraft(hSimConnect); + return hr; + } + + HRESULT CSimConnectDataDefinition::initOwnAircraft(const HANDLE hSimConnect) + { + HRESULT hr = S_OK; + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Latitude", "Degrees"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Longitude", "Degrees"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Altitude", "Feet"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Heading Degrees True", "Degrees"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Pitch Degrees", "Degrees"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Bank Degrees", "Degrees"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "GROUND VELOCITY", "knots"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "SIM ON GROUND", "bool"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "TRANSPONDER CODE:1", NULL); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM ACTIVE FREQUENCY:1", "MHz"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM ACTIVE FREQUENCY:2", "MHz"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM STANDBY FREQUENCY:1", "MHz"); + hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM STANDBY FREQUENCY:2", "MHz"); + + return hr; + } + } +} diff --git a/src/blackcore/fsx/simconnect_datadefinition.h b/src/blackcore/fsx/simconnect_datadefinition.h new file mode 100644 index 000000000..24c516520 --- /dev/null +++ b/src/blackcore/fsx/simconnect_datadefinition.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKCORE_FSX_SIMCONNECT_DATADEFINITION_H +#define BLACKCORE_FSX_SIMCONNECT_DATADEFINITION_H + +#include + +namespace BlackCore +{ + namespace FSX + { + //! \brief Data struct of our own aircraft + struct OwnAircraft + { + double latitude; //!< Latitude + double longitude; //!< Longitude + double altitude; //!< Altitude + double trueHeading; //!< True heading + double pitch; //!< Pitch + double bank; //!< Bank + double velocity; //!< Ground velocity + double simOnGround; //!< Is sim on ground? + double transponderCode; //!< Transponder Code + double com1ActiveMHz; //!< COM1 active frequency + double com2ActiveMHz; //!< COM2 active frequency + double com1StandbyMHz; //!< COM1 standby frequency + double com2StandbyMHz; //!< COM1 standby frequency + }; + + //! \brief Handles SimConnect data definitions + class CSimConnectDataDefinition + { + public: + + //! \brief SimConnect definiton ID's + enum DataDefiniton { + DataOwnAircraft, + }; + + //! \brief SimConnect request ID's + enum Requests { + RequestOwnAircraft = 1000 + }; + + //! \brief Constructor + CSimConnectDataDefinition(); + + /*! + * \brief Initialize all data definitions + * \param hSimConnect + * \return + */ + static HRESULT initDataDefinitions(const HANDLE hSimConnect); + + /*! + * \brief Initialize data definition for our own aircraft + * \param hSimConnect + * \return + */ + static HRESULT initOwnAircraft(const HANDLE hSimConnect); + }; + } +} + +#endif // BLACKCORE__FSX_SIMCONNECT_DATADEFINITION_H diff --git a/src/blackcore/fsx/simconnect_exception.cpp b/src/blackcore/fsx/simconnect_exception.cpp new file mode 100644 index 000000000..3ae259eed --- /dev/null +++ b/src/blackcore/fsx/simconnect_exception.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "simconnect_exception.h" +#include + +namespace BlackCore +{ + namespace FSX + { + CSimConnectException::CSimConnectException() + { + } + + void CSimConnectException::handleException(SIMCONNECT_EXCEPTION exception) + { + switch(exception) + { + case SIMCONNECT_EXCEPTION_ERROR: + break; + case SIMCONNECT_EXCEPTION_SIZE_MISMATCH: + break; + case SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID: + break; + case SIMCONNECT_EXCEPTION_UNOPENED: + break; + case SIMCONNECT_EXCEPTION_VERSION_MISMATCH: + break; + case SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS: + break; + case SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED: + break; + case SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES: + break; + case SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE: + break; + case SIMCONNECT_EXCEPTION_TOO_MANY_MAPS: + break; + case SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS: + break; + case SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS: + break; + case SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT: + break; + case SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR: + break; + case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION: + break; + case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION: + break; + case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION: + break; + case SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE: + break; + case SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE: + { + qDebug() << "Invalid data size!"; + break; + } + case SIMCONNECT_EXCEPTION_DATA_ERROR: + break; + case SIMCONNECT_EXCEPTION_INVALID_ARRAY: + break; + case SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED: + { + qDebug() << "Failed to create object!"; + break; + } + case SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED: + break; + case SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE: + break; + case SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION: + break; + case SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED: + break; + case SIMCONNECT_EXCEPTION_INVALID_ENUM: + break; + case SIMCONNECT_EXCEPTION_DEFINITION_ERROR: + break; + case SIMCONNECT_EXCEPTION_DUPLICATE_ID: + break; + case SIMCONNECT_EXCEPTION_DATUM_ID: + break; + case SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS: + break; + case SIMCONNECT_EXCEPTION_ALREADY_CREATED: + break; + case SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE: + break; + case SIMCONNECT_EXCEPTION_OBJECT_CONTAINER: + break; + case SIMCONNECT_EXCEPTION_OBJECT_AI: + break; + case SIMCONNECT_EXCEPTION_OBJECT_ATC: + break; + case SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE: + break; + default: + break; + } + } + } +} diff --git a/src/blackcore/fsx/simconnect_exception.h b/src/blackcore/fsx/simconnect_exception.h new file mode 100644 index 000000000..94413c5c4 --- /dev/null +++ b/src/blackcore/fsx/simconnect_exception.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H +#define BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H + +#include "simconnect/SimConnect.h" + +namespace BlackCore +{ + namespace FSX + { + //! \brief Handles SimConnect exceptions + class CSimConnectException + { + public: + CSimConnectException(); + + /*! + * \brief Handle exception + * \param exception + */ + static void handleException(SIMCONNECT_EXCEPTION exception); + }; + } +} + +#endif // BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H diff --git a/src/blackcore/fsx/simulator_fsx.cpp b/src/blackcore/fsx/simulator_fsx.cpp new file mode 100644 index 000000000..a6b7e6c68 --- /dev/null +++ b/src/blackcore/fsx/simulator_fsx.cpp @@ -0,0 +1,207 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "simulator_fsx.h" +#include "simconnect_datadefinition.h" +#include "simconnect_exception.h" +#include + +using namespace BlackMisc::Aviation; +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; + +namespace BlackCore +{ + namespace FSX + { + CSimulatorFSX::CSimulatorFSX(QObject *parent) : + ISimulator(parent), + m_isConnected(false), + m_simRunning(false), + m_hSimConnect(nullptr) + { + QTimer::singleShot(5000, this, SLOT(checkConnection())); + } + + bool CSimulatorFSX::isConnected() const + { + return m_isConnected; + } + + void CALLBACK CSimulatorFSX::SimConnectProc(SIMCONNECT_RECV* pData, DWORD /* cbData */, void *pContext) + { + CSimulatorFSX *simulatorFsx = static_cast(pContext); + + switch(pData->dwID) + { + case SIMCONNECT_RECV_ID_EXCEPTION: + { + SIMCONNECT_RECV_EXCEPTION *event = (SIMCONNECT_RECV_EXCEPTION*)pData; + CSimConnectException::handleException((SIMCONNECT_EXCEPTION)event->dwException); + break; + } + case SIMCONNECT_RECV_ID_QUIT: + { + simulatorFsx->onSimExit(); + break; + } + case SIMCONNECT_RECV_ID_EVENT: + { + SIMCONNECT_RECV_EVENT *event = static_cast(pData); + + switch(event->uEventID) + { + case EVENT_SIM_STATUS: + if (event->dwData) + { + simulatorFsx->onSimRunning(); + } + else + { + simulatorFsx->onSimStopped(); + } + break; + } + break; + } + case SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE: + { + SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE *event = static_cast(pData); + if (event->uEventID == EVENT_OBJECT_ADDED) + { + } + else if (event->uEventID == EVENT_OBJECT_REMOVED) + { + } + + break; + } + case SIMCONNECT_RECV_ID_EVENT_FRAME: + { + simulatorFsx->onSimFrame(); + break; + } + case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID: + { + SIMCONNECT_RECV_ASSIGNED_OBJECT_ID *event = static_cast(pData); + simulatorFsx->setSimconnectObjectID(event->dwRequestID, event->dwObjectID); + } + case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: + { + SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*) pData; + switch(pObjData->dwRequestID) + { + case CSimConnectDataDefinition::RequestOwnAircraft: + OwnAircraft *ownAircaft; + ownAircaft = (OwnAircraft*)&pObjData->dwData; + simulatorFsx->setOwnAircraft(*ownAircaft); + break; + } + break; + } + + } + } + + void CSimulatorFSX::onSimRunning() + { + m_simRunning = true; + SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::RequestOwnAircraft, + CSimConnectDataDefinition::DataOwnAircraft, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME); + } + + void CSimulatorFSX::onSimStopped() + { + m_simRunning = false; + } + + void CSimulatorFSX::onSimFrame() + { + } + + void CSimulatorFSX::onSimExit() + { + + } + + void CSimulatorFSX::setOwnAircraft(OwnAircraft aircraft) + { + BlackMisc::Geo::CCoordinateGeodetic position; + position.setLatitude(CLatitude(aircraft.latitude, CAngleUnit::deg())); + position.setLongitude(CLongitude(aircraft.longitude, CAngleUnit::deg())); + + BlackMisc::Aviation::CAircraftSituation aircraftSituation; + aircraftSituation.setPosition(position); + aircraftSituation.setPitch(CAngle(aircraft.pitch, CAngleUnit::deg())); + aircraftSituation.setBank(CAngle(aircraft.bank, CAngleUnit::deg())); + aircraftSituation.setHeading(CHeading(aircraft.trueHeading, CHeading::True, CAngleUnit::deg())); + aircraftSituation.setGroundspeed(CSpeed(aircraft.velocity, CSpeedUnit::kts())); + aircraftSituation.setAltitude(CAltitude(aircraft.altitude, CAltitude::MeanSeaLevel, CLengthUnit::ft())); + + CComSystem com1; + com1.setFrequencyActive(CFrequency(aircraft.com1ActiveMHz, CFrequencyUnit::MHz())); + com1.setFrequencyStandby(CFrequency(aircraft.com1StandbyMHz, CFrequencyUnit::MHz())); + + CComSystem com2; + com2.setFrequencyActive(CFrequency(aircraft.com2ActiveMHz, CFrequencyUnit::MHz())); + com2.setFrequencyStandby(CFrequency(aircraft.com2StandbyMHz, CFrequencyUnit::MHz())); + + CTransponder transponder("Transponder", aircraft.transponderCode, CTransponder::ModeC); + + m_ownAircraft.setSituation(aircraftSituation); + m_ownAircraft.setCom1System(com1); + m_ownAircraft.setCom2System(com2); + m_ownAircraft.setTransponder(transponder); + } + + void CSimulatorFSX::setSimconnectObjectID(DWORD /* requestID */, DWORD /* objectID */) + { + + } + + void CSimulatorFSX::timerEvent(QTimerEvent* /* event */) + { + dispatch(); + } + + void CSimulatorFSX::checkConnection() + { + if (FAILED(SimConnect_Open(&m_hSimConnect, "BlackBox", nullptr, 0, 0, 0))) + { + QTimer::singleShot(5000, this, SLOT(checkConnection())); + return; + } + + initSystemEvents(); + initDataDefinitions(); + startTimer(50); + m_isConnected = true; + + emit connectionChanged(true); + } + + void CSimulatorFSX::dispatch() + { + SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this); + } + + HRESULT CSimulatorFSX::initSystemEvents() + { + HRESULT hr = S_OK; + // System events + hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_SIM_STATUS, "Sim"); + hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_OBJECT_ADDED, "ObjectAdded"); + hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_OBJECT_REMOVED, "ObjectRemoved"); + + return hr; + } + + HRESULT CSimulatorFSX::initDataDefinitions() + { + return CSimConnectDataDefinition::initDataDefinitions(m_hSimConnect); + } + } +} diff --git a/src/blackcore/fsx/simulator_fsx.h b/src/blackcore/fsx/simulator_fsx.h new file mode 100644 index 000000000..813be5125 --- /dev/null +++ b/src/blackcore/fsx/simulator_fsx.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKCORE_SIMULATOR_FSX_H +#define BLACKCORE_SIMULATOR_FSX_H + +#include +#include "simconnect_datadefinition.h" +#include "blackmisc/avaircraft.h" +#include +#include "simconnect/SimConnect.h" +#include + +namespace BlackCore +{ + namespace FSX + { + //! \brief SimConnect Event ID's + enum EVENT_ID { + EVENT_SIM_STATUS, + EVENT_OBJECT_ADDED, + EVENT_OBJECT_REMOVED, + EVENT_SLEW_ON, + EVENT_FRAME, + EVENT_FREEZELAT, + EVENT_FREEZEALT, + EVENT_FREEZEATT + }; + + //! \brief FSX Simulator Implementation + class CSimulatorFSX : public ISimulator + { + Q_OBJECT + public: + //! \brief Constructor + CSimulatorFSX(QObject *parent = nullptr); + + //! \copydoc ISimulator::isConnected() + virtual bool isConnected() const override; + + //! \copydoc ISimulator::getOwnAircraft() + virtual BlackMisc::Aviation::CAircraft getOwnAircraft() const override { return m_ownAircraft; } + + /*! + * \brief SimConnect Callback + * \param pData + * \param cbData + * \param pContext + */ + static void CALLBACK SimConnectProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext); + + //! \brief Called when sim has started + void onSimRunning(); + + //! \brief Called when sim has stopped + void onSimStopped(); + + //! \brief Slot called every visual frame + void onSimFrame(); + + /*! + * \brief Called when data about our own aircraft is received + * \param aircraft + */ + void setOwnAircraft(OwnAircraft aircraft); + + /*! + * \brief Set ID of a SimConnect object + * \param requestID + * \param objectID + */ + void setSimconnectObjectID(DWORD requestID, DWORD objectID); + + //! \private + void onSimExit(); + + protected: + //! \brief Timer event + virtual void timerEvent(QTimerEvent *event); + + private slots: + //! \brief Try to connect + void checkConnection(); + + //! \brief Dispatch SimConnect messages + void dispatch(); + + private: + + /*! + * \brief Initialize SimConnect system events + * \return + */ + HRESULT initSystemEvents(); + + /*! + * \brief Initialize SimConnect data definitions + * \return + */ + HRESULT initDataDefinitions(); + + bool m_isConnected; //!< Is sim connected + bool m_simRunning; //!< Sim running. + HANDLE m_hSimConnect; //!< Handle to SimConnect object + + BlackMisc::Aviation::CAircraft m_ownAircraft; //!< Object representing our own aircraft from simulator + + }; + } + +} // namespace BlackCore + +#endif // BLACKCORE_SIMULATOR_FSX_H