8 #include <QElapsedTimer>
10 #include <QStringBuilder>
13 #include "../fscommon/simulatorfscommonfunctions.h"
36 using namespace swift::config;
38 using namespace swift::misc::aviation;
39 using namespace swift::misc::physical_quantities;
40 using namespace swift::misc::geo;
41 using namespace swift::misc::network;
42 using namespace swift::misc::math;
43 using namespace swift::misc::simulation;
44 using namespace swift::misc::simulation::fscommon;
45 using namespace swift::misc::simulation::fsx;
46 using namespace swift::misc::simulation::settings;
48 using namespace swift::simplugin::fscommon;
50 namespace swift::simplugin::fsxcommon
56 :
CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, clientProvider, parent)
58 Q_ASSERT_X(ownAircraftProvider, Q_FUNC_INFO,
"Missing provider");
59 Q_ASSERT_X(remoteAircraftProvider, Q_FUNC_INFO,
"Missing provider");
60 Q_ASSERT_X(
sApp, Q_FUNC_INFO,
"Missing global object");
62 m_simObjectTimer.
setInterval(AddPendingAircraftIntervalMs);
92 this->initDataDefinitionsWhenConnected();
101 if (!m_simConnected) {
return true; }
102 m_simSimulating =
false;
103 m_traceAutoUntilTs = -1;
104 m_traceSendId =
false;
111 m_simConnected =
false;
115 return CSimulatorFsCommon::disconnectFrom();
121 return this->physicallyAddRemoteAircraftImpl(newRemoteAircraft, ExternalCall);
124 bool CSimulatorFsxCommon::updateCOMFromSwiftToSimulator(
const CFrequency &newFreq,
const CFrequency &lastSimFreq,
127 if (newFreq == lastSimFreq) {
return false; }
129 if (CComSystem::isExclusiveWithin8_33kHzChannel(newFreq) && last25kHzSimFreq.
isNull())
133 last25kHzSimFreq = lastSimFreq;
137 if (CComSystem::isWithin25kHzChannel(newFreq))
141 SimConnect_TransmitClientEvent(
m_hSimConnect, 0,
id, CBcdConversions::comFrequencyToBcdHz(newFreq),
142 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
143 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
154 if (originator == this->
identifier()) {
return false; }
162 bool changed =
false;
165 m_lastCom1Active, EventSetCom1Active);
167 m_lastCom1Standby, EventSetCom1Standby);
169 m_lastCom2Active, EventSetCom2Active);
171 m_lastCom2Standby, EventSetCom2Standby);
178 byte standby = newTransponder.
isInStandby() ? 1U : 0U;
181 hr += SimConnect_SetClientData(
m_hSimConnect, ClientAreaSquawkBox,
183 SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT, 0, 1, &ident);
184 hr += SimConnect_SetClientData(
m_hSimConnect, ClientAreaSquawkBox,
186 SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT, 0, 1, &standby);
211 hr += SimConnect_SetDataOnSimObject(
m_hSimConnect, CSimConnectDefinitions::DataTransponderModeMSFS,
212 SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0,
230 if (originator == this->
identifier()) {
return false; }
244 SIMCONNECT_TEXT_TYPE type = SIMCONNECT_TEXT_TYPE_PRINT_BLACK;
247 case CStatusMessage::SeverityDebug:
return;
248 case CStatusMessage::SeverityInfo: type = SIMCONNECT_TEXT_TYPE_PRINT_GREEN;
break;
249 case CStatusMessage::SeverityWarning: type = SIMCONNECT_TEXT_TYPE_PRINT_YELLOW;
break;
250 case CStatusMessage::SeverityError: type = SIMCONNECT_TEXT_TYPE_PRINT_RED;
break;
262 SIMCONNECT_TEXT_TYPE type = SIMCONNECT_TEXT_TYPE_PRINT_BLACK;
264 else if (message.
isPrivateMessage()) { type = SIMCONNECT_TEXT_TYPE_PRINT_YELLOW; }
265 else if (message.
isRadioMessage()) { type = SIMCONNECT_TEXT_TYPE_PRINT_GREEN; }
283 m_addPendingAircraft.
keys());
290 if (!CBuildConfig::isLocalDeveloperDebugBuild()) {
return msgs; }
291 msgs = CSimulatorFsCommon::debugVerifyStateAfterAllAircraftRemoved();
297 if (!m_simConnectObjectsPositionAndPartsTraces.
isEmpty())
312 static const QString specificInfo(
313 "dispatch #: %1 %2 times (cur/max): %3ms (%4ms) %5ms (%6ms) %7 %8 simData#: %9");
314 return specificInfo.
arg(m_dispatchProcCount)
315 .
arg(m_dispatchProcEmptyCount)
316 .
arg(m_dispatchTimeMs)
317 .
arg(m_dispatchProcTimeMs)
318 .
arg(m_dispatchMaxTimeMs)
319 .
arg(m_dispatchProcMaxTimeMs)
320 .
arg(CSimConnectUtilities::simConnectReceiveIdToString(
static_cast<DWORD>(m_dispatchReceiveIdMaxTime)),
321 requestIdToString(m_dispatchRequestIdMaxTime))
322 .
arg(m_requestSimObjectDataCount);
331 if (reference.
isNull()) {
return false; }
342 simObject.
getObjectId(), 0, 0,
sizeof(SIMCONNECT_DATA_INITPOSITION),
344 simObject,
"Cannot request AI elevation", Q_FUNC_INFO,
"SimConnect_SetDataOnSimObject");
348 const bool ok = this->requestTerrainProbeData(simObject, aircraftCallsign);
355 if (m_traceSendId) {
return true; }
356 if (m_traceAutoUntilTs < 0) {
return false; }
358 const bool trace = ts <= m_traceAutoUntilTs;
364 m_traceSendId = trace;
365 m_traceAutoUntilTs = -1;
370 m_useAddSimulatedObj = enabled;
379 m_useSbOffsets = enabled;
388 m_dispatchProcCount = 0;
389 m_dispatchProcEmptyCount = 0;
390 m_dispatchMaxTimeMs = -1;
391 m_dispatchProcMaxTimeMs = -1;
392 m_dispatchTimeMs = -1;
393 m_dispatchProcTimeMs = -1;
394 m_requestSimObjectDataCount = 0;
395 m_dispatchReceiveIdLast = SIMCONNECT_RECV_ID_NULL;
396 m_dispatchReceiveIdMaxTime = SIMCONNECT_RECV_ID_NULL;
399 CSimulatorPluginCommon::resetAircraftStatistics();
412 byte sbNetworkConnected = connected ? 1u : 0u;
413 const HRESULT hr = SimConnect_SetClientData(
m_hSimConnect, ClientAreaSquawkBox,
415 SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT, 0, 1, &sbNetworkConnected);
418 ISimulator::setFlightNetworkConnected(connected);
437 this->sendRemoteAircraftPartsToSimulator(simObject, parts);
446 static_cast<SIMCONNECT_OBJECT_ID
>(simObject.
getObjectId()), 0, 0,
447 sizeof(SIMCONNECT_DATA_INITPOSITION), &position),
448 traceSendId, simObject,
"Failed to set position", Q_FUNC_INFO,
"SimConnect_SetDataOnSimObject");
449 if (hr == S_OK) { u++; }
460 v = (requestId - RequestSimObjTerrainProbeStart) / MaxSimObjProbes;
466 bool CSimulatorFsxCommon::stillDisplayReceiveExceptions()
468 m_receiveExceptionCount++;
469 return m_receiveExceptionCount < IgnoreReceiveExceptions;
472 CSimConnectObject CSimulatorFsxCommon::getSimObjectForObjectId(
DWORD objectId)
const
477 void CSimulatorFsxCommon::setSimConnected()
479 m_simConnected =
true;
487 if (!myself) {
return; }
488 myself->initSimulatorInternals();
492 void CSimulatorFsxCommon::onSimRunning()
496 if (!myself) {
return; }
498 this->onSimRunningDeferred(m_simulatingChangedTs);
502 void CSimulatorFsxCommon::onSimRunningDeferred(qint64 referenceTs)
504 if (m_simSimulating) {
return; }
505 if (referenceTs != m_simulatingChangedTs) {
return; }
506 m_simSimulating =
true;
507 m_simConnected =
true;
515 m_useSbOffsets =
false;
520 SimConnect_RequestDataOnSimObject(
m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraft,
521 CSimConnectDefinitions::DataOwnAircraft, SIMCONNECT_OBJECT_ID_USER,
522 SIMCONNECT_PERIOD_VISUAL_FRAME),
523 "Cannot request own aircraft data", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
526 SimConnect_RequestDataOnSimObject(
m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraftTitle,
527 CSimConnectDefinitions::DataOwnAircraftTitle, SIMCONNECT_OBJECT_ID_USER,
528 SIMCONNECT_PERIOD_SECOND, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED),
529 "Cannot request title", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
541 SIMCONNECT_CLIENT_DATA_PERIOD_SECOND,
542 SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED),
543 "Cannot request client data", Q_FUNC_INFO,
"SimConnect_RequestClientData");
549 CSimConnectDefinitions::DataTransponderModeMSFS,
550 SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME,
551 SIMCONNECT_DATA_REQUEST_FLAG_CHANGED),
552 "Cannot request MSFS transponder data", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
559 void CSimulatorFsxCommon::onSimStopped()
564 m_simSimulating =
false;
569 void CSimulatorFsxCommon::onSimFrame()
575 if (!myself) {
return; }
576 myself->updateRemoteAircraft();
580 void CSimulatorFsxCommon::onSimExit()
591 if (!myself) {
return; }
598 const SIMCONNECT_DATA_REQUEST_ID
id = m_requestIdSimObjAircraft++;
599 if (
id > RequestSimObjAircraftEnd) { m_requestIdSimObjAircraft = RequestSimObjAircraftStart; }
605 const SIMCONNECT_DATA_REQUEST_ID
id = m_requestIdSimObjTerrainProbe++;
606 if (
id > RequestSimObjTerrainProbeEnd) { m_requestIdSimObjTerrainProbe = RequestSimObjTerrainProbeStart; }
612 const SIMCONNECT_OBJECT_ID objectId = simObject.
getObjectId();
615 "Release control", Q_FUNC_INFO,
"SimConnect_AIReleaseControl");
618 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
619 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
620 simObject,
"EventFreezeLatLng", Q_FUNC_INFO,
"SimConnect_TransmitClientEvent");
623 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
624 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
625 simObject,
"EventFreezeAlt", Q_FUNC_INFO,
"SimConnect_TransmitClientEvent");
628 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
629 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
630 simObject,
"EventFreezeAtt", Q_FUNC_INFO,
"SimConnect_TransmitClientEvent");
632 return isOk(hr1, hr2, hr3, hr4);
667 if (m_traceSendId) {
return false; }
670 const qint64 traceUntil = traceTimeMs + ts;
671 if (traceUntil <= m_traceAutoUntilTs) {
return false; }
672 m_traceAutoUntilTs = traceUntil;
674 static const QString format(
"hh:mm:ss.zzz");
676 CLogMessage(
this).
info(u
"Triggered FSX/P3D auto trace until %1") << untilString;
680 if (!myself) {
return; }
682 if (m_traceAutoUntilTs < 0) {
return; }
684 m_traceAutoUntilTs = -1;
705 if (simulatorOwnAircraft.
pitchDeg < -90.0 || simulatorOwnAircraft.
pitchDeg >= 90.0)
720 CAircraftSituation::FromProvider);
723 CAltitude::PressureAltitude, CLengthUnit::m()));
727 {
dtb(simulatorOwnAircraft.
simOnGround) ? COnGroundInfo::OnGround : COnGroundInfo::NotOnGround,
728 COnGroundInfo::OutOnGroundOwnAircraft });
749 for (
int index = 0; index < simulatorOwnAircraft.
numberOfEngines; ++index)
754 const double factor = 30.0;
755 double engineRpm = (powerList.value(index, 0) - factor) * 100 / (100 - factor);
756 if (engineRpm < 0) engineRpm = 0;
786 const bool com1Test =
dtb(simulatorOwnAircraft.
comTest1);
788 const int com1Status =
791 com1.setTransmitEnabled(com1Status == 0 && com1Transmit);
792 com1.setReceiveEnabled(com1Status == 0 && (comReceiveAll || com1Transmit));
794 const bool changedCom1Active =
795 myAircraft.getCom1System().getFrequencyActive() != com1.getFrequencyActive() &&
796 com1.getFrequencyActive() != m_lastCom1Active;
797 const bool changedCom1Standby =
798 myAircraft.getCom1System().getFrequencyStandby() != com1.getFrequencyStandby() &&
799 com1.getFrequencyStandby() != m_lastCom1Standby;
802 if (!changedCom1Active) { com1.setFrequencyActive(myAircraft.getCom1System().getFrequencyActive()); }
803 else { m_lastCom1Active.
setNull(); }
805 if (!changedCom1Standby) { com1.setFrequencyStandby(myAircraft.getCom1System().getFrequencyStandby()); }
806 else { m_lastCom1Standby.
setNull(); }
808 const bool changedCom1 = myAircraft.getCom1System() != com1;
815 const bool com2Test =
dtb(simulatorOwnAircraft.
comTest2);
817 const int com2Status =
820 com2.setTransmitEnabled(com2Status == 0 && com2Transmit);
821 com2.setReceiveEnabled(com2Status == 0 && (comReceiveAll || com2Transmit));
822 const bool changedCom2Active =
823 myAircraft.getCom2System().getFrequencyActive() != com2.getFrequencyActive() &&
824 com2.getFrequencyActive() != m_lastCom2Active;
825 const bool changedCom2Standby =
826 myAircraft.getCom2System().getFrequencyStandby() != com2.getFrequencyStandby() &&
827 com2.getFrequencyStandby() != m_lastCom2Standby;
830 if (!changedCom2Active) { com2.setFrequencyActive(myAircraft.getCom2System().getFrequencyActive()); }
831 else { m_lastCom2Active.
setNull(); }
833 if (!changedCom2Standby) { com2.setFrequencyStandby(myAircraft.getCom2System().getFrequencyStandby()); }
834 else { m_lastCom2Standby.
setNull(); }
836 const bool changedCom2 = myAircraft.getCom2System() != com2;
842 transponder.setTransponderCode(qRound(simulatorOwnAircraft.
transponderCode));
848 const bool changedXpr = (myAircraft.getTransponderCode() != transponder.getTransponderCode());
850 if (changedCom1 || changedCom2 || changedXpr)
864 this->physicallyInitAITerrainProbes(position, 2);
871 QStringLiteral(
"disabled"));
886 void CSimulatorFsxCommon::triggerUpdateRemoteAircraftFromSimulator(
const CSimConnectObject &simObject,
887 const DataDefinitionPosData &remoteAircraftData)
892 if (!myself) {
return; }
893 myself->updateRemoteAircraftFromSimulator(simObject, remoteAircraftData);
897 void CSimulatorFsxCommon::triggerUpdateRemoteAircraftFromSimulator(
898 const CSimConnectObject &simObject,
const DataDefinitionRemoteAircraftModel &remoteAircraftModel)
903 if (!myself) {
return; }
904 myself->updateRemoteAircraftFromSimulator(simObject, remoteAircraftModel);
908 void CSimulatorFsxCommon::updateRemoteAircraftFromSimulator(
const CSimConnectObject &simObject,
909 const DataDefinitionPosData &remoteAircraftData)
914 const CCallsign cs(simObject.getCallsign());
916 const bool moving = lastSituation.
isMoving();
917 const bool onGround = remoteAircraftData.isOnGround();
922 CElevationPlane(remoteAircraftData.latitudeDeg, remoteAircraftData.longitudeDeg,
923 remoteAircraftData.elevationFt, CElevationPlane::singlePointRadius());
924 if (remoteAircraftData.aboveGroundFt() < 250)
926 const CLength cg(remoteAircraftData.cgToGroundFt, CLengthUnit::ft());
934 const CAltitude alt(remoteAircraftData.altitudeFt, CAltitude::MeanSeaLevel, CAltitude::TrueAltitude,
942 if (moving && remoteAircraftData.aboveGroundFt() <= 100.0)
945 if (simObject.getSimDataPeriod() != SIMCONNECT_PERIOD_VISUAL_FRAME)
947 this->requestPositionDataForSimObject(simObject, SIMCONNECT_PERIOD_VISUAL_FRAME);
953 if (simObject.getSimDataPeriod() != SIMCONNECT_PERIOD_SECOND)
955 this->requestPositionDataForSimObject(simObject, SIMCONNECT_PERIOD_SECOND);
961 CSimulatorFsxCommon::updateRemoteAircraftFromSimulator(
const CSimConnectObject &simObject,
962 const DataDefinitionRemoteAircraftModel &remoteAircraftModel)
964 const CCallsign cs(simObject.getCallsign());
967 if (so.isPendingRemoved()) {
return; }
969 const QString modelString(remoteAircraftModel.title);
970 const CLength cg(remoteAircraftModel.cgToGroundFt, CLengthUnit::ft());
971 so.setAircraftCG(cg);
972 so.setAircraftModelString(modelString);
980 void CSimulatorFsxCommon::updateProbeFromSimulator(
const CCallsign &callsign,
981 const DataDefinitionPosData &remoteAircraftData)
983 const CElevationPlane elevation(remoteAircraftData.latitudeDeg, remoteAircraftData.longitudeDeg,
984 remoteAircraftData.elevationFt, CElevationPlane::singlePointRadius());
988 void CSimulatorFsxCommon::updateOwnAircraftFromSimulator(
const DataDefinitionClientAreaSb &sbDataArea)
993 if (m_logSbOffsets) {
CLogMessage(
this).
info(u
"SB from sim: " % sbDataArea.toQString()); }
997 if (!sbDataArea.isIdent())
999 newMode = sbDataArea.isStandby() ? CTransponder::StateStandby : CTransponder::ModeC;
1002 const bool changed = (myAircraft.getTransponderMode() != newMode);
1003 if (!changed) {
return; }
1006 this->
updateCockpit(myAircraft.getCom1System(), myAircraft.getCom2System(), xpdr, this->identifier());
1013 const bool changed = (myAircraft.getTransponderMode() != xpdrMode);
1014 if (!changed) {
return; }
1017 this->
updateCockpit(myAircraft.getCom1System(), myAircraft.getCom2System(), myXpdr, this->identifier());
1020 void CSimulatorFsxCommon::updateMSFSTransponderMode(
const DataDefinitionMSFSTransponderMode transponderMode)
1022 auto mode = CTransponder::StateIdent;
1023 if (!transponderMode.ident)
1025 qRound(transponderMode.transponderMode) >= 3 ? mode = CTransponder::ModeC :
1026 mode = CTransponder::StateStandby;
1028 this->updateTransponderMode(mode);
1031 bool CSimulatorFsxCommon::simulatorReportedObjectAdded(
DWORD objectId)
1035 const CCallsign callsign(simObject.getCallsign());
1036 if (!simObject.hasValidRequestAndObjectId() || callsign.isEmpty()) {
return false; }
1045 this->verifyAddedRemoteAircraft(verifyAircraft);
1050 void CSimulatorFsxCommon::verifyAddedRemoteAircraft(
const CSimulatedAircraft &remoteAircraftIn)
1055 this->verifyAddedTerrainProbe(remoteAircraftIn);
1065 if (callsign.isEmpty())
1067 msg =
CLogMessage(
this).
error(u
"Cannot confirm AI object, empty callsign");
1075 if (aircraftStillInRange)
1078 u
"Callsign '%1' removed in meantime from AI objects, but still in range")
1079 << callsign.toQString();
1083 this->removeFromAddPendingAndAddAgainAircraft(callsign);
1084 msg =
CLogMessage(
this).
info(u
"Callsign '%1' removed in meantime and no longer in range")
1085 << callsign.toQString();
1091 remoteAircraft = simObject.getAircraft();
1093 if (!simObject.hasValidRequestAndObjectId() || simObject.isPendingRemoved())
1096 << callsign.
toQString() << simObject.getObjectId();
1112 Q_ASSERT_X(simObject.isPendingAdded(), Q_FUNC_INFO,
"Already confirmed, this should be the only place");
1113 simObject.setConfirmedAdded(
true);
1116 this->requestPositionDataForSimObject(simObject);
1117 this->requestLightsForSimObject(simObject);
1118 this->requestModelInfoForSimObject(simObject);
1120 this->removeFromAddPendingAndAddAgainAircraft(callsign);
1124 static const QString debugMsg(
"CS: '%1' model: '%2' verified, request/object id: %3 %4");
1128 debugMsg.arg(callsign.toQString(), remoteAircraft.
getModelString())
1129 .arg(simObject.getRequestId())
1130 .arg(simObject.getObjectId()));
1133 this->sendRemoteAircraftAtcDataToSimulator(simObject);
1139 u
"Verified aircraft '%1' model '%2', request/object id: %3 %4 was already marked rendered")
1140 << callsign.asString() << remoteAircraft.
getModelString() << simObject.getRequestId()
1141 << simObject.getObjectId();
1144 if (simObject.isConfirmedAdded() && simObject.getType() == CSimConnectObject::AircraftSimulatedObject)
1148 << simObject.getTypeAsString();
1150 simObject.decreaseAddingExceptions();
1158 CLogMessage::preformatted(msg);
1163 if (!m_addPendingAircraft.
isEmpty()) { this->addPendingAircraftAfterAdded(); }
1166 void CSimulatorFsxCommon::addingAircraftFailed(
const CSimConnectObject &simObject)
1168 if (CBuildConfig::isLocalDeveloperDebugBuild())
1170 Q_ASSERT_X(simObject.isAircraft(), Q_FUNC_INFO,
"Need aircraft");
1172 if (!simObject.isAircraft()) {
return; }
1176 this->removeFromAddPendingAndAddAgainAircraft(simObject.getCallsign());
1179 << simObject.getAircraftModelString() << simObject.getAircraft().toQString(
true);
1181 const bool verifiedAircraft = this->verifyFailedAircraftInfo(simObject, verifyMsg);
1182 if (!verifyMsg.
isEmpty()) { CLogMessage::preformatted(verifyMsg); }
1184 CSimConnectObject simObjAddAgain(simObject);
1185 simObjAddAgain.increaseAddingExceptions();
1186 if (!simObject.hasCallsign())
1192 if (!verifiedAircraft || simObjAddAgain.getAddingExceptions() > ThresholdAddException)
1196 CLogMessage(
this).
warning(u
"Model '%1' %2 failed %3 time(s) before and will be disabled")
1197 << simObjAddAgain.getAircraftModelString() << simObjAddAgain.toQString()
1198 << simObjAddAgain.getAddingExceptions() :
1200 << simObjAddAgain.getAircraftModelString() << simObjAddAgain.toQString();
1208 << simObject.getAircraftModelString() << simObject.getAircraft().toQString(
true);
1211 if (!myself) {
return; }
1213 m_addPendingAircraft.
insert(simObjAddAgain,
true);
1218 bool CSimulatorFsxCommon::verifyFailedAircraftInfo(
const CSimConnectObject &simObject,
1225 bool canBeUsed =
true;
1231 bool parsed =
false;
1233 CAircraftCfgParser::performParsingOfSingleFile(model.
getFileName(), parsed, messages);
1245 CStatusMessage(
this).warning(u
"Model '%1' no longer in re-parsed file '%2'. Models are: %3.")
1271 bool CSimulatorFsxCommon::logVerifyFailedAircraftInfo(
const CSimConnectObject &simObject)
const
1274 const bool r = verifyFailedAircraftInfo(simObject, m);
1275 if (!m.
isEmpty()) { CLogMessage::preformatted(m); }
1279 void CSimulatorFsxCommon::verifyAddedTerrainProbe(
const CSimulatedAircraft &remoteAircraftIn)
1281 bool verified =
false;
1287 simObject.setConfirmedAdded(
true);
1288 simObject.resetTimestampToNow();
1289 cs = simObject.getCallsign();
1291 << simObject.getCallsignAsString() << simObject.getAircraftModelString() << simObject.toQString();
1306 if (!m_addPendingAircraft.
isEmpty()) { this->addPendingAircraftAfterAdded(); }
1309 void CSimulatorFsxCommon::timerBasedObjectAddOrRemove()
1311 this->addPendingAircraft(AddByTimer);
1312 if (!this->
isTestMode()) { this->physicallyRemoveAircraftNotInProvider(); }
1315 void CSimulatorFsxCommon::addPendingAircraftAfterAdded()
1317 this->addPendingAircraft(AddAfterAdded);
1320 void CSimulatorFsxCommon::addPendingAircraft(AircraftAddMode mode)
1322 if (m_addPendingAircraft.
isEmpty()) {
return; }
1327 for (
const CSimConnectObject &pendingSimObj : std::as_const(m_addPendingAircraft))
1329 SWIFT_VERIFY_X(pendingSimObj.hasCallsign(), Q_FUNC_INFO,
"missing callsign");
1330 if (!pendingSimObj.hasCallsign()) {
continue; }
1331 if (pendingSimObj.isTerrainProbe() || aircraftCallsignsInRange.contains(pendingSimObj.getCallsign()))
1333 toBeAddedAircraft.
push_back(pendingSimObj.getAircraft());
1335 else { toBeRemovedCallsigns.
push_back(pendingSimObj.getCallsign()); }
1343 if (!toBeAddedAircraft.
isEmpty())
1345 const CSimConnectObject oldestSimObject = m_addPendingAircraft.
getOldestObject();
1351 if (!myself) {
return; }
1353 this->physicallyAddRemoteAircraftImpl(nextPendingAircraft, mode, oldestSimObject);
1364 CSimConnectObject CSimulatorFsxCommon::removeFromAddPendingAndAddAgainAircraft(
const CCallsign &callsign)
1366 CSimConnectObject simObjectOld;
1367 if (callsign.
isEmpty()) {
return simObjectOld; }
1370 if (m_addPendingAircraft.
contains(callsign))
1372 simObjectOld = m_addPendingAircraft[callsign];
1373 m_addPendingAircraft.
remove(callsign);
1375 return simObjectOld;
1378 bool CSimulatorFsxCommon::simulatorReportedObjectRemoved(
DWORD objectID)
1382 if (!simObject.hasValidRequestAndObjectId()) {
return false; }
1384 const CCallsign callsign(simObject.getCallsign());
1385 Q_ASSERT_X(!callsign.
isEmpty(), Q_FUNC_INFO,
"Missing callsign for removed object");
1387 if (simObject.isPendingRemoved())
1401 if (!simObject.getAircraftModelString().isEmpty() &&
1402 simObject.getAddingDirectlyRemoved() < ThresholdAddedAndDirectlyRemoved)
1404 simObject.increaseAddingDirectlyRemoved();
1405 m_addPendingAircraft.
insert(simObject,
true);
1411 msg =
CLogMessage(
this).
warning(u
"Aircraft removed, '%1' '%2' object id '%3' out of reality bubble or "
1412 u
"other reason. Interpolator: '%4'")
1413 << callsign.
toQString() << simObject.getAircraftModelString() << objectID
1416 else if (simObject.getAddingDirectlyRemoved() < ThresholdAddedAndDirectlyRemoved)
1420 u
"Aircraft removed again multiple times and will be disabled, '%1' '%2' object id '%3'")
1421 << callsign.
toQString() << simObject.getAircraftModelString() << objectID;
1429 u
"Removed '%1' from simulator, but was not initiated by us (swift): %1 '%2' object id %3")
1430 << callsign.
toQString() << simObject.getAircraftModelString() << objectID;
1434 this->logVerifyFailedAircraftInfo(simObject);
1442 const bool removedAny = (c > 0);
1453 if (!myself) {
return; }
1455 myself->physicallyAddRemoteAircraftImpl(aircraftAddAgain, AddedAfterRemoved);
1461 bool CSimulatorFsxCommon::setSimConnectObjectId(
DWORD requestId,
DWORD objectId)
1494 const bool trace = parser.
toBool(2);
1495 this->setTraceSendId(trace);
1496 CLogMessage(
this, CLogCategories::cmdLine()).
info(u
"Tracing %1 driver sendIds is '%2'")
1504 const bool on = parser.
toBool(2);
1513 const bool on = parser.
toBool(2);
1514 m_logSbOffsets = on;
1519 return CSimulatorFsCommon::parseDetails(parser);
1524 if (CSimpleCommandParser::registered(
"swift::simplugin::fsxcommon::CSimulatorFsxCommon::CSimulatorFsxCommon"))
1528 CSimpleCommandParser::registerCommand({
".drv",
"alias: .driver .plugin" });
1529 CSimpleCommandParser::registerCommand({
".drv sendid on|off",
"Trace simConnect sendId on|off" });
1530 CSimpleCommandParser::registerCommand({
".drv sboffsets on|off",
"SB offsets via simConnect on|off" });
1531 CSimpleCommandParser::registerCommand({
".drv sblog on|off",
"SB offsets logging on|off" });
1541 const QString &CSimulatorFsxCommon::modeToString(CSimulatorFsxCommon::AircraftAddMode mode)
1543 static const QString e(
"external call");
1544 static const QString pt(
"add pending by timer");
1545 static const QString oa(
"add pending after object added");
1546 static const QString ar(
"add again after removed");
1547 static const QString dontKnow(
"???");
1551 case ExternalCall:
return e;
1552 case AddByTimer:
return pt;
1553 case AddAfterAdded:
return oa;
1554 case AddedAfterRemoved:
return ar;
1560 void CSimulatorFsxCommon::dispatch()
1566 m_dispatchReceiveIdLast = SIMCONNECT_RECV_ID_NULL;
1575 m_dispatchTimeMs =
end - start;
1576 if (m_dispatchMaxTimeMs < m_dispatchTimeMs)
1578 m_dispatchMaxTimeMs = m_dispatchTimeMs;
1579 m_dispatchReceiveIdMaxTime = m_dispatchReceiveIdLast;
1580 m_dispatchRequestIdMaxTime = m_dispatchRequestIdLast;
1589 const bool disconnectedOrNotSimulating =
1594 if (m_dispatchErrors == 2)
1599 QStringLiteral(u
"%1: Dispatch error, sim.status: %2")
1602 disconnectedOrNotSimulating ? CStatusMessage::SeverityWarning : CStatusMessage::SeverityError, msg);
1604 else if (m_dispatchErrors > 5)
1608 QStringLiteral(u
"%1: Multiple dispatch errors, disconnecting. Sim.status: %2")
1611 disconnectedOrNotSimulating ? CStatusMessage::SeverityWarning : CStatusMessage::SeverityError, msg);
1616 m_dispatchErrors = 0;
1619 bool CSimulatorFsxCommon::physicallyAddRemoteAircraftImpl(
const CSimulatedAircraft &newRemoteAircraft,
1620 CSimulatorFsxCommon::AircraftAddMode addMode,
1621 const CSimConnectObject &correspondingSimObject)
1627 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"thread");
1628 Q_ASSERT_X(!callsign.
isEmpty(), Q_FUNC_INFO,
"empty callsign");
1629 Q_ASSERT_X(newRemoteAircraft.
hasModelString(), Q_FUNC_INFO,
"missing model string");
1632 m_simObjectTimer.
start(AddPendingAircraftIntervalMs);
1635 const CSimConnectObjects outdatedAdded =
1637 if (!outdatedAdded.isEmpty())
1639 const CCallsignSet callsigns = outdatedAdded.getAllCallsigns(
false);
1644 static const QString msgText(
"%1 outdated adding, %2");
1645 for (
const CSimConnectObject &simObjOutdated : outdatedAdded)
1648 msgText.arg(simObjOutdated.getCallsign().asString(), simObjOutdated.toQString()));
1657 bool canAdd = this->
isSimulating() && !hasPendingAdded;
1660 "There must be only 0..1 pending objects");
1663 this->
debugLogMessage(Q_FUNC_INFO, QStringLiteral(
"CS: '%1' mode: '%2' model: '%3'")
1667 Q_FUNC_INFO, QStringLiteral(
"CS: '%1' pending callsigns: '%2', pending objects: '%3'")
1679 const QString simObjModelString(simObject.getAircraftModelString());
1680 const bool sameModel =
1681 (simObjModelString ==
1692 const bool rendered = simObject.isConfirmedAdded() && simObject.isPending();
1702 QStringLiteral(
"CS: '%1' re-added changed model '%2', will be added again")
1710 if (canAdd && situation.isPositionOrAltitudeNull())
1714 if (situations.isEmpty())
1721 CLogMessage(
this).
warning(u
"Invalid aircraft situation for new aircraft '%1', use closest situation")
1724 Q_ASSERT_X(!situation.isPositionOrAltitudeNull(), Q_FUNC_INFO,
"Invalid situation for new aircraft");
1728 canAdd = situation.isPositionOrAltitudeNull();
1729 if (CBuildConfig::isLocalDeveloperDebugBuild())
1739 CSimConnectObject &addPendingObj = m_addPendingAircraft[newRemoteAircraft.
getCallsign()];
1740 addPendingObj.setAircraft(newRemoteAircraft);
1741 addPendingObj.resetTimestampToNow();
1746 const CSimConnectObject removedPendingObj = this->removeFromAddPendingAndAddAgainAircraft(callsign);
1761 bool adding =
false;
1762 const SIMCONNECT_DATA_REQUEST_ID requestId =
1769 const CSimConnectObject dummyObject = CSimConnectObject(
1783 const SIMCONNECT_DATA_INITPOSITION initialPosition =
1789 this->
debugLogMessage(Q_FUNC_INFO, QStringLiteral(
"CS: '%1' model: '%2' request: %3, init pos: %4")
1792 .
arg(fsxPositionToString(initialPosition)));
1804 type = CSimConnectObject::TerrainProbe;
1809 correspondingSimObject.getAddingExceptions() > 0 &&
1810 correspondingSimObject.getType() == CSimConnectObject::AircraftNonAtc)
1813 u
"Model '%1' for '%2' failed %1 time(s) before, using AICreateSimulatedObject now")
1817 type = CSimConnectObject::AircraftSimulatedObject;
1822 initialPosition, requestId);
1823 type = CSimConnectObject::AircraftNonAtc;
1827 if (!underflowStatus.
isEmpty())
1837 CLogMessage::preformatted(msg);
1844 const CSimConnectObject simObject =
1845 this->insertNewSimConnectObject(newRemoteAircraft, requestId, type, removedPendingObj);
1846 this->traceSendId(simObject, Q_FUNC_INFO,
1847 QStringLiteral(
"mode: %1").arg(CSimulatorFsxCommon::modeToString(addMode)),
true);
1853 bool CSimulatorFsxCommon::physicallyAddAITerrainProbe(
const ICoordinateGeodetic &coordinate,
int number)
1855 if (coordinate.
isNull()) {
return false; }
1857 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"thread");
1865 static const QString modelString(
"swiftTerrainProbe0");
1866 static const QString pseudoCallsign(
"PROBE%1");
1867 static const CCountry ctry(
"SW",
"SWIFT");
1868 static const CAirlineIcaoCode swiftAirline(
"SWI",
"swift probe", ctry,
"SWIFT",
false,
false);
1869 static const CLivery swiftLivery(CLivery::getStandardCode(swiftAirline), swiftAirline,
"swift probe");
1871 const CCallsign cs(pseudoCallsign.arg(number));
1872 const CAircraftModel model(modelString, CAircraftModel::TypeTerrainProbe, QStringLiteral(
"swift terrain probe"),
1873 CAircraftIcaoCode::unassignedIcao(), swiftLivery);
1875 situation.setAltitude(terrainProbeAltitude());
1876 situation.setZeroPBH();
1878 return this->physicallyAddRemoteAircraftImpl(pseudoAircraft, ExternalCall);
1881 int CSimulatorFsxCommon::physicallyInitAITerrainProbes(
const ICoordinateGeodetic &coordinate,
int number)
1883 if (number < 1) {
return 0; }
1889 for (
int n = 0; n < number; ++n)
1891 if (this->physicallyAddAITerrainProbe(coordinate, n)) { c++; }
1902 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"wrong thread");
1903 if (callsign.
isEmpty()) {
return false; }
1906 this->removeFromAddPendingAndAddAgainAircraft(callsign);
1915 m_addPendingAircraft.
remove(callsign);
1922 CLogMessage(
this).
warning(u
"'%1' requested to be removed, but pending added (%2) / or pending lights(%3). "
1923 u
"Object will be removed again: %4")
1924 << callsign.
asString() << boolToYesNo(pendingAdded) << boolToYesNo(stillWaitingForLights)
1929 if (!myself) {
return; }
1931 myself->physicallyRemoveRemoteAircraft(callsign);
1937 this->stopRequestingDataForSimObject(simObject);
1943 this->
debugLogMessage(Q_FUNC_INFO, QStringLiteral(
"CS: '%1' request/object id: %2/%3")
1950 const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.
getRequestId(CSimConnectDefinitions::SimObjectRemove);
1953 const HRESULT result = SimConnect_AIRemoveObject(
1957 if (this->
isTracingSendId()) { this->traceSendId(simObject, Q_FUNC_INFO); }
1971 this->physicallyRemoveAircraftNotInProviderAsync();
1974 return CSimulatorPluginCommon::physicallyRemoveRemoteAircraft(callsign);
1981 m_addPendingAircraft.
clear();
1992 CSimulatorFsCommon::physicallyRemoveAllRemoteAircraft();
1996 HRESULT CSimulatorFsxCommon::initEvents()
1998 HRESULT hr =
s_ok();
2000 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventSimStatus,
"Sim");
2001 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventObjectAdded,
"ObjectAdded");
2002 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventObjectRemoved,
"ObjectRemoved");
2003 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventFrame,
"Frame");
2004 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventPause,
"Pause");
2005 hr += SimConnect_SubscribeToSystemEvent(
m_hSimConnect, SystemEventFlightLoaded,
"FlightLoaded");
2008 CLogMessage(
this).
error(u
"FSX plugin error: %1") <<
"SimConnect_SubscribeToSystemEvent failed";
2015 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventPauseToggle,
"PAUSE_TOGGLE");
2016 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, SystemEventSlewToggle,
"SLEW_TOGGLE");
2017 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventFreezeLatLng,
2018 "FREEZE_LATITUDE_LONGITUDE_SET");
2019 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventFreezeAlt,
2020 "FREEZE_ALTITUDE_SET");
2021 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventFreezeAtt,
2022 "FREEZE_ATTITUDE_SET");
2023 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetCom1Active,
"COM_RADIO_SET");
2024 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetCom1Standby,
"COM_STBY_RADIO_SET");
2025 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetCom2Active,
"COM2_RADIO_SET");
2026 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetCom2Standby,
"COM2_STBY_RADIO_SET");
2027 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetTransponderCode,
"XPNDR_SET");
2029 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetTimeZuluYear,
"ZULU_YEAR_SET");
2030 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetTimeZuluDay,
"ZULU_DAY_SET");
2031 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetTimeZuluHours,
"ZULU_HOURS_SET");
2032 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventSetTimeZuluMinutes,
"ZULU_MINUTES_SET");
2034 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventLandingLightsOff,
"LANDING_LIGHTS_OFF");
2035 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventLandinglightsOn,
"LANDING_LIGHTS_ON");
2036 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventLandingLightsSet,
"LANDING_LIGHTS_SET");
2037 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventLandingLightsToggle,
"LANDING_LIGHTS_TOGGLE");
2038 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventPanelLightsOff,
"PANEL_LIGHTS_OFF");
2039 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventPanelLightsOn,
"PANEL_LIGHTS_ON");
2040 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventPanelLightsSet,
"PANEL_LIGHTS_SET");
2041 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventStrobesOff,
"STROBES_OFF");
2042 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventStrobesOn,
"STROBES_ON");
2043 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventStrobesSet,
"STROBES_SET");
2044 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventStrobesToggle,
"STROBES_TOGGLE");
2045 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleBeaconLights,
"TOGGLE_BEACON_LIGHTS");
2046 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleCabinLights,
"TOGGLE_CABIN_LIGHTS");
2047 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleLogoLights,
"TOGGLE_LOGO_LIGHTS");
2048 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleNavLights,
"TOGGLE_NAV_LIGHTS");
2049 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleRecognitionLights,
2050 "TOGGLE_RECOGNITION_LIGHTS");
2051 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleTaxiLights,
"TOGGLE_TAXI_LIGHTS");
2052 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventToggleWingLights,
"TOGGLE_WING_LIGHTS");
2054 hr += SimConnect_MapClientEventToSimEvent(
m_hSimConnect, EventFlapsSet,
"FLAPS_SET");
2058 CLogMessage(
this).
error(u
"FSX plugin error: %1") <<
"SimConnect_MapClientEventToSimEvent failed";
2063 SIMCONNECT_DATA_REQUEST_ID requestId =
2064 static_cast<SIMCONNECT_DATA_REQUEST_ID
>(CSimConnectDefinitions::RequestFacility);
2065 hr += SimConnect_SubscribeToFacilities(
m_hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, requestId);
2068 CLogMessage(
this).
error(u
"FSX plugin error: %1") <<
"SimConnect_SubscribeToFacilities failed";
2074 HRESULT CSimulatorFsxCommon::initDataDefinitionsWhenConnected()
2080 HRESULT CSimulatorFsxCommon::initWhenConnected()
2084 HRESULT hr = this->initEvents();
2092 hr += this->initDataDefinitionsWhenConnected();
2095 CLogMessage(
this).
error(u
"FSX plugin: initDataDefinitionsWhenConnected failed");
2102 void CSimulatorFsxCommon::updateRemoteAircraft()
2104 static_assert(
sizeof(DataDefinitionRemoteAircraftPartsWithoutLights) ==
sizeof(
double) * 14,
2105 "DataDefinitionRemoteAircraftPartsWithoutLights has an incorrect size.");
2106 Q_ASSERT_X(CThreadUtils::isInThisThread(
this), Q_FUNC_INFO,
"thread");
2110 if (remoteAircraftNo < 1)
2128 uint32_t simObjectNumber = 0;
2131 for (
const CSimConnectObject &simObject : simObjects)
2134 if (!simObject.isReadyToSend()) {
continue; }
2135 if (!simObject.hasCurrentLightsInSimulator()) {
continue; }
2137 const CCallsign callsign(simObject.getCallsign());
2138 const bool hasCs = !callsign.
isEmpty();
2139 const bool hasValidIds = simObject.hasValidRequestAndObjectId();
2142 if (!hasCs || !hasValidIds) {
continue; }
2143 const DWORD objectId = simObject.getObjectId();
2153 const CInterpolationResult result = simObject.getInterpolation(currentTimestamp, setup, simObjectNumber++);
2162 const CLength relativeAltitude =
2164 const double altitudeDeltaWeight =
2165 2 - qBound(3000.0, relativeAltitude.
abs().
value(CLengthUnit::ft()), 6000.0) / 3000;
2173 static_cast<SIMCONNECT_OBJECT_ID
>(objectId), 0, 0,
2174 sizeof(SIMCONNECT_DATA_INITPOSITION), &position),
2175 traceSendId, simObject,
"Failed to set position", Q_FUNC_INFO,
"SimConnect_SetDataOnSimObject");
2189 const bool updatedParts = this->updateRemoteAircraftParts(simObject, result, forceUpdate);
2190 Q_UNUSED(updatedParts)
2198 bool CSimulatorFsxCommon::updateRemoteAircraftParts(
const CSimConnectObject &simObject,
2201 if (!simObject.hasValidRequestAndObjectId()) {
return false; }
2202 if (!simObject.isConfirmedAdded()) {
return false; }
2205 if (parts.
isNull()) {
return false; }
2211 const CCallsign cs = simObject.getCallsign();
2217 const bool ok = this->sendRemoteAircraftPartsToSimulator(simObject, parts);
2222 bool CSimulatorFsxCommon::sendRemoteAircraftPartsToSimulator(
const CSimConnectObject &simObject,
2226 if (!simObject.isReadyToSend()) {
return false; }
2228 const DWORD objectId = simObject.getObjectId();
2231 DataDefinitionRemoteAircraftPartsWithoutLights ddRemoteAircraftPartsWithoutLights(parts);
2235 const bool simObjectAircraftType = simObject.isAircraftSimulatedObject();
2237 simObjectAircraftType ?
2240 SimConnect_SetDataOnSimObject(
2241 m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftPartsWithoutLights,
2242 static_cast<SIMCONNECT_OBJECT_ID
>(objectId), SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0,
2243 sizeof(DataDefinitionRemoteAircraftPartsWithoutLights), &ddRemoteAircraftPartsWithoutLights),
2244 traceId, simObject,
"Failed so set parts", Q_FUNC_INFO,
2245 "SimConnect_SetDataOnSimObject::ddRemoteAircraftPartsWithoutLights");
2251 SimConnect_TransmitClientEvent(
m_hSimConnect, objectId, EventFlapsSet, flapsDw,
2252 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2253 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2254 traceId, simObject,
"Failed so set flaps", Q_FUNC_INFO,
"SimConnect_TransmitClientEvent::EventFlapsSet");
2258 SimConnect_TransmitClientEvent(
m_hSimConnect, objectId, EventLandingLightsSet,
2259 lights.
isLandingOn() ? 1.0 : 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2260 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2261 traceId, simObject,
"Failed so set landing lights", Q_FUNC_INFO,
2262 "SimConnect_TransmitClientEvent::EventLandingLightsSet");
2267 SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2268 traceId, simObject,
"Failed to set strobe lights", Q_FUNC_INFO,
2269 "SimConnect_TransmitClientEvent::EventStrobesSet");
2274 this->sendToggledLightsToSimulator(simObject, lights);
2277 return isOk(hr1, hr2, hr3, hr4);
2280 bool CSimulatorFsxCommon::sendRemoteAircraftAtcDataToSimulator(
const CSimConnectObject &simObject)
2282 if (!simObject.isReadyToSend()) {
return false; }
2283 if (simObject.isTerrainProbe()) {
return false; }
2286 const DWORD objectId = simObject.getObjectId();
2289 DataDefinitionRemoteAtc ddAtc;
2290 ddAtc.setDefaultValues();
2291 const QByteArray csBa = simObject.getCallsignByteArray();
2292 const QByteArray airlineBa = simObject.getAircraft().getAirlineIcaoCode().getName().toLatin1();
2296 ddAtc.copyAtcAirline(airlineBa.
constData());
2297 ddAtc.copyFlightNumber(flightNumberBa.
constData());
2302 static_cast<SIMCONNECT_OBJECT_ID
>(objectId), SIMCONNECT_DATA_SET_FLAG_DEFAULT,
2303 0,
sizeof(DataDefinitionRemoteAtc), &ddAtc),
2304 traceId, simObject,
"Failed so aircraft ATC data", Q_FUNC_INFO,
"SimConnect_SetDataOnSimObject");
2309 void CSimulatorFsxCommon::sendToggledLightsToSimulator(
const CSimConnectObject &simObj,
2312 if (!simObj.isReadyToSend()) {
return; }
2314 const CAircraftLights lightsIsState = simObj.getCurrentLightsInSimulator();
2315 if (lightsWanted == lightsIsState) {
return; }
2316 if (!force && lightsWanted == simObj.getLightsAsSent()) {
return; }
2317 const CCallsign callsign(simObj.getCallsign());
2323 simObjToUpdate.setLightsAsSent(lightsWanted);
2327 if (!lightsIsState.
isNull())
2329 const DWORD objectId = simObj.getObjectId();
2335 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2336 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2337 trace, simObj,
"Toggle taxi lights", Q_FUNC_INFO,
"EventToggleTaxiLights");
2342 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2343 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2344 trace, simObj,
"Toggle nav.lights", Q_FUNC_INFO,
"EventToggleNavLights");
2349 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2350 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2351 trace, simObj,
"Toggle becon lights", Q_FUNC_INFO,
"EventToggleBeaconLights");
2356 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2357 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2358 trace, simObj,
"Toggle logo lights", Q_FUNC_INFO,
"EventToggleLogoLights");
2363 SimConnect_TransmitClientEvent(
m_hSimConnect, objectId, EventToggleRecognitionLights, 0.0,
2364 SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2365 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2366 trace, simObj,
"Toggle recognition lights", Q_FUNC_INFO,
"EventToggleRecognitionLights");
2371 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST,
2372 SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY),
2373 trace, simObj,
"Toggle cabin lights", Q_FUNC_INFO,
"EventToggleCabinLights");
2381 this->
debugLogMessage(Q_FUNC_INFO, QStringLiteral(
"Missing light state in simulator for '%1', model '%2'")
2382 .arg(callsign.
asString(), simObj.getAircraftModelString()));
2387 if (!myself) {
return; }
2390 if (!currentSimObject.isReadyToSend()) { return; }
2391 if (lightsWanted != currentSimObject.getLightsAsSent())
2397 this->
debugLogMessage(Q_FUNC_INFO, QStringLiteral(
"Resending light state for '%1', model '%2'")
2398 .arg(callsign.
asString(), simObj.getAircraftModelString()));
2400 this->sendToggledLightsToSimulator(currentSimObject, lightsWanted,
true);
2404 SIMCONNECT_DATA_INITPOSITION
2409 Q_ASSERT_X(!situation.
isPositionNull(), Q_FUNC_INFO,
"Missing position");
2414 if (forceUnderflowDetection)
2417 position.Altitude = alt.
value(CLengthUnit::ft());
2421 position.Pitch = -situation.
getPitch().
value(CAngleUnit::deg());
2422 position.Bank = -situation.
getBank().
value(CAngleUnit::deg());
2424 position.OnGround = 0U;
2427 position.Airspeed =
static_cast<DWORD>(qRound(gsKts));
2434 position.Airspeed = 0U;
2436 else { position.Airspeed =
static_cast<DWORD>(qRound(gsKts)); }
2441 const bool onGround = situation.
isOnGround();
2442 position.OnGround = onGround ? 1U : 0U;
2446 if (forceUnderflowDetection && position.OnGround == 0 &&
2447 !CAircraftSituation::isCorrectedAltitude(altCorrection))
2452 if (position.Airspeed < 2)
2454 position.OnGround = 1U;
2458 .
warning(u
"Force GND flag for underflow protection");
2467 if (CBuildConfig::isLocalDeveloperDebugBuild())
2487 SIMCONNECT_DATA_INITPOSITION position;
2488 position.Latitude = coordinate.
latitude().
value(CAngleUnit::deg());
2489 position.Longitude = coordinate.
longitude().
value(CAngleUnit::deg());
2492 position.Heading = 0;
2493 position.Airspeed = 0;
2496 position.OnGround = 0;
2502 SIMCONNECT_DATA_LATLONALT lla;
2503 lla.Latitude = coordinate.
latitude().
value(CAngleUnit::deg());
2525 bool CSimulatorFsxCommon::requestPositionDataForSimObject(
const CSimConnectObject &simObject,
2526 SIMCONNECT_PERIOD period)
2530 if (simObject.
isPending()) {
return false; }
2535 const SIMCONNECT_DATA_REQUEST_ID reqId =
static_cast<SIMCONNECT_DATA_REQUEST_ID
>(
2536 simObject.
getRequestId(CSimConnectDefinitions::SimObjectPositionData));
2541 simObject,
"Cannot request simulator data", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2545 m_requestSimObjectDataCount++;
2552 bool CSimulatorFsxCommon::requestTerrainProbeData(
const CSimConnectObject &simObject,
2555 static const QString w(
"Cannot request terrain probe data for id '%1'");
2556 const SIMCONNECT_DATA_REQUEST_ID requestId =
2557 simObject.getRequestId(CSimConnectDefinitions::SimObjectPositionData);
2558 const DWORD objectId = simObject.getObjectId();
2560 SimConnect_RequestDataOnSimObject(
m_hSimConnect,
static_cast<SIMCONNECT_DATA_REQUEST_ID
>(requestId),
2562 static_cast<SIMCONNECT_OBJECT_ID
>(objectId), SIMCONNECT_PERIOD_ONCE),
2563 simObject, w.arg(requestId), Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2564 const bool ok = isOk(result);
2569 bool CSimulatorFsxCommon::requestLightsForSimObject(
const CSimConnectObject &simObject)
2575 const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectLights);
2578 CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(),
2579 SIMCONNECT_PERIOD_SECOND),
2580 simObject,
"Cannot request lights data", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2581 return isOk(result);
2584 bool CSimulatorFsxCommon::requestModelInfoForSimObject(
const CSimConnectObject &simObject)
2590 const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectModel);
2594 simObject.getObjectId(), SIMCONNECT_PERIOD_ONCE),
2595 simObject,
"Cannot request model info", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2596 return isOk(result);
2599 bool CSimulatorFsxCommon::stopRequestingDataForSimObject(
const CSimConnectObject &simObject)
2601 if (!simObject.hasValidRequestAndObjectId()) {
return false; }
2605 SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectPositionData);
2609 simObject.getObjectId(), SIMCONNECT_PERIOD_NEVER),
2610 simObject,
"Stopping position request", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2612 requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectLights);
2615 CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(),
2616 SIMCONNECT_PERIOD_NEVER),
2617 simObject,
"Stopping lights request", Q_FUNC_INFO,
"SimConnect_RequestDataOnSimObject");
2618 return isOk(hr1, hr2);
2623 CSimulatorFsCommon::initSimulatorInternals();
2637 CSimulatorFsCommon::reset();
2640 m_simulatingChangedTs = -1;
2641 m_simConnected =
false;
2642 m_simSimulating =
false;
2643 m_sbDataReceived = 0;
2644 m_requestIdSimObjAircraft =
static_cast<SIMCONNECT_DATA_REQUEST_ID
>(RequestSimObjAircraftStart);
2645 m_dispatchErrors = 0;
2646 m_receiveExceptionCount = 0;
2649 m_sendIdTraces.clear();
2654 const bool reinitProbe =
2656 this->removeAllProbes();
2659 CSimulatorFsCommon::clearAllRemoteAircraftData();
2661 m_addPendingAircraft.
clear();
2662 m_simConnectObjectsPositionAndPartsTraces.
clear();
2678 m_sbDataReceived = 0;
2679 CSimulatorFsCommon::onOwnModelChanged(newModel);
2682 QString CSimulatorFsxCommon::fsxPositionToString(
const SIMCONNECT_DATA_INITPOSITION &position)
2684 static const QString positionStr(
2685 "Lat: %1deg lng: %2deg alt: %3ft pitch: %4deg bank: %5deg hdg: %6deg airspeed: %7kts onGround: %8");
2686 return positionStr.arg(position.Latitude)
2687 .arg(position.Longitude)
2688 .arg(position.Altitude)
2689 .arg(position.Pitch)
2691 .arg(position.Heading)
2692 .arg(position.Airspeed)
2693 .arg(position.OnGround);
2696 CCallsignSet CSimulatorFsxCommon::getCallsignsMissingInProvider()
const
2701 return simObjectCallsigns.difference(providerCallsigns);
2704 void CSimulatorFsxCommon::traceSendId(
const CSimConnectObject &simObject,
const QString &functionName,
2705 const QString &details,
bool forceTrace)
2708 if (MaxSendIdTraces < 1) {
return; }
2710 const HRESULT hr = SimConnect_GetLastSentPacketID(
m_hSimConnect, &dwLastId);
2712 if (m_sendIdTraces.size() > MaxSendIdTraces) { m_sendIdTraces.removeLast(); }
2713 const TraceFsxSendId trace(dwLastId, simObject,
2714 details.
isEmpty() ? functionName : details % u
", " % functionName);
2715 m_sendIdTraces.push_front(trace);
2719 const QString &functionDetails)
2722 return this->
logAndTraceSendId(hr, empty, warningMsg, functionName, functionDetails);
2727 const QString &functionDetails)
2735 const QString &functionDetails)
2737 if (traceSendId) { this->traceSendId(simObject, functionName, functionDetails); }
2738 if (isOk(hr)) {
return hr; }
2750 if (trace.sendId == sendId) {
return trace; }
2755 QString CSimulatorFsxCommon::getSendIdTraceDetails(
DWORD sendId)
const
2757 const TraceFsxSendId trace = this->getSendIdTrace(sendId);
2758 if (trace.sendId == sendId) {
return this->getSendIdTraceDetails(trace); }
2762 QString CSimulatorFsxCommon::getSendIdTraceDetails(
const TraceFsxSendId &trace)
const
2764 static const QString d(
"Send id: %1 obj.id.: %2 SimObj: %3 | '%4'");
2765 if (trace.isInvalid()) {
return QString(); }
2769 return d.arg(trace.sendId).arg(simObject.getObjectId()).arg(simObject.toQString(), trace.comment);
2772 int CSimulatorFsxCommon::removeAllProbes()
2778 for (
const CSimConnectObject &probeSimObject : probes)
2780 if (!probeSimObject.isConfirmedAdded()) {
continue; }
2781 const SIMCONNECT_DATA_REQUEST_ID requestId =
2782 probeSimObject.getRequestId(CSimConnectDefinitions::SimObjectRemove);
2783 const HRESULT result = SimConnect_AIRemoveObject(
2784 m_hSimConnect,
static_cast<SIMCONNECT_OBJECT_ID
>(probeSimObject.getObjectId()), requestId);
2785 if (isOk(result)) { c++; }
2788 CLogMessage(
this).
warning(u
"Removing probe '%1' from simulator failed") << probeSimObject.getObjectId();
2796 CSimConnectObject CSimulatorFsxCommon::insertNewSimConnectObject(
const CSimulatedAircraft &aircraft,
2799 const CSimConnectObject &removedPendingObject)
2805 simObject.copyAddingFailureCounters(removedPendingObject);
2806 simObject.resetTimestampToNow();
2810 CSimConnectObject simObject;
2814 simObject = m_simConnectObjectsPositionAndPartsTraces[aircraft.
getCallsign()];
2816 simObject.resetState();
2817 simObject.setRequestId(requestId);
2818 simObject.setAircraft(aircraft);
2826 simObject.copyAddingFailureCounters(removedPendingObject);
2827 simObject.setType(type);
2832 const CAltitude &CSimulatorFsxCommon::terrainProbeAltitude()
2834 static const CAltitude alt(50000, CLengthUnit::ft());
2843 QString CSimulatorFsxCommon::requestIdToString(
DWORD requestId)
2853 static const QString req(
"%1 %2 %3");
2854 return req.arg(requestId)
2865 case CSimConnectObject::TerrainProbe:
2866 start = RequestSimObjTerrainProbeStart;
2867 end = RequestSimObjTerrainProbeEnd;
2869 case CSimConnectObject::AircraftNonAtc:
2870 case CSimConnectObject::AircraftSimulatedObject:
2872 start = RequestSimObjAircraftStart;
2873 end = RequestSimObjAircraftEnd;
2877 const int id = CMathUtils::randomInteger(start,
end);
2878 return static_cast<DWORD>(id);
2881 CCallsignSet CSimulatorFsxCommon::physicallyRemoveAircraftNotInProvider()
2883 const CCallsignSet callsignsToBeRemoved(this->getCallsignsMissingInProvider());
2884 if (callsignsToBeRemoved.isEmpty()) {
return callsignsToBeRemoved; }
2890 QStringLiteral(
"CS: '%1'").arg(callsignsToBeRemoved.toStringList().join(
", ")));
2892 return callsignsToBeRemoved;
2895 void CSimulatorFsxCommon::physicallyRemoveAircraftNotInProviderAsync()
2900 CSimulatorFsxCommon::physicallyRemoveAircraftNotInProvider();
2914 m_simulatorVersion.
clear();
2915 m_simConnectVersion.
clear();
2916 m_simulatorName.
clear();
2917 m_simulatorDetails.
clear();
2925 this->disconnectFromSimulator();
2930 if (!m_timer.
isActive()) {
return; }
2936 this->checkConnection();
2945 if (m_simulatorName.
isEmpty()) {
return ISimulatorListener::backendInfo(); }
2946 return m_simulatorDetails;
2949 void CSimulatorFsxCommonListener::checkConnection()
2951 Q_ASSERT_X(!CThreadUtils::thisIsMainThread(), Q_FUNC_INFO,
"Expect to run in background");
2966 if (!this->connectToSimulator()) {
break; }
2970 const HRESULT result =
2971 SimConnect_CallDispatch(m_hSimConnect, CSimulatorFsxCommonListener::SimConnectProc,
this);
2981 check = this->checkVersionAndSimulator();
2985 this->adjustTimerInterval(t.
elapsed());
2989 void CSimulatorFsxCommonListener::adjustTimerInterval(qint64 checkTimeMs)
2992 CLogMessage(
this).
debug(u
"Checked sim.'%1' connection in %2ms") << sim << checkTimeMs;
2993 if (checkTimeMs > qRound(1.25 * MinQueryIntervalMs))
2995 const int newIntervalMs = qRound(1.2 * checkTimeMs / 1000.0) * 1000;
2996 CLogMessage(
this).
debug(u
"Check for simulator sim.'%1' connection in %2ms, too slow. Setting %3ms")
2997 << sim << checkTimeMs << newIntervalMs;
3002 if (m_timer.
interval() != MinQueryIntervalMs) { m_timer.
setInterval(MinQueryIntervalMs); }
3009 bool CSimulatorFsxCommonListener::checkVersionAndSimulator()
const
3014 if (connectedSimName.
isEmpty()) {
return false; }
3015 if (pluginSim.isP3D())
3018 return connectedSimName.
contains(
"lockheed") || connectedSimName.
contains(
"martin") ||
3021 else if (pluginSim.isFSX())
3024 return connectedSimName.
contains(
"fsx") || connectedSimName.
contains(
"microsoft") ||
3025 connectedSimName.
contains(
"simulator x");
3027 else if (pluginSim.isMSFS())
3030 return connectedSimName.
contains(
"kittyhawk");
3032 else if (pluginSim.isMSFS2024())
3035 return connectedSimName.
contains(
"sunrise");
3040 bool CSimulatorFsxCommonListener::checkSimConnectDll()
const
3047 bool CSimulatorFsxCommonListener::connectToSimulator()
3049 if (m_simConnected) {
return true; }
3050 const HRESULT result = SimConnect_Open(&m_hSimConnect,
sApp->
swiftVersionChar(),
nullptr, 0,
nullptr, 0);
3051 const bool ok = isOk(result);
3052 m_simConnected = ok;
3056 bool CSimulatorFsxCommonListener::disconnectFromSimulator()
3058 if (!m_simConnected) {
return false; }
3059 SimConnect_Close(m_hSimConnect);
3060 m_hSimConnect =
nullptr;
3061 m_simConnected =
false;
3065 void CSimulatorFsxCommonListener::SimConnectProc(SIMCONNECT_RECV *pData,
DWORD cbData,
void *pContext)
3069 switch (pData->dwID)
3071 case SIMCONNECT_RECV_ID_OPEN:
3073 SIMCONNECT_RECV_OPEN *
event =
static_cast<SIMCONNECT_RECV_OPEN *
>(pData);
3074 simListener->m_simulatorVersion = QStringLiteral(
"%1.%2.%3.%4")
3075 .arg(
event->dwApplicationVersionMajor)
3076 .arg(
event->dwApplicationVersionMinor)
3077 .arg(
event->dwApplicationBuildMajor)
3078 .arg(
event->dwApplicationBuildMinor);
3079 simListener->m_simConnectVersion = QStringLiteral(
"%1.%2.%3.%4")
3080 .arg(
event->dwSimConnectVersionMajor)
3081 .arg(
event->dwSimConnectVersionMinor)
3082 .arg(
event->dwSimConnectBuildMajor)
3083 .arg(
event->dwSimConnectBuildMinor);
3085 simListener->m_simulatorDetails = QStringLiteral(
"Name: '%1' Version: %2 SimConnect: %3")
3086 .arg(simListener->m_simulatorName, simListener->m_simulatorVersion,
3087 simListener->m_simConnectVersion);
3089 << simListener->getPluginInfo().getIdentifier() << simListener->backendInfo();
3092 if (msg.
getMessage() != simListener->m_lastMessage.getMessage())
3094 CLogMessage::preformatted(msg);
3095 simListener->m_lastMessage = msg;
3099 case SIMCONNECT_RECV_ID_EXCEPTION:
break;
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
const char * swiftVersionChar()
swift info string
bool isShuttingDown() const
Is application shutting down?
virtual void callbackReceivedRequestedElevation(const swift::misc::geo::CElevationPlane &plane, const swift::misc::aviation::CCallsign &callsign, bool isWater)
A requested elevation has been received.
bool showDebugLogMessage() const
Show log messages?
bool addLoopbackSituation(const swift::misc::aviation::CAircraftSituation &situation)
Add a loopback situation if logging is enabled.
bool isEqualLastSent(const swift::misc::aviation::CAircraftSituation &compare) const
Equal to last sent situation.
bool updateOwnSituationAndGroundElevation(const swift::misc::aviation::CAircraftSituation &situation)
Update own aircraft position and if suitable use it to update ground elevation.
bool isUpdateAllRemoteAircraft(qint64 currentTimestamp=-1) const
Do update all remote aircraft?
virtual bool isShuttingDown() const
Is overall (swift) application shutting down.
int m_timerId
dispatch timer id
void requestedElevation(const swift::misc::aviation::CCallsign &callsign)
Requested elevation, call pending.
bool m_updateRemoteAircraftInProgress
currently updating remote aircraft
virtual bool isShuttingDownDisconnectedOrNoAircraft() const
Shutting down, disconnected, or no remote aircraft.
void physicallyAddingRemoteModelFailed(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft, bool disabled, bool requestFailover, const swift::misc::CStatusMessage &message)
Adding the remote model failed.
void rememberElevationAndSimulatorCG(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, bool likelyOnGroundElevation, const swift::misc::geo::CElevationPlane &elevation, const swift::misc::physical_quantities::CLength &simulatorCG)
Set elevation and CG in the providers and for auto publishing.
bool isAircraftInRangeOrTestMode(const swift::misc::aviation::CCallsign &callsign) const
Test version aware version of isAircraftInRange.
void finishUpdateRemoteAircraftAndSetStatistics(qint64 startTime, bool limited=false)
Update stats and flags.
bool isTestMode() const
Test mode? (driver can skip code parts etc., driver dependent)
void debugLogMessage(const QString &msg)
Display a debug log message based on swift::misc::simulation::CInterpolationAndRenderingSetup remark ...
void emitSimulatorCombinedStatus(SimulatorStatus oldStatus=Unspecified)
Emit the combined status.
int m_statsUpdateAircraftRuns
statistics update count
swift::misc::simulation::CSimulatedAircraftList m_addAgainAircraftWhenRemoved
add this model again when removed, normally used to change model
swift::misc::simulation::CSimulatorInternals m_simulatorInternals
setup read from the sim
void logAddingAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft) const
Unified qeeing aircraft message.
@ Disconnected
not connected, and hence not simulating/paused
@ Simulating
Is the simulator actually simulating?
swift::misc::simulation::CInterpolationAndRenderingSetupPerCallsign getInterpolationSetupConsolidated(const swift::misc::aviation::CCallsign &callsign, bool forceFullUpdate) const
Consolidate setup with other data like from swift::misc::simulation::IRemoteAircraftProvider.
virtual SimulatorStatus getSimulatorStatus() const
Combined status.
swift::misc::simulation::settings::CSpecializedSimulatorSettings getSimulatorSettings() const
Settings for current simulator.
swift::misc::simulation::CInterpolationLogger m_interpolationLogger
log.interpolation
bool isUpdateAircraftLimitedWithStats(qint64 startTime=-1)
Limited as ISimulator::isUpdateAircraftLimited plus updating statistics.
void safeKillTimer()
Kill timer if id is valid.
void aircraftRenderingChanged(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft rendering changed.
bool isFlightNetworkConnected() const
Is the flight network connected.
virtual bool isShuttingDownOrDisconnected() const
Shutting down or disconnected?
void driverMessages(const swift::misc::CStatusMessageList &messages)
Relevant simulator messages to be explicitly displayed.
swift::misc::aviation::CAircraftSituationPerCallsign m_lastSentSituations
last situations sent to simulator
void rememberLastSent(const swift::misc::aviation::CAircraftSituation &sent)
Remember as last sent.
Interface to a simulator listener.
const swift::misc::simulation::CSimulatorPluginInfo & getPluginInfo() const
Corresponding info.
void simulatorStarted(const swift::misc::simulation::CSimulatorPluginInfo &info)
Emitted when the listener discovers the simulator running.
virtual bool isShuttingDown() const
Overall (swift) application shutting down.
void check()
Check simulator availability.
iterator push_back(const T &value)
Synonym for insert.
const CIdentifier & identifier() const
Get identifier.
Value object encapsulating information identifying a component of a modular distributed swift process...
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
Derived & log(StatusSeverity s, const char16_t(&m)[N])
Set the severity and format string.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
bool contains(const T &object) const
Return true if there is an element equal to given object. Uses the most efficient implementation avai...
void push_back(const T &value)
Appends an element at the end of the sequence.
void clear()
Removes all elements in the sequence.
bool isEmpty() const
Synonym for empty.
Utility methods for simple line parsing used with the command line.
bool toBool(int index, bool def=false) const
Part as bool.
bool matchesPart(int index, const QString &toMatch, Qt::CaseSensitivity cs=Qt::CaseInsensitive) const
Matches given part.
bool hasPart(int index) const
Existing part.
Streamable status message, e.g.
bool isWarningOrAbove() const
Warning or above.
StatusSeverity getSeverity() const
Message severity.
QString getMessage() const
Message.
Status messages, e.g. from Core -> GUI.
CStatusMessage toSingleMessage() const
Merge into a single message.
void setMSecsSinceEpoch(qint64 mSecsSinceEpoch)
Timestamp as ms value.
Value object encapsulating information about aircraft's engines.
Value object encapsulating a list of aircraft engines.
Value object encapsulating information about aircraft's lights.
bool isRecognitionOn() const
Recognition lights on?
bool isCabinOn() const
Cabin lights on?
bool isLandingOn() const
Landing lights on?
bool isBeaconOn() const
Beacon lights on?
bool isNavOn() const
Nac lights on?
bool isLogoOn() const
Logo lights on?
bool isTaxiOn() const
Taxi lights on?
bool isStrobeOn() const
Strobes lights on?
Value object encapsulating information of aircraft's parts.
bool isNull() const
NULL parts object?
CAircraftLights getAdjustedLights() const
Lights adjusted depending on engines.
PartsDetails getPartsDetails() const
Get parts details.
int getFlapsPercent() const
Get flaps position in percent.
Value object encapsulating information of an aircraft's situation.
void setPressureAltitude(const CAltitude &altitude)
Set pressure altitude.
void setGroundSpeed(const physical_quantities::CSpeed &groundspeed)
Set ground speed.
bool setGroundElevation(const aviation::CAltitude &altitude, GndElevationInfo info, bool transferred=false)
Elevation of the ground directly beneath at the given situation.
const CHeading & getHeading() const
Get heading.
void setBank(const physical_quantities::CAngle &bank)
Set bank (angle)
void setHeading(const CHeading &heading)
Set heading.
const CAltitude & geodeticHeight() const
Height, ellipsoidal or geodetic height (used in GPS)
AltitudeCorrection
How was altitude corrected?
bool isOnGroundInfoAvailable() const
On ground info available?
void setAltitude(const CAltitude &altitude)
Set altitude.
bool isPositionNull() const
Position null?
bool isOnGround() const
Is on ground?
CAltitude getCorrectedAltitude(bool enableDragToGround=true, AltitudeCorrection *correction=nullptr) const
Get altitude under consideration of ground elevation and ground flag.
const physical_quantities::CSpeed & getGroundSpeed() const
Get ground speed.
void setOnGroundInfo(const aviation::COnGroundInfo &info)
Set the on ground info.
const CAltitude & getAltitude() const
Get altitude.
void setPitch(const physical_quantities::CAngle &pitch)
Set pitch.
const physical_quantities::CAngle & getBank() const
Get bank (angle)
bool isNull() const
Null situation.
const physical_quantities::CAngle & getPitch() const
Get pitch.
void setVelocity(const CAircraftVelocity &velocity)
Set 6DOF velocity.
bool isMoving() const
Is moving? Means ground speed > epsilon.
void setPosition(const geo::CCoordinateGeodetic &position)
Set position.
List of aircraft situations.
Velocity and angular velocity for 6DOF bodies.
Value object for ICAO classification.
Altitude as used in aviation, can be AGL or MSL altitude.
ReferenceDatum getReferenceDatum() const
Get reference datum (MSL or AGL)
Value object encapsulating information of a callsign.
const QString & asString() const
Get callsign (normalized)
bool isEmpty() const
Is empty?
Value object for a set of callsigns.
QStringList getCallsignStrings(bool sorted=false) const
The callsign strings.
QString getCallsignsAsString(bool sorted=false, const QString &separator=", ") const
Callsigns as string.
void setFrequencyActive(const physical_quantities::CFrequency &frequency)
Set active frequency.
Heading as used in aviation, can be true or magnetic heading.
Value object encapsulating information about an airpot.
swift::misc::physical_quantities::CFrequency getFrequencyStandby() const
Standby frequency.
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
Active frequency.
bool isIdentifying() const
Standby?
bool isInStandby() const
Standby?
bool setTransponderMode(TransponderMode mode)
Set transponder mode.
TransponderMode
Transponder codes.
TransponderMode getTransponderMode() const
Transponder mode.
int removeByCallsigns(const CCallsignSet &callsigns)
Remove all objects with callsigns.
OBJ findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound={}) const
Find the first aircraft by callsign, if none return given one.
int removeByCallsign(const CCallsign &callsign)
Remove all objects with callsign.
swift::misc::aviation::CCallsignSet getCallsigns() const
All callsigns.
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
QStringList getCallsignStrings(bool sorted=false) const
Get callsign string list.
const aviation::CAltitude & geodeticHeight() const
Height, ellipsoidal or geodetic height (used in GPS)
void setLatitude(const CLatitude &latitude)
Set latitude.
void setGeodeticHeight(const aviation::CAltitude &height)
Set height (ellipsoidal or geodetic height)
void setLongitude(const CLongitude &longitude)
Set longitude.
Plane of same elevation, can be a single point or larger area (e.g. airport)
Geodetic coordinate, a position in 3D space relative to the reference geoid.
virtual CLongitude longitude() const =0
Longitude.
virtual bool isNull() const
Is null, means vector x, y, z == 0.
virtual const aviation::CAltitude & geodeticHeight() const =0
Height, ellipsoidal or geodetic height (used in GPS)
bool isGeodeticHeightNull() const
Geodetic height null?
virtual CLatitude latitude() const =0
Latitude.
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information of a text message.
bool isPrivateMessage() const
Is private message?
QString asString(bool withSender, bool withRecipient, const QString &separator=", ") const
Whole message as formatted string. Used to display message in a console window.
bool isRadioMessage() const
Is radio message?
bool isSupervisorMessage() const
Supervisor message?
Value object encapsulating information of a user.
Direct in memory access to client (network client) data.
Physical unit angle (radians, degrees)
Physical unit length (length)
bool isNull() const
Is quantity null?
double value(MU unit) const
Value in given unit.
PQ abs() const
Absolute value (always >=0)
Aircraft model (used by another pilot, my models on disk)
const aviation::CCallsign & getCallsign() const
Corresponding callsign if applicable.
bool hasExistingCorrespondingFile() const
Does the corresponding file exist?
const QString & getModelString() const
Model key, either queried or loaded from simulator model.
CStatusMessageList verifyModelData() const
Verify the model data.
const QString & getFileName() const
File name (corresponding data for simulator, only available if representing simulator model.
bool isSendingGndFlagToSimulator() const
Send GND flag to simulator.
InterpolatorMode getInterpolatorMode() const
Interpolator mode.
bool isForcingFullInterpolation() const
Full interpolation (skip optimizations like checking if aircraft moves etc.)
Value object for interpolator and rendering per callsign.
const CInterpolationStatus & getInterpolationStatus() const
Get status.
const aviation::CAircraftSituation & getInterpolatedSituation() const
Get situation.
const CPartsStatus & getPartsStatus() const
Get status.
bool hasValidSituation() const
Is the corresponding position valid?
bool isInterpolated() const
Did interpolation succeed?
bool updateOwnParts(const aviation::CAircraftParts &parts)
Update own parts.
bool updateOwnCG(const physical_quantities::CLength &cg)
Update own aircraft's CG (aka vertical offset)
bool updateCockpit(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
Update cockpit, but only send signals when applicable.
swift::misc::geo::CCoordinateGeodetic getOwnAircraftPosition() const
Own aircraft's position.
CSimulatedAircraft getOwnAircraft() const
Own aircraft.
bool isReusedParts() const
Is a reused parts object?
bool isSupportingParts() const
Supporting parts.
aviation::CCallsignSet getAircraftInRangeCallsigns() const
Unique callsigns for aircraft in range.
bool isAircraftInRange(const aviation::CCallsign &callsign) const
Is aircraft in range?
bool updateMultipleAircraftEnabled(const aviation::CCallsignSet &callsigns, bool enabledForRendering)
Enable/disable aircraft.
aviation::CAircraftSituationList remoteAircraftSituations(const aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history)
int getAircraftInRangeCount() const
Count remote aircraft.
bool updateAircraftEnabled(const aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
IRemoteAircraftProvider * getRemoteAircraftProvider() const
Get the aircraft provider.
bool updateCGAndModelString(const aviation::CCallsign &callsign, const physical_quantities::CLength &cg, const QString &modelString)
Update the CG and model string.
bool updateAircraftRendered(const aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
Comprehensive information of an aircraft.
bool hasModelString() const
Has model string?
const aviation::CAircraftSituation & getSituation() const
Get situation.
const aviation::CComSystem & getCom2System() const
Get COM2 system.
const aviation::CTransponder & getTransponder() const
Get transponder.
bool setRendered(bool rendered)
Rendered?
const aviation::CCallsign & getCallsign() const
Get callsign.
bool isTerrainProbe() const
Terrain probe?
QString getCallsignAsString() const
Get callsign.
const aviation::CComSystem & getCom1System() const
Get COM1 system.
const QString & getModelString() const
Get model string.
Value object encapsulating a list of aircraft.
bool replaceOrAddByCallsign(const CSimulatedAircraft &aircraft)
Replace or add by callsign.
Simple hardcoded info about the corresponding simulator.
void setValue(const QString &name, const QString &value)
Set value.
Describing a simulator plugin.
const QString & getIdentifier() const
Identifier.
const CSimulatorInfo & getSimulatorInfo() const
Simulator info object.
bool isLogCallsign(const aviation::CCallsign &callsign) const
Is callsign marked for logging.
CInterpolationAndRenderingSetupPerCallsign getInterpolationSetupPerCallsignOrDefault(const aviation::CCallsign &callsign) const
Get the setup for callsign, if not existing the global setup.
Direct threadsafe in memory access to own aircraft.
Direct thread safe in memory access to remote aircraft.
CSimulatorPluginInfo getSimulatorPluginInfo() const
Get the represented plugin.
CSimulatorInfo getSimulatorInfo() const
Get the represented simulator.
QString getSimulatorDetails() const
Simulator details as set from the running simulator.
Utility, providing FS aircraft.cfg entries.
QString getTitlesAsString(bool sorted, const QString &separator=", ") const
All titles as string.
bool containsTitle(const QString &title) const
Can check if a title (model string) is known.
bool isAddingAsSimulatedObjectEnabled() const
Use simulated object adding.
void setSbOffsetsEnabled(bool enable)
Use SB offsets?
void setAddingAsSimulatedObjectEnabled(bool enable)
Use simulated object adding.
bool isSbOffsetsEnabled() const
Are SB offsets enabled.
CFsxP3DSettings getSettings(const CSimulatorInfo &sim) const
Settings per simulator.
CStatusMessage setSettings(const CFsxP3DSettings &settings, const CSimulatorInfo &simulator)
Set settings per simulator.
Allows to have specific utility functions for each simulator.
QStringList getModelDirectoriesOrDefault() const
Model directories or default.
Common base class for MS flight simulators.
swift::misc::aviation::CComSystem m_simCom1
cockpit COM1 state in simulator
swift::misc::aviation::CSelcal m_selcal
SELCAL as in cockpit.
swift::misc::aviation::CComSystem m_simCom2
cockpit COM2 state in simulator
int m_ownAircraftUpdateCycles
own aircraft updates, even with 50 updates/sec long enough even for 32bit
swift::misc::aviation::CTransponder m_simTransponder
cockpit xpdr state in simulator
int m_skipCockpitUpdateCycles
skip some update cycles to allow changes in simulator cockpit to be set
SimObjectRequest
SimObject requests used for AI aircraft and probes.
@ SimObjectEndMarker
end marker, do NOT remove, also means invalid
Request
SimConnect request IDs.
@ RequestEndMarker
free request ids can start here
@ RequestMSFSTransponder
MSFS XPDR mode/ident.
@ RequestSbData
SB client area / XPDR mode.
static const QString & requestToString(Request request)
Request to string.
static HRESULT initDataDefinitionsWhenConnected(const HANDLE hSimConnect, const swift::misc::simulation::CSimulatorInfo &simInfo)
Initialize all data definitions.
static const QString & simObjectRequestToString(SimObjectRequest simObjectRequest)
Request to string.
@ DataRemoteAircraftSetData
set model data such as airline
@ DataClientAreaSbConnected
SB connected with network 0x7b81/1.
@ DataRemoteAircraftSetPosition
the position which will be set
@ DataClientAreaSb
whole SB area, see http://squawkbox.ca/doc/sdk/fsuipc.php
@ DataRemoteAircraftModelData
model data eventually used and reported back from simulator
@ DataClientAreaSbIdent
SB ident single value 0x7b93/19.
@ DataRemoteAircraftGetPosition
get position to evaluate altitude / AGL
@ DataClientAreaSbStandby
SB standby 0x7b91/17.
Class representing a SimConnect object.
bool isPendingAdded() const
Object is requested in simulator, not yet confirmed added.
bool isConfirmedAdded() const
Adding is confirmed.
DWORD getObjectId() const
Get SimConnect object id.
QString toQString() const
SimObject as string.
bool hasValidRequestAndObjectId() const
Was the object really added to simulator.
bool hasCurrentLightsInSimulator() const
Received lights in simulator.
bool isPending() const
Pending added or removed?
bool isRemovedWhileAdding() const
Special states.
const swift::misc::simulation::CSimulatedAircraft & getAircraft() const
Simulated aircraft (as added)
static SimObjectType requestIdToType(DWORD requestId)
Type of id.
static const QString & typeToString(SimObjectType type)
Type to string.
DWORD getRequestId() const
Get SimConnect request id.
const swift::misc::aviation::CCallsign & getCallsign() const
Get callsign.
SIMCONNECT_PERIOD getSimDataPeriod() const
How often do we request data from simulator for this remote aircraft.
void setRemovedWhileAdding(bool removedWhileAdding)
Special states.
bool isTerrainProbe() const
Probe?
bool isPendingRemoved() const
Removing is pending.
void setPendingRemoved(bool pending)
Marked as pending for removal.
bool removeByOtherSimObject(const CSimConnectObject &otherSimObj)
Remove by object id or request id.
int countPendingAdded() const
Number of pending added.
swift::misc::aviation::CCallsignSet getAllCallsigns(bool withoutProbes=true) const
Get all callsigns.
CSimConnectObject getSimObjectForObjectId(DWORD objectId) const
Get object per object id.
bool insert(const CSimConnectObject &simObject, bool updateTimestamp=false)
Insert.
CSimConnectObject getSimObjectForOtherSimObject(const CSimConnectObject &otherSimObj) const
Get by request or object id, just as possible.
bool setSimConnectObjectIdForRequestId(DWORD requestId, DWORD objectId)
Set ID of a SimConnect object, so far we only have an request id in the object.
CSimConnectObject getOldestNotPendingProbe() const
Get a non pending probe.
swift::misc::aviation::CCallsignSet getPendingAddedCallsigns() const
Callsigns of pending added callsigns.
CSimConnectObject getOldestObject() const
Get the oldest object.
QString getAllCallsignStringsAsString(bool sorted=false, const QString &separator=", ") const
Get all callsign strings as string.
bool containsPendingAdded() const
Pending add condition.
int removeAllProbes()
Remove all the probes.
int removeCallsigns(const swift::misc::aviation::CCallsignSet &callsigns)
Remove callsigns.
QList< CSimConnectObject > getProbes() const
All probes.
CSimConnectObjects removeOutdatedPendingAdded(CSimConnectObject::SimObjectType type)
Remove all pending added objects.
QStringList getAllCallsignStrings(bool sorted=false, bool withoutProbes=true) const
Get all callsign strings.
FSX Simulator Implementation.
bool isUsingFsxTerrainProbe() const
FSX Terrain probe.
virtual bool updateOwnSimulatorSelcal(const swift::misc::aviation::CSelcal &selcal, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
virtual bool isPhysicallyRenderedAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is the aircraft rendered (displayed in simulator)? This shall only return true if the aircraft is rea...
virtual void setTrueAltitude(swift::misc::aviation::CAircraftSituation &aircraftSituation, const swift::simplugin::fsxcommon::DataDefinitionOwnAircraft &simulatorOwnAircraft)
Customization point for adjusting altitude to compensate for temperature effect.
virtual void displayTextMessage(const swift::misc::network::CTextMessage &message) const
Display a text message.
virtual swift::misc::CStatusMessageList debugVerifyStateAfterAllAircraftRemoved() const
Debug function to check state after all aircraft have been removed.
SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForSimObjTerrainProbe()
Get new request id, overflow safe.
static bool isValid180Deg(double deg)
Valid 180degrees value.
bool removeSimObjectForTrace(const TraceFsxSendId &trace)
Remove the CSimConnectObject linked in the trace.
virtual void setFlightNetworkConnected(bool connected)
Flight network has been connected.
int m_addedProbes
added probes
CSimConnectObjects m_simConnectObjects
AI objects and their object and request ids.
swift::misc::physical_quantities::CLength m_altitudeDelta
FS2020 effect of temperature on altitude.
QMap< DWORD, swift::misc::aviation::CCallsign > m_pendingProbeRequests
pending elevation requests: requestId/aircraft callsign
static QString fsxCharToQString(const char *fsxChar, int size=-1)
Encapsulates creating QString from FSX string data.
static SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const swift::misc::geo::ICoordinateGeodetic &coordinate)
Format conversion.
virtual bool requestElevation(const swift::misc::geo::ICoordinateGeodetic &reference, const swift::misc::aviation::CCallsign &aircraftCallsign)
Request elevation, there is no guarantee the requested elevation will be available in the provider.
static bool isRequestForSimObjTerrainProbe(DWORD requestId)
Request for probe (elevation)?
virtual void displayStatusMessage(const swift::misc::CStatusMessage &message) const
Display a status message in the simulator.
void setTractingSendId(bool trace)
Set tracing on/off.
HRESULT logAndTraceSendId(HRESULT hr, const QString &warningMsg, const QString &functionName, const QString &functionDetails={})
Trace if required, log errors.
virtual void removeCamera(CSimConnectObject &simObject)
Remove camera if any.
virtual int physicallyRemoveAllRemoteAircraft()
Remove all remote aircraft and their data via ISimulator::clearAllRemoteAircraftData.
HANDLE m_hSimConnect
handle to SimConnect object
void setUsingSbOffsetValues(bool use)
Use SB offset values.
virtual bool physicallyAddRemoteAircraft(const swift::misc::simulation::CSimulatedAircraft &newRemoteAircraft)
Add new remote aircraft physically to the simulator.
SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForSimObjAircraft()
Get new request id, overflow safe.
DispatchProc m_dispatchProc
called function for dispatch, can be overriden by specialized P3D function
virtual ~CSimulatorFsxCommon()
Destructor.
virtual void removeObserver(CSimConnectObject &simObject)
Remove observer if any.
virtual void initSimulatorInternals()
Init the internal objects.
virtual bool testSendSituationAndParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CAircraftParts &parts)
Send situation/parts for testing.
virtual bool releaseAIControl(const CSimConnectObject &simObject, SIMCONNECT_DATA_REQUEST_ID requestId)
Release AI control.
virtual HRESULT initEventsP3D()
Specific P3D events.
virtual bool disconnectFrom()
Disconnect from simulator.
swift::misc::aviation::CCallsign getCallsignForPendingProbeRequests(DWORD requestId, bool remove)
Callsign for pending request.
bool isAddingAsSimulatedObjectEnabled() const
Allow adding as simulated object instead of non ATC.
void setAddingAsSimulatedObjectEnabled(bool enabled)
Allow adding as simulated object instead of non ATC.
virtual void onOwnModelChanged(const swift::misc::simulation::CAircraftModel &newModel)
Own model has been changed.
virtual swift::misc::aviation::CCallsignSet physicallyRenderedAircraft() const
Physically rendered (displayed in simulator) This shall only return aircraft handled in the simulator...
virtual bool isConnected() const
Are we connected to the simulator?
virtual void resetAircraftStatistics()
Reset the statistics.
virtual bool isSimulating() const
Simulator running?
static SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const swift::misc::aviation::CAircraftSituation &situation, bool sendGnd=true, bool forceUnderflowDetection=false, swift::misc::CStatusMessage *details=nullptr)
Format conversion.
bool m_initFsxTerrainProbes
initialized terrain probes
static CSimConnectDefinitions::SimObjectRequest requestToSimObjectRequest(DWORD requestId)
Sub request type.
virtual QString getStatisticsSimulatorSpecific() const
Allows to print out simulator specific statistics.
static SIMCONNECT_DATA_LATLONALT coordinateToFsxLatLonAlt(const swift::misc::geo::ICoordinateGeodetic &coordinate)
Format conversion.
virtual bool updateOwnSimulatorCockpit(const swift::misc::simulation::CSimulatedAircraft &ownAircraft, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
bool triggerAutoTraceSendId(qint64 traceTimeMs=AutoTraceOffsetMs)
Trigger tracing ids for some while.
static void registerHelp()
Register help.
static bool isRequestForSimObjAircraft(DWORD requestId)
Request for sim data (request in range of sim data)?
bool m_useFsxTerrainProbe
Use FSX Terrain probe?
bool isTracingSendId() const
Tracing right now?
virtual void timerEvent(QTimerEvent *event)
Timer event (our SimConnect event loop), runs dispatch.
static QByteArray toFsxChar(const QString &string)
Convert to FSX char array.
virtual bool connectTo()
Connect to simulator.
virtual void reset()
Full reset of state.
bool isValidSimObjectNotPendingRemoved(const CSimConnectObject &simObject) const
Valid CSimConnectObject which is NOT pendig removed.
static bool isValidFsxPosition(const SIMCONNECT_DATA_INITPOSITION &fsxPos)
Valid FSX/P3D position.
virtual void clearAllRemoteAircraftData()
Clear all aircraft related data, but do not physically remove the aircraft.
virtual swift::misc::CStatusMessageList getInterpolationMessages(const swift::misc::aviation::CCallsign &callsign) const
Interpolation messages for callsign.
CSimConnectObject getSimObjectForTrace(const TraceFsxSendId &trace) const
CSimConnectObject for trace.
static SIMCONNECT_DATA_PBH aircraftSituationToFsxPBH(const swift::misc::aviation::CAircraftSituation &situation)
Format conversion.
virtual bool physicallyRemoveRemoteAircraft(const swift::misc::aviation::CCallsign &callsign)
Remove remote aircraft from simulator.
virtual void startImpl()
Plugin specific implementation to start listener.
CSimulatorFsxCommonListener(const swift::misc::simulation::CSimulatorPluginInfo &info)
Constructor.
virtual void stopImpl()
Plugin specific implementation to stop listener.
virtual void checkImpl()
Plugin specific implementation to check.
virtual QString backendInfo() const
Info about the backend system (if available)
virtual bool parseDetails(const swift::misc::CSimpleCommandParser &parser)
Backend services of the swift project, like dealing with the network or the simulators.
Free functions in swift::misc.
SWIFT_MISC_EXPORT const QString & boolToOnOff(bool v)
Bool to on/off.
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
SWIFT_MISC_EXPORT const QString & boolToEnabledDisabled(bool v)
Bool to enabled/disabled.
QByteArray & append(QByteArrayView data)
const char * constData() const const
qsizetype size() const const
qint64 currentMSecsSinceEpoch()
QDateTime fromMSecsSinceEpoch(qint64 msecs)
QString toString(QStringView format) const const
qint64 elapsed() const const
bool contains(const Key &key) const const
bool isEmpty() const const
QList< Key > keys() const const
bool remove(const Key &key)
T value(const Key &key) const const
QList< T > values() const const
QMap< Key, T >::iterator insert(QMap< Key, T >::const_iterator pos, const Key &key, const T &value)
QMap< Key, T >::size_type remove(const Key &key)
T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
void setObjectName(QAnyStringView name)
int startTimer(int interval, Qt::TimerType timerType)
QThread * thread() const const
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
QString left(qsizetype n) &&
QString number(double n, char format, int precision)
QByteArray toLatin1() const const
QString toLower() const const
QString trimmed() const const
QString join(QChar separator) const const
const std::string & boolToYesNo(bool t)
Yes/no from bool.
void setInterval(int msec)
bool isActive() const const
unsigned long DWORD
Fake Windows DWORD.
HRESULT s_ok()
Correctly casted values/checks.
bool isFailure(HRESULT result)
Correctly casted values/checks.
bool dtb(double doubleBool)
Correctly casted values/checks.
EventIds
SimConnect Event IDs.
adding struct SIMCONNECT_DATA_PBH not existing in SimConnect FSX
QString errorMsg
error message if any
Data structure for MSFS transponder mode information.
double transponderMode
transponder state simvar
Data struct of our own aircraft.
double rotationVelocityBodyX
Rotation Velocity Body X.
double lightBeacon
Is beacon light on?
double lightNav
Is nav light on?
double velocity
Ground velocity.
double lightLogo
Is logo light on?
double velocityWorldY
Velocity World Y.
double com2ActiveMHz
COM2 active frequency.
double engine1RpmPct
Engine 1 RPM [%].
double engine2Combustion
Engine 2 combustion flag.
double latitudeDeg
Latitude (deg)
double simOnGround
Is aircraft on ground?
double altitudeFt
Altitude (ft)
double comTransmit1
COM1 transmit, means also receiving.
double comReceiveAll
all COMs receiving, or COM:x transmitting or receiving
double engine3RpmPct
Engine 3 RPM [%].
double comStatus1
COM1 status.
double comStatus2
COM2 status.
double engine4RpmPct
Engine 4 RPM [%]g.
double comTransmit2
COM2 transmit, means also receiving.
double flapsHandlePosition
Flaps handle position in percent.
double com2StandbyMHz
COM2 standby frequency.
double elevationFt
Elevation (ft)
double pressureAltitudeM
Pressure altitude (m)
double trueHeadingDeg
True heading (deg)
double rotationVelocityBodyZ
Rotation Velocity Body Z.
double spoilersHandlePosition
Spoilers out? (flag)
double velocityWorldX
Velocity World X.
double comTest1
COM1 test.
double rotationVelocityBodyY
Rotation Velocity Body Y.
double com1ActiveMHz
COM1 active frequency.
double lightLanding
Is landing light on?
double engine1Combustion
Engine 1 combustion flag.
double pitchDeg
Pitch (deg)
double engine2RpmPct
Engine 2 RPM [%].
double lightTaxi
Is taxi light on?
double numberOfEngines
Number of engines.
double velocityWorldZ
Velocity World Z.
double cgToGroundFt
Static CG to ground (ft)
double com1StandbyMHz
COM1 standby frequency.
double engine4Combustion
Engine 4 combustion flag.
double longitudeDeg
Longitude (deg)
double gearHandlePosition
Gear handle position (flag)
double comTest2
COM2 test.
double engine3Combustion
Engine 3 combustion flag.
double lightStrobe
Is strobe light on?
double transponderCode
Transponder Code.
Struct to trace send ids.
static const TraceFsxSendId & invalid()
Invalid object.
CSimConnectObject simObject
CSimConnectObject at the time of the trace.
#define SWIFT_AUDIT_X(COND, WHERE, WHAT)
A weaker kind of verify.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.