From 05ec07edf3279a52380267e0d719640eef63697c Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sun, 5 Nov 2017 01:50:15 +0100 Subject: [PATCH] Ref T180, allow to trace send ids (Rational: hope to get more details about exceptions of FSX) * trace functions * command line parsing to set tracing on/off --- .../fsxcommon/simulatorfsxcommon.cpp | 75 +++++++++++++++++-- .../simulator/fsxcommon/simulatorfsxcommon.h | 39 +++++++++- .../fsxcommon/simulatorfsxsimconnectproc.cpp | 4 +- 3 files changed, 108 insertions(+), 10 deletions(-) diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp index 493973433..7b5a35e5c 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp @@ -51,11 +51,13 @@ namespace BlackSimPlugin Q_ASSERT_X(ownAircraftProvider, Q_FUNC_INFO, "Missing provider"); Q_ASSERT_X(remoteAircraftProvider, Q_FUNC_INFO, "Missing provider"); Q_ASSERT_X(sApp, Q_FUNC_INFO, "Missing global object"); - m_addPendingAircraftTimer.setInterval(AddPendingAircraftIntervalMs); - connect(&m_addPendingAircraftTimer, &QTimer::timeout, this, &CSimulatorFsxCommon::addPendingAircraftByTimer); + m_addPendingAircraftTimer.setInterval(AddPendingAircraftIntervalMs); m_useFsuipc = false; // default model will be set in derived class + + CSimulatorFsxCommon::registerHelp(); + connect(&m_addPendingAircraftTimer, &QTimer::timeout, this, &CSimulatorFsxCommon::addPendingAircraftByTimer); } CSimulatorFsxCommon::~CSimulatorFsxCommon() @@ -731,6 +733,25 @@ namespace BlackSimPlugin this->dispatch(); } + bool CSimulatorFsxCommon::parseDetails(const CSimpleCommandParser &parser) + { + // .driver sendid on|off + if (parser.matchesPart(1, "sendid") && parser.hasPart(2)) + { + const bool trace = parser.toBool(2); + this->setTraceSendId(trace); + return true; + } + return CSimulatorFsCommon::parseDetails(parser); + } + + void CSimulatorFsxCommon::registerHelp() + { + if (CSimpleCommandParser::registered("BlackSimPlugin::CSimulatorFsxCommon::CSimulatorFsxCommon")) { return; } + CSimpleCommandParser::registerCommand({".drv", "alias: .driver .plugin"}); + CSimpleCommandParser::registerCommand({".drv sendid on|off", "Trace simConnect sendId on|off"}); + } + const QString &CSimulatorFsxCommon::modeToString(CSimulatorFsxCommon::AircraftAddMode mode) { static const QString e("external call"); @@ -838,7 +859,6 @@ namespace BlackSimPlugin // create AI bool adding = false; - const CAircraftModel aircraftModel = newRemoteAircraft.getModel(); CSimulatedAircraft addedAircraft(newRemoteAircraft); const DWORD requestId = this->obtainRequestIdForSimData(); @@ -849,7 +869,7 @@ namespace BlackSimPlugin const HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, static_cast(requestId)); if (hr != S_OK) { - const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create AI traffic: '%1' '%2'") << callsign.toQString() << aircraftModel.getModelString(); + const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create AI traffic: '%1' '%2'") << callsign.toQString() << modelString; CLogMessage::preformatted(msg); emit this->physicallyAddingRemoteModelFailed(addedAircraft, msg); } @@ -860,6 +880,7 @@ namespace BlackSimPlugin addedAircraft.setRendered(false); const CSimConnectObject simObject(addedAircraft, requestId, &m_interpolationLogger); m_simConnectObjects.insert(callsign, simObject); + if (m_traceSendId) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);} adding = true; } return adding; @@ -1070,11 +1091,15 @@ namespace BlackSimPlugin SIMCONNECT_DATA_INITPOSITION position = this->aircraftSituationToFsxPosition(interpolatedSituation); HRESULT hr = S_OK; hr += SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftPosition, - static_cast(simObj.getObjectId()), 0, 0, + static_cast(simObject.getObjectId()), 0, 0, sizeof(SIMCONNECT_DATA_INITPOSITION), &position); - if (hr != S_OK) + if (hr == S_OK) { - CLogMessage(this).warning("Failed so set position on SimObject '%1' callsign: '%2'") << simObj.getObjectId() << callsign; + if (m_traceSendId) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);} + } + else + { + CLogMessage(this).warning("Failed so set position on SimObject '%1' callsign: '%2'") << simObject.getObjectId() << callsign; } } // interpolation data @@ -1211,6 +1236,8 @@ namespace BlackSimPlugin if (hr == S_OK && m_simConnectObjects.contains(simObject.getCallsign())) { + if (m_traceSendId) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);} + // Update data CSimConnectObject &objUdpate = m_simConnectObjects[simObject.getCallsign()]; objUdpate.setPartsAsSent(ddRemoteAircraftPartsWithoutLights); @@ -1379,6 +1406,7 @@ namespace BlackSimPlugin if (result == S_OK && m_simConnectObjects.contains(simObject.getCallsign())) { + if (m_traceSendId) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);} m_simConnectObjects[simObject.getCallsign()].setSimDataPeriod(period); return true; } @@ -1395,7 +1423,11 @@ namespace BlackSimPlugin m_hSimConnect, simObject.getRequestId() + RequestLightsOffset, CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(), SIMCONNECT_PERIOD_SECOND); - if (result == S_OK) { return true; } + if (result == S_OK) + { + if (m_traceSendId) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);} + return true; + } CLogMessage(this).error("Cannot request lights data on object '%1'") << simObject.getObjectId(); return false; } @@ -1425,6 +1457,7 @@ namespace BlackSimPlugin m_requestIdSimData = RequestSimDataStart; m_dispatchErrors = 0; m_receiveExceptionCount = 0; + m_sendIdTraces.clear(); CSimulatorFsCommon::reset(); // clears all pending aircraft etc } @@ -1462,6 +1495,32 @@ namespace BlackSimPlugin return simObjectCallsigns.difference(providerCallsigns); } + void CSimulatorFsxCommon::traceSendId(DWORD simObjectId, const QString &comment) + { + if (!m_traceSendId) { return; } + if (MaxSendIdTraces < 1) { return; } + DWORD dwLastId = -1; + const HRESULT hr = SimConnect_GetLastSentPacketID(m_hSimConnect, &dwLastId); + if (hr != S_OK || dwLastId < 0) { return; } + if (m_sendIdTraces.size() > MaxSendIdTraces) { m_sendIdTraces.removeFirst(); } + const TraceFsxSendId t(dwLastId, simObjectId, comment); + m_sendIdTraces.push_back(t); + } + + QString CSimulatorFsxCommon::getSendIdTraceDetails(DWORD sendId) const + { + for (const TraceFsxSendId &t : m_sendIdTraces) + { + if (t.sendId == sendId) + { + static const QString d("Send id: %1 obj.id.: %2 cs.: %4 '%3'"); + const CCallsign cs = m_simConnectObjects.getCallsignForObjectId(t.simObjectId); + return d.arg(sendId).arg(t.simObjectId).arg(cs.asString(), t.comment); + } + } + return ""; + } + CCallsignSet CSimulatorFsxCommon::physicallyRemoveAircraftNotInProvider() { const CCallsignSet toBeRemoved(getCallsignsMissingInProvider()); diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h index f8067bde0..6b24d73ea 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace BlackSimPlugin @@ -81,6 +82,19 @@ namespace BlackSimPlugin EventToggleWingLights }; + //! Struct to trace send ids + struct TraceFsxSendId + { + //! Ctor + TraceFsxSendId(DWORD sendId, DWORD simObjectId, const QString &comment) : + sendId(sendId), simObjectId(simObjectId), comment(comment) + { } + + DWORD sendId = -1; //!< the send id + DWORD simObjectId = -1; //!< corresponding CSimConnectObject + QString comment; //!< where sent + }; + //! FSX Simulator Implementation class CSimulatorFsxCommon : public BlackSimPlugin::FsCommon::CSimulatorFsCommon { @@ -143,6 +157,17 @@ namespace BlackSimPlugin //! \sa CSimulatorFsxCommon::dispatch virtual void timerEvent(QTimerEvent *event) override; + //! \addtogroup swiftdotcommands + //! @{ + //!
+            //! .drv sendid  on|off      tracing simCOnnect sendId on/off
+            //! 
+ //! @} + virtual bool parseDetails(const BlackMisc::CSimpleCommandParser &parser) override; + + //! Register help + static void registerHelp(); + private: //! Reason for adding an aircraft enum AircraftAddMode @@ -204,7 +229,7 @@ namespace BlackSimPlugin void onSimExit(); //! Get new request id, overflow safe - DWORD obtainRequestIdSimData(); + DWORD obtainRequestIdForSimData(); //! Init when connected HRESULT initWhenConnected(); @@ -283,6 +308,15 @@ namespace BlackSimPlugin //! Get the callsigns which are no longer in the provider, but still in m_simConnectObjects BlackMisc::Aviation::CCallsignSet getCallsignsMissingInProvider() const; + //! Set tracing on/off + void setTraceSendId(bool traceSendId) { m_traceSendId = traceSendId; } + + //! Trace the send id + void traceSendId(DWORD simObjectId, const QString &comment); + + //! Get the trace details, otherwise empty string + QString getSendIdTraceDetails(DWORD sendId) const; + //! Request for sim data (request in range of sim data)? static bool isRequestForSimData(DWORD requestId) { return requestId >= (RequestSimDataStart + RequestSimDataOffset) && requestId < (RequestSimDataStart + RequestSimDataOffset + MaxSimObjects); } @@ -293,6 +327,7 @@ namespace BlackSimPlugin static constexpr int SkipUpdateCyclesForCockpit = 10; //!< skip x cycles before updating cockpit again static constexpr int IgnoreReceiveExceptions = 10; //!< skip exceptions when displayed more than x times static constexpr int MaxSimObjects = 10000; //!< max.number of SimObjects at the same time + static constexpr int MaxSendIdTraces = 10000; //!< max.traces of send id static constexpr int RequestSimDataStart = static_cast(CSimConnectDefinitions::RequestEndMarker); static constexpr int RequestSimDataEnd = RequestSimDataStart + MaxSimObjects - 1; static constexpr int RequestSimDataOffset = 0 * MaxSimObjects; @@ -306,6 +341,7 @@ namespace BlackSimPlugin bool m_simConnected = false; //!< Is simulator connected? bool m_simSimulating = false; //!< Simulator running? bool m_useSbOffsets = true; //!< with SB offsets + bool m_traceSendId = false; //!< trace the send ids, meant for dedugging qint64 m_simulatingChangedTs = -1; //!< timestamp, when simulating changed (used to avoid jitter) int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time int m_simConnectTimerId = -1; //!< Timer identifier @@ -315,6 +351,7 @@ namespace BlackSimPlugin int m_receiveExceptionCount = 0; //!< exceptions HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object CSimConnectObjects m_simConnectObjects; //!< AI objects and their object / request ids + QList m_sendIdTraces; //!< Send id traces for debugging QTimer m_addPendingAircraftTimer { this }; //!< updating of aircraft awaiting add DWORD m_requestIdSimData = RequestSimDataStart; //!< request id, use obtainRequestId() to get id BlackMisc::Simulation::CSimulatedAircraftList m_addPendingAircraft; //!< aircraft awaiting to be added diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp index c7fc7eae7..4312a6f31 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp @@ -65,7 +65,9 @@ namespace BlackSimPlugin ex.sprintf("Exception=%lu | SendID=%lu | Index=%lu | cbData=%lu", exceptionId, sendId, index, data); const QString exceptionString(CSimConnectUtilities::simConnectExceptionToString((SIMCONNECT_EXCEPTION)exception->dwException)); const QString sendIdDetails = simulatorFsx->getSendIdTraceDetails(sendId); - CLogMessage(simulatorFsx).warning("Caught simConnect exception: '%1' '%2' '%3'") << exceptionString << ex << sendIdDetails; + CLogMessage(simulatorFsx).warning("Caught simConnect exception: '%1' '%2' | send details: '%3'") + << exceptionString << ex + << (sendIdDetails.isEmpty() ? "N/A" : sendIdDetails); break; } case SIMCONNECT_RECV_ID_QUIT: