From e11a3c1e6b50746f54041f3e2e3f6ab8a043352f Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 29 Nov 2014 13:14:57 +0100 Subject: [PATCH] refs #349, added SB client area (for ident, transponder mode) to driver * added SB client area support * renamed member functions to better reflect meaning * added all structures required for SB client area * changed to new logging --- .../fsx/simconnect_datadefinition.cpp | 118 +++++++---- .../simulator/fsx/simconnect_datadefinition.h | 77 +++++-- .../simulator/fsx/simconnect_object.cpp | 11 +- src/plugins/simulator/fsx/simconnect_object.h | 22 +- src/plugins/simulator/fsx/simulator_fsx.cpp | 188 +++++++++++++----- src/plugins/simulator/fsx/simulator_fsx.h | 42 ++-- .../fsx/simulator_fsx_simconnectproc.cpp | 30 ++- 7 files changed, 349 insertions(+), 139 deletions(-) diff --git a/src/plugins/simulator/fsx/simconnect_datadefinition.cpp b/src/plugins/simulator/fsx/simconnect_datadefinition.cpp index 852e354b5..35f30d4e8 100644 --- a/src/plugins/simulator/fsx/simconnect_datadefinition.cpp +++ b/src/plugins/simulator/fsx/simconnect_datadefinition.cpp @@ -8,76 +8,126 @@ */ #include "simconnect_datadefinition.h" +#include "blackmisc/logmessage.h" + +using namespace BlackMisc; namespace BlackSimPlugin { namespace Fsx { - CSimConnectDataDefinition::CSimConnectDataDefinition() { } + CSimConnectDefinitions::CSimConnectDefinitions() { } - HRESULT CSimConnectDataDefinition::initDataDefinitions(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::initDataDefinitionsWhenConnected(const HANDLE hSimConnect) { HRESULT hr = S_OK; hr += initOwnAircraft(hSimConnect); hr += initRemoteAircraftSituation(hSimConnect); hr += initGearHandlePosition(hSimConnect); hr += initSimulatorEnvironment(hSimConnect); + hr += initSbDataArea(hSimConnect); return hr; } - HRESULT CSimConnectDataDefinition::initOwnAircraft(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::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"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraftTitle, "TITLE", NULL, SIMCONNECT_DATATYPE_STRING256); - if (hr != S_OK) { - qFatal("initOwnAircraft"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Latitude", "Degrees"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Longitude", "Degrees"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Altitude", "Feet"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Heading Degrees True", "Degrees"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Pitch Degrees", "Degrees"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "Plane Bank Degrees", "Degrees"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GROUND VELOCITY", "knots"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SIM ON GROUND", "bool"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "TRANSPONDER CODE:1", NULL); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:1", "MHz"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:2", "MHz"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:1", "MHz"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:2", "MHz"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraftTitle, "TITLE", NULL, SIMCONNECT_DATATYPE_STRING256); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: initOwnAircraft %1") << hr; } return hr; } - HRESULT CSimConnectDataDefinition::initRemoteAircraftSituation(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::initRemoteAircraftSituation(const HANDLE hSimConnect) { HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataRemoteAircraftSituation, "Initial Position", "", SIMCONNECT_DATATYPE_INITPOSITION); - if (hr != S_OK) { - qFatal("initRemoteAircraftSituation"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSituation, "Initial Position", "", SIMCONNECT_DATATYPE_INITPOSITION); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSituation %1") << hr; } return hr; } - HRESULT CSimConnectDataDefinition::initGearHandlePosition(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::initGearHandlePosition(const HANDLE hSimConnect) { HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataGearHandlePosition, "GEAR HANDLE POSITION", "BOOL", SIMCONNECT_DATATYPE_INT32); - if (hr != S_OK) { - qFatal("initGearHandlePosition"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataGearHandlePosition, "GEAR HANDLE POSITION", "BOOL", SIMCONNECT_DATATYPE_INT32); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: initGearHandlePosition %1") << hr; } return hr; } - HRESULT CSimConnectDataDefinition::initSimulatorEnvironment(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::initSimulatorEnvironment(const HANDLE hSimConnect) { HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataSimEnvironment, "ZULU TIME", "", SIMCONNECT_DATATYPE_INT32); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataSimEnvironment, "LOCAL TIME", "", SIMCONNECT_DATATYPE_INT32); - if (hr != S_OK) { - qFatal("initSimulatorEnvironment"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "ZULU TIME", "", SIMCONNECT_DATATYPE_INT32); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "LOCAL TIME", "", SIMCONNECT_DATATYPE_INT32); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: initSimulatorEnvironment %1") << hr; } return hr; } - } -} + + HRESULT CSimConnectDefinitions::initSbDataArea(const HANDLE hSimConnect) + { + HRESULT hr = S_OK; + DWORD sbSize = sizeof(DataDefinitionClientAreaSb); + + // We need to know the client area 'name' and map it to a client ID + hr += SimConnect_MapClientDataNameToID(hSimConnect, "SquawkBox Data", ClientAreaSquawkBox); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_MapClientDataNameToID %1") << hr; + return hr; + } + + // Mapping needs to be first + hr += SimConnect_CreateClientData(hSimConnect, ClientAreaSquawkBox, sbSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_CreateClientData %1") << hr; + return hr; + } + + hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSb, 0, sbSize); + hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbStandby, 17, 1); + hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbIdent, 19, 1); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: SB data area data definitions %1") << hr; + return hr; + } + + // write a default client area so we are not suddenly squawking ident or so + DataDefinitionClientAreaSb sbArea; + sbArea.setDefaultValues(); + hr += SimConnect_SetClientData(hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSb, NULL, 0, sbSize, &sbArea); + if (hr != S_OK) + { + CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_SetClientData %1") << hr; + } + return hr; + } + + } // namespace +} // namespace diff --git a/src/plugins/simulator/fsx/simconnect_datadefinition.h b/src/plugins/simulator/fsx/simconnect_datadefinition.h index cab1aeb85..17b0dbf54 100644 --- a/src/plugins/simulator/fsx/simconnect_datadefinition.h +++ b/src/plugins/simulator/fsx/simconnect_datadefinition.h @@ -1,7 +1,13 @@ -/* 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/. */ +/* Copyright (C) 2013 + * 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 and at http://www.swift-project.org/license.html. 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 BLACKSIMPLUGIN_FSX_SIMCONNECT_DATADEFINITION_H #define BLACKSIMPLUGIN_FSX_SIMCONNECT_DATADEFINITION_H @@ -13,6 +19,8 @@ #endif #include #include +#include +#include namespace BlackSimPlugin { @@ -57,13 +65,46 @@ namespace BlackSimPlugin }; //! Data struct simulator environment - struct DataDefinitionSimEnvironment { + struct DataDefinitionSimEnvironment + { qint32 zuluTimeSeconds; //!< Simulator zulu (GMT) ime in secs. qint32 localTimeSeconds; //!< Simulator local time in secs. }; + //! The whole SB data area + struct DataDefinitionClientAreaSb + { + byte data[128] {}; //!< 128 bytes of data, offsets http://www.squawkbox.ca/doc/sdk/fsuipc.php + + //! Standby = 1, else 0 + byte getTransponderMode() const { return data[17]; } + + //! Ident = 1, else 0 + byte getIdent() const { return data[19]; } + + //! Ident? + bool isIdent() const { return getIdent() != 0; } + + //! Standby + bool isStandby() const { return getTransponderMode() != 0; } + + //! Set default values + void setDefaultValues() + { + std::fill(data, data + 128, 0); + data[17] = 1; // standby + data[19] = 0; // no ident + } + }; + + //! Client areas + enum ClientAreaId + { + ClientAreaSquawkBox + }; + //! Handles SimConnect data definitions - class CSimConnectDataDefinition + class CSimConnectDefinitions { public: @@ -74,23 +115,30 @@ namespace BlackSimPlugin DataOwnAircraftTitle, DataRemoteAircraftSituation, DataGearHandlePosition, - DataSimEnvironment + DataSimEnvironment, + DataClientAreaSb, //!< whole SB area + DataClientAreaSbIdent, //!< ident single value + DataClientAreaSbStandby //!< standby }; //! SimConnect request IDs - enum Requests + enum Request { RequestOwnAircraft, RequestRemoveAircraft, RequestOwnAircraftTitle, - RequestSimEnvironment + RequestSimEnvironment, + RequestSbData, // SB client area / XPDR mode .. }; //! Constructor - CSimConnectDataDefinition(); + CSimConnectDefinitions(); //! Initialize all data definitions - static HRESULT initDataDefinitions(const HANDLE hSimConnect); + static HRESULT initDataDefinitionsWhenConnected(const HANDLE hSimConnect); + + //! Log message category + static QString getMessageCategory() { return "swift.fsx.simconnect"; } private: @@ -105,8 +153,11 @@ namespace BlackSimPlugin //! Initialize data definition for Simulator environment static HRESULT initSimulatorEnvironment(const HANDLE hSimConnect); + + //! Initialize the SB data are + static HRESULT initSbDataArea(const HANDLE hSimConnect); }; - } -} + } // namespace +} // namespace #endif // guard diff --git a/src/plugins/simulator/fsx/simconnect_object.cpp b/src/plugins/simulator/fsx/simconnect_object.cpp index 033fddae5..c0dafe160 100644 --- a/src/plugins/simulator/fsx/simconnect_object.cpp +++ b/src/plugins/simulator/fsx/simconnect_object.cpp @@ -17,10 +17,7 @@ namespace BlackSimPlugin namespace Fsx { CSimConnectObject::CSimConnectObject() : - m_interpolator(new CInterpolatorLinear()), - m_requestId(-1), - m_objectId(-1) - { - } - } -} + m_interpolator(new CInterpolatorLinear()) + { } + } // namespace +} // namespace diff --git a/src/plugins/simulator/fsx/simconnect_object.h b/src/plugins/simulator/fsx/simconnect_object.h index accf0646f..e6daca113 100644 --- a/src/plugins/simulator/fsx/simconnect_object.h +++ b/src/plugins/simulator/fsx/simconnect_object.h @@ -1,7 +1,13 @@ -/* 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/. */ +/* Copyright (C) 2013 + * 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 and at http://www.swift-project.org/license.html. 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 BLACKSIMPLUGIN_SIMCONNECT_OBJECT_H #define BLACKSIMPLUGIN_SIMCONNECT_OBJECT_H @@ -50,10 +56,10 @@ namespace BlackSimPlugin BlackMisc::Aviation::CCallsign m_callsign; QSharedPointer m_interpolator; - int m_requestId; - int m_objectId; + int m_requestId = -1; + int m_objectId = -1; }; - } -} + } // namespace +} // namespace #endif // guard diff --git a/src/plugins/simulator/fsx/simulator_fsx.cpp b/src/plugins/simulator/fsx/simulator_fsx.cpp index d5c4bfb1a..0f1454e47 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx.cpp @@ -45,14 +45,7 @@ namespace BlackSimPlugin CSimulatorFsx::CSimulatorFsx(QObject *parent) : ISimulator(parent), - m_simConnected(false), - m_simRunning(false), - m_simTimeSynced(false), - m_hSimConnect(nullptr), - m_nextObjID(1), m_simulatorInfo(CSimulatorInfo::FSX()), - m_simconnectTimerId(-1), - m_skipCockpitUpdateCycles(0), m_fsuipc(new FsCommon::CFsuipc()) { CFsxSimulatorSetup setup; @@ -77,26 +70,27 @@ namespace BlackSimPlugin bool CSimulatorFsx::isFsuipcConnected() const { + Q_ASSERT(m_fsuipc); return m_fsuipc->isConnected(); } bool CSimulatorFsx::connectTo() { - if (m_simConnected) return true; + if (m_simConnected) { return true; } if (FAILED(SimConnect_Open(&m_hSimConnect, BlackMisc::CProject::systemNameAndVersionChar(), nullptr, 0, 0, 0))) { emit connectionStatusChanged(ConnectionFailed); - emitSimulatorCombinedStatus(); + emitSimulatorCombinedStatus(); // all status values at once return false; } else { + Q_ASSERT(m_fsuipc); this->m_fsuipc->connect(); // connect FSUIPC too } - initEvents(); - initDataDefinitions(); + initWhenConnected(); m_simconnectTimerId = startTimer(10); m_simConnected = true; @@ -112,7 +106,7 @@ namespace BlackSimPlugin // simplified connect, timers and signals not in different thread auto asyncConnectFunc = [&]() -> bool { - if (FAILED(SimConnect_Open(&m_hSimConnect, BlackMisc::CProject::systemNameAndVersionChar(), nullptr, 0, 0, 0))) return false; + if (FAILED(SimConnect_Open(&m_hSimConnect, BlackMisc::CProject::systemNameAndVersionChar(), nullptr, 0, 0, 0))) { return false; } this->m_fsuipc->connect(); // FSUIPC too return true; }; @@ -225,12 +219,17 @@ namespace BlackSimPlugin if (newCom1 != this->m_ownAircraft.getCom1System()) { if (newCom1.getFrequencyActive() != this->m_ownAircraft.getCom1System().getFrequencyActive()) + { + CFrequency newFreq = newCom1.getFrequencyActive(); SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom1Active, - CBcdConversions::comFrequencyToBcdHz(newCom1.getFrequencyActive()), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } if (newCom1.getFrequencyStandby() != this->m_ownAircraft.getCom1System().getFrequencyStandby()) + { + CFrequency newFreq = newCom1.getFrequencyStandby(); SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom1Standby, - CBcdConversions::comFrequencyToBcdHz(newCom1.getFrequencyStandby()), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - + CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } this->m_ownAircraft.setCom1System(newCom1); changed = true; } @@ -238,29 +237,54 @@ namespace BlackSimPlugin if (newCom2 != this->m_ownAircraft.getCom2System()) { if (newCom2.getFrequencyActive() != this->m_ownAircraft.getCom2System().getFrequencyActive()) + { + CFrequency newFreq = newCom2.getFrequencyActive(); SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom2Active, - CBcdConversions::comFrequencyToBcdHz(newCom2.getFrequencyActive()), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } if (newCom2.getFrequencyStandby() != this->m_ownAircraft.getCom2System().getFrequencyStandby()) + { + CFrequency newFreq = newCom2.getFrequencyStandby(); SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom2Standby, - CBcdConversions::comFrequencyToBcdHz(newCom2.getFrequencyStandby()), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - + CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } this->m_ownAircraft.setCom2System(newCom2); changed = true; } - if (newTransponder != this->m_ownAircraft.getTransponder()) + CTransponder xpdr = this->m_ownAircraft.getTransponder(); + if (newTransponder != xpdr) { - if (newTransponder.getTransponderCode() != this->m_ownAircraft.getTransponder().getTransponderCode()) + if (newTransponder.getTransponderCode() != xpdr.getTransponderCode()) { SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTransponderCode, CBcdConversions::transponderCodeToBcd(newTransponder), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); changed = true; } - this->m_ownAircraft.setTransponder(newTransponder); + + if (newTransponder.getTransponderMode() != xpdr.getTransponderMode()) + { + if (m_useSbOffsets) + { + byte ident = newTransponder.isIdentifying() ? 1 : 0; // 1 is ident + byte standby = newTransponder.isInStandby() ? 1 : 0; // 1 is standby + HRESULT hr = S_OK; + + hr += SimConnect_SetClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSbIdent, NULL, 0, 1, &ident); + hr += SimConnect_SetClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSbStandby, NULL, 0, 1, &standby); + if (hr != S_OK) + { + CLogMessage(this).warning("Setting transponder mode failed (SB offsets)"); + } + } + changed = true; + } + + if (changed) { this->m_ownAircraft.setTransponder(newTransponder); } } // avoid changes of cockpit back to old values due to an outdated read back value - if (changed) m_skipCockpitUpdateCycles = SkipUpdateCyclesForCockpit; + if (changed) { m_skipCockpitUpdateCycles = SkipUpdateCyclesForCockpit; } // bye return changed; @@ -311,21 +335,38 @@ namespace BlackSimPlugin void CSimulatorFsx::onSimRunning() { - if (m_simRunning) return; + if (m_simRunning) { return; } m_simRunning = true; - SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::RequestOwnAircraft, - CSimConnectDataDefinition::DataOwnAircraft, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME); + HRESULT hr; + hr = SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraft, + CSimConnectDefinitions::DataOwnAircraft, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME); - SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::RequestOwnAircraftTitle, - CSimConnectDataDefinition::DataOwnAircraftTitle, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, - SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); + hr += SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraftTitle, + CSimConnectDefinitions::DataOwnAircraftTitle, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, + SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); - SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::RequestSimEnvironment, - CSimConnectDataDefinition::DataSimEnvironment, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, - SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); + hr += SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestSimEnvironment, + CSimConnectDefinitions::DataSimEnvironment, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, + SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); + + if (hr != S_OK) + { + CLogMessage(this).error("FSX plugin: SimConnect_RequestDataOnSimObject failed"); + return; + } + + // Request the data from SB only when its changed and only ONCE so we don't have to run a 1sec event to get/set this info ;) + hr += SimConnect_RequestClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::RequestSbData, + CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED); + + if (hr != S_OK) + { + CLogMessage(this).error("FSX plugin: SimConnect_RequestClientData failed"); + return; + } emit simulatorStarted(); emitSimulatorCombinedStatus(); @@ -366,9 +407,8 @@ namespace BlackSimPlugin CComSystem com1 = m_ownAircraft.getCom1System(); // set defaults CComSystem com2 = m_ownAircraft.getCom2System(); - CTransponder transponder = m_ownAircraft.getTransponder(); - // When I change cockpit values in the sim (from GUI to simulator, not originating from simulator) + // 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. // To avoid jitters, I wait some update cylces to stabilize the values if (m_skipCockpitUpdateCycles < 1) @@ -381,22 +421,35 @@ namespace BlackSimPlugin com2.setFrequencyStandby(CFrequency(simulatorOwnAircraft.com2StandbyMHz, CFrequencyUnit::MHz())); m_ownAircraft.setCom2System(com2); - transponder.setTransponderCode(simulatorOwnAircraft.transponderCode); - m_ownAircraft.setTransponder(transponder); + m_ownAircraft.setTransponderCode(simulatorOwnAircraft.transponderCode); + } else + { --m_skipCockpitUpdateCycles; + } } - void CSimulatorFsx::setSimconnectObjectID(DWORD requestID, DWORD objectID) + void CSimulatorFsx::updateOwnAircraftFromSim(DataDefinitionClientAreaSb sbDataArea) + { + if (sbDataArea.isIdent()) + { + this->m_ownAircraft.setTransponderMode(CTransponder::StateIdent); + } + else + { + this->m_ownAircraft.setTransponderMode(sbDataArea.isStandby() ? CTransponder::StateStandby : CTransponder::ModeC); + } + } + + void CSimulatorFsx::setSimConnectObjectID(DWORD requestID, DWORD objectID) { // First check, if this request id belongs to us auto it = std::find_if(m_simConnectObjects.begin(), m_simConnectObjects.end(), [requestID](const CSimConnectObject & obj) { return obj.getRequestId() == static_cast(requestID); }); + if (it == m_simConnectObjects.end()) { return; } - if (it == m_simConnectObjects.end()) - return; - + // belongs to use it->setObjectId(objectID); SimConnect_AIReleaseControl(m_hSimConnect, objectID, requestID); SimConnect_TransmitClientEvent(m_hSimConnect, objectID, EventFreezeLat, 1, @@ -409,26 +462,26 @@ namespace BlackSimPlugin DataDefinitionGearHandlePosition gearHandle; gearHandle.gearHandlePosition = 1; - SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataGearHandlePosition, objectID, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(gearHandle), &gearHandle); + SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataGearHandlePosition, objectID, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(gearHandle), &gearHandle); } - void CSimulatorFsx::timerEvent(QTimerEvent * /* event */) + void CSimulatorFsx::timerEvent(QTimerEvent *event) { + Q_UNUSED(event); ps_dispatch(); } void CSimulatorFsx::ps_dispatch() { SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this); - if (this->m_fsuipc) this->m_fsuipc->process(); + this->m_fsuipc->process(); } void CSimulatorFsx::ps_connectToFinished() { if (m_watcherConnect.result()) { - initEvents(); - initDataDefinitions(); + initWhenConnected(); m_simconnectTimerId = startTimer(50); m_simConnected = true; @@ -449,6 +502,28 @@ namespace BlackSimPlugin m_simConnectObjects.remove(simObject.getCallsign()); } + HRESULT CSimulatorFsx::initWhenConnected() + { + // called when connected + + HRESULT hr = initEvents(); + if (hr != S_OK) + { + CLogMessage(this).error("FSX plugin: initEvents failed"); + return hr; + } + + // inti data definitions and SB data area + hr += initDataDefinitionsWhenConnected(); + if (hr != S_OK) + { + CLogMessage(this).error("FSX plugin: initDataDefinitionsWhenConnected failed"); + return hr; + } + + return hr; + } + HRESULT CSimulatorFsx::initEvents() { HRESULT hr = S_OK; @@ -460,7 +535,8 @@ namespace BlackSimPlugin hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventPause, "Pause"); if (hr != S_OK) { - qFatal("SimConnect_SubscribeToSystemEvent failed"); + CLogMessage(this).error("FSX plugin: SimConnect_SubscribeToSystemEvent failed"); + return hr; } // Mapped events, see event ids here: http://msdn.microsoft.com/en-us/library/cc526980.aspx @@ -481,21 +557,23 @@ namespace BlackSimPlugin hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTimeZuluMinutes, "ZULU_MINUTES_SET"); if (hr != S_OK) { - qFatal("SimConnect_MapClientEventToSimEvent failed"); + CLogMessage(this).error("FSX plugin: SimConnect_MapClientEventToSimEvent failed"); + return hr; } // facility hr += SimConnect_SubscribeToFacilities(m_hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, m_nextObjID++); if (hr != S_OK) { - qFatal("SimConnect_SubscribeToFacilities failed"); + CLogMessage(this).error("FSX plugin: SimConnect_SubscribeToFacilities failed"); + return hr; } return hr; } - HRESULT CSimulatorFsx::initDataDefinitions() + HRESULT CSimulatorFsx::initDataDefinitionsWhenConnected() { - return CSimConnectDataDefinition::initDataDefinitions(m_hSimConnect); + return CSimConnectDefinitions::initDataDefinitionsWhenConnected(m_hSimConnect); } void CSimulatorFsx::updateOtherAircrafts() @@ -526,10 +604,10 @@ namespace BlackSimPlugin if (simObj.getObjectId() != 0) { - SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataRemoteAircraftSituation, simObj.getObjectId(), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(ddAircraftSituation), &ddAircraftSituation); + SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSituation, simObj.getObjectId(), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(ddAircraftSituation), &ddAircraftSituation); // With the following SimConnect call all aircrafts loose their red tag. No idea why though. - SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataGearHandlePosition, simObj.getObjectId(), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionGearHandlePosition), &gearHandle); + SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataGearHandlePosition, simObj.getObjectId(), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionGearHandlePosition), &gearHandle); } } } @@ -558,10 +636,10 @@ namespace BlackSimPlugin int simMins = zuluTimeSim.valueRounded(CTimeUnit::min()); int diffMins = qAbs(targetMins - simMins); if (diffMins < 2) return; + HRESULT hr = S_OK; hr += SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTimeZuluHours, h, SIMCONNECT_GROUP_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); hr += SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTimeZuluMinutes, m, SIMCONNECT_GROUP_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - if (hr != S_OK) { CLogMessage(this).warning("Sending time sync failed!"); diff --git a/src/plugins/simulator/fsx/simulator_fsx.h b/src/plugins/simulator/fsx/simulator_fsx.h index 23999cffd..71c6c140a 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.h +++ b/src/plugins/simulator/fsx/simulator_fsx.h @@ -52,6 +52,10 @@ namespace BlackSimPlugin //! Simulator info virtual BlackSim::CSimulatorInfo getSimulatorInfo() const override; + + //! Log message category + static QString getMessageCategory() { return "swift.fsx.plugin"; } + }; //! SimConnect Event IDs @@ -76,13 +80,14 @@ namespace BlackSimPlugin EventSetTimeZuluYear, EventSetTimeZuluDay, EventSetTimeZuluHours, - EventSetTimeZuluMinutes + EventSetTimeZuluMinutes, }; //! FSX Simulator Implementation class CSimulatorFsx : public BlackCore::ISimulator { Q_OBJECT + public: //! Constructor CSimulatorFsx(QObject *parent = nullptr); @@ -104,6 +109,9 @@ namespace BlackSimPlugin //! SimConnect Callback static void CALLBACK SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext); + //! Log message category + static QString getMessageCategory() { return "swift.fsx.plugin"; } + public slots: //! \copydoc ISimulator::connectTo() @@ -173,12 +181,15 @@ namespace BlackSimPlugin //! Called when data about our own aircraft are received void updateOwnAircraftFromSim(DataDefinitionOwnAircraft simulatorOwnAircraft); + //! Called when data about SB area received + void updateOwnAircraftFromSim(DataDefinitionClientAreaSb sbDataArea); + /*! * Set ID of a SimConnect object * \param requestID * \param objectID */ - void setSimconnectObjectID(DWORD requestID, DWORD objectID); + void setSimConnectObjectID(DWORD requestID, DWORD objectID); //! \private void onSimExit(); @@ -195,7 +206,7 @@ namespace BlackSimPlugin //! Dispatch SimConnect messages void ps_dispatch(); - //! Called when asynchronous connection to Simconnect has finished + //! Called when asynchronous connection to SimConnect has finished void ps_connectToFinished(); private: @@ -203,11 +214,14 @@ namespace BlackSimPlugin //! Remove a remote aircraft void removeRemoteAircraft(const CSimConnectObject &simObject); + //! Init SimConnect + HRESULT initWhenConnected(); + //! Initialize SimConnect system events HRESULT initEvents(); //! Initialize SimConnect data definitions - HRESULT initDataDefinitions(); + HRESULT initDataDefinitionsWhenConnected(); //! Update other aircrafts void updateOtherAircrafts(); @@ -216,14 +230,15 @@ namespace BlackSimPlugin void synchronizeTime(const BlackMisc::PhysicalQuantities::CTime &zuluTimeSim, const BlackMisc::PhysicalQuantities::CTime &localTimeSim); static const int SkipUpdateCyclesForCockpit = 10; //!< skip x cycles before updating cockpit again - bool m_simConnected = false; //!< Is simulator connected? - bool m_simRunning = false; //!< Simulator running? - bool m_simPaused = false; //!< Simulator paused? + bool m_simConnected = false; //!< Is simulator connected? + bool m_simRunning = false; //!< Simulator running? + bool m_simPaused = false; //!< Simulator paused? bool m_simTimeSynced = false; //!< Time synchronized? + bool m_useSbOffsets = true; //!< SB offsets int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time BlackMisc::PhysicalQuantities::CTime m_syncTimeOffset; - HANDLE m_hSimConnect; //!< Handle to SimConnect object - uint m_nextObjID; //!< object ID TODO: also used as request id, where to we place other request ids as for facilities + HANDLE m_hSimConnect = nullptr; //!< Handle to SimConnect object + uint m_nextObjID = 1; //!< object ID TODO: also used as request id, where to we place other request ids as for facilities QString simulatorDetails; BlackSim::CSimulatorInfo m_simulatorInfo; BlackMisc::Aviation::CAircraft m_ownAircraft; //!< Object representing our own aircraft from simulator @@ -231,13 +246,12 @@ namespace BlackSimPlugin BlackMisc::Network::CAircraftModel m_aircraftModel; BlackMisc::Aviation::CAirportList m_airportsInRange; - int m_simconnectTimerId; - int m_skipCockpitUpdateCycles; //!< Skip some update cycles to allow changes in simulator cockpit to be set + int m_simconnectTimerId = -1; + int m_skipCockpitUpdateCycles = 0; //!< Skip some update cycles to allow changes in simulator cockpit to be set QFutureWatcher m_watcherConnect; QScopedPointer m_fsuipc; }; - } - -} // namespace BlackCore + } // namespace +} // namespace #endif // guard diff --git a/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp b/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp index 39a74fe71..71b57679e 100644 --- a/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx_simconnectproc.cpp @@ -42,7 +42,7 @@ namespace BlackSimPlugin .arg(event->szApplicationName) .arg(event->dwApplicationVersionMajor).arg(event->dwApplicationVersionMinor).arg(event->dwApplicationBuildMajor).arg(event->dwApplicationBuildMinor) .arg(event->dwSimConnectVersionMajor).arg(event->dwSimConnectVersionMinor).arg(event->dwSimConnectBuildMajor).arg(event->dwSimConnectBuildMinor); - CLogMessage(static_cast(nullptr)).info(CProject::systemNameAndVersion()); + CLogMessage(static_cast(nullptr)).info("Connect to FSX: %1") << CProject::systemNameAndVersion(); break; } case SIMCONNECT_RECV_ID_EXCEPTION: @@ -52,7 +52,7 @@ namespace BlackSimPlugin ex.sprintf("Exception=%d SendID=%d Index=%d cbData=%d", static_cast(exception->dwException), static_cast(exception->dwSendID), static_cast(exception->dwIndex), static_cast(cbData)); - CLogMessage(static_cast(nullptr)).error("Caught simConnect exception: %1 %2") + CLogMessage(static_cast(nullptr)).error("Caught FSX simConnect exception: %1 %2") << CSimConnectUtilities::simConnectExceptionToString((SIMCONNECT_EXCEPTION)exception->dwException) << ex; break; @@ -93,9 +93,11 @@ namespace BlackSimPlugin SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE *event = static_cast(pData); if (event->uEventID == SystemEventObjectAdded) { + // } else if (event->uEventID == SystemEventObjectRemoved) { + // } break; } @@ -115,7 +117,7 @@ namespace BlackSimPlugin case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID: { SIMCONNECT_RECV_ASSIGNED_OBJECT_ID *event = static_cast(pData); - simulatorFsx->setSimconnectObjectID(event->dwRequestID, event->dwObjectID); + simulatorFsx->setSimConnectObjectID(event->dwRequestID, event->dwObjectID); break; } case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: @@ -123,14 +125,14 @@ namespace BlackSimPlugin SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA *) pData; switch (pObjData->dwRequestID) { - case CSimConnectDataDefinition::RequestOwnAircraft: + case CSimConnectDefinitions::RequestOwnAircraft: { DataDefinitionOwnAircraft *ownAircaft; ownAircaft = (DataDefinitionOwnAircraft *)&pObjData->dwData; simulatorFsx->updateOwnAircraftFromSim(*ownAircaft); break; } - case CSimConnectDataDefinition::RequestOwnAircraftTitle: + case CSimConnectDefinitions::RequestOwnAircraftTitle: { DataDefinitionOwnAircraftModel *dataDefinitionModel = (DataDefinitionOwnAircraftModel *) &pObjData->dwData; CAircraftModel model; @@ -138,7 +140,7 @@ namespace BlackSimPlugin simulatorFsx->setAircraftModel(model); break; } - case CSimConnectDataDefinition::RequestSimEnvironment: + case CSimConnectDefinitions::RequestSimEnvironment: { DataDefinitionSimEnvironment *simEnv = (DataDefinitionSimEnvironment *) &pObjData->dwData; qint32 zh = simEnv->zuluTimeSeconds / 3600; @@ -179,12 +181,24 @@ namespace BlackSimPlugin } break; } + case SIMCONNECT_RECV_ID_CLIENT_DATA: + { + if (!simulatorFsx->m_useSbOffsets) { break; } + SIMCONNECT_RECV_CLIENT_DATA *clientData = (SIMCONNECT_RECV_CLIENT_DATA *)pData; + if (simulatorFsx->m_useSbOffsets && clientData->dwRequestID == CSimConnectDefinitions::RequestSbData) + { + //! \todo why is offset 19 ident 2/0 ? + //! In FSUIPC it is 0/1, according to documentation it is 0/1 but I receive 2/0 here + DataDefinitionClientAreaSb *sbData = (DataDefinitionClientAreaSb *) &clientData->dwData; + simulatorFsx->updateOwnAircraftFromSim(*sbData); + } + break; + } default: break; + } // main switch } // method } // namespace } // namespace - } -}