swift
contextnetworkimpl.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QStringBuilder>
7 #include <QTimer>
8 
9 #include "config/buildconfig.h"
10 #include "core/airspaceanalyzer.h"
11 #include "core/airspacemonitor.h"
12 #include "core/application.h"
16 #include "core/corefacade.h"
17 #include "core/fsd/fsdclient.h"
18 #include "core/webdataservices.h"
22 #include "misc/aviation/callsign.h"
24 #include "misc/dbusserver.h"
25 #include "misc/logcategories.h"
26 #include "misc/logmessage.h"
30 #include "misc/pq/constants.h"
31 #include "misc/pq/frequency.h"
32 #include "misc/pq/time.h"
33 #include "misc/pq/units.h"
34 #include "misc/sequence.h"
37 #include "misc/stringutils.h"
38 
39 using namespace swift::config;
40 using namespace swift::misc;
41 using namespace swift::misc::physical_quantities;
42 using namespace swift::misc::aviation;
43 using namespace swift::misc::network;
44 using namespace swift::misc::geo;
45 using namespace swift::misc::simulation;
46 using namespace swift::misc::weather;
47 using namespace swift::core::fsd;
48 using namespace swift::core::vatsim;
49 
50 namespace swift::core::context
51 {
52  CContextNetwork::CContextNetwork(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime)
53  : IContextNetwork(mode, runtime)
54  {
56  Q_ASSERT(this->getRuntime());
57  Q_ASSERT(this->getIContextOwnAircraft());
60 
61  // 1. Init by "network driver"
62  m_fsdClient = new CFSDClient(this, // client provider
63  this->getRuntime()->getCContextOwnAircraft(), // own aircraft provider
64  this, // remote aircraft provider
65  this); // thread owner
66  m_fsdClient->start(); // FSD thread
67  connect(m_fsdClient, &CFSDClient::connectionStatusChanged, this, &CContextNetwork::onFsdConnectionStatusChanged,
69  connect(m_fsdClient, &CFSDClient::killRequestReceived, this, &CContextNetwork::kicked, Qt::QueuedConnection);
70  connect(m_fsdClient, &CFSDClient::textMessagesReceived, this, &CContextNetwork::onTextMessagesReceived,
72  connect(m_fsdClient, &CFSDClient::textMessageSent, this, &CContextNetwork::onTextMessageSent,
74  connect(m_fsdClient, &CFSDClient::severeNetworkError, this, &CContextNetwork::severeNetworkError,
76  connect(m_fsdClient, &CFSDClient::muteRequestReceived, this, &CContextNetwork::muteRequestReceived,
78 
79  // 2. Update timer for data (network data such as frequency)
80  // we use 2 timers so we can query at different times (not too many queirs at once)
81  m_requestAircraftDataTimer = new QTimer(this);
82  connect(m_requestAircraftDataTimer, &QTimer::timeout, this, &CContextNetwork::requestAircraftDataUpdates);
83  m_requestAircraftDataTimer->start(30 * 1000);
84  m_requestAircraftDataTimer->setObjectName("CContextNetwork::m_requestAircraftDataTimer");
85 
86  m_requestAtisTimer = new QTimer(this);
87  connect(m_requestAtisTimer, &QTimer::timeout, this, &CContextNetwork::requestAtisUpdates);
88  m_requestAtisTimer->start(13 * 1000); // should not be called at the same time as above
89  m_requestAtisTimer->setObjectName("CContextNetwork::m_requestAtisTimer");
90 
91  // 3. send staggered model matching signals, to avoid to many matchings at the same time
92  m_staggeredMatchingTimer = new QTimer(this);
93  connect(m_staggeredMatchingTimer, &QTimer::timeout, this, &CContextNetwork::emitReadyForMatching);
94  m_staggeredMatchingTimer->start(200);
95  m_staggeredMatchingTimer->setObjectName("CContextNetwork::m_staggeredMatchingTimer");
96 
97  // 4. Airspace contents
98  Q_ASSERT_X(this->getRuntime()->getCContextOwnAircraft(), Q_FUNC_INFO,
99  "this and own aircraft context must be local");
100  Q_ASSERT_X(this->getRuntime()->getCContextSimulator(), Q_FUNC_INFO,
101  "this and own simulator context must be local");
102  m_airspace = new CAirspaceMonitor(this->getRuntime()->getCContextOwnAircraft(),
103  this->getRuntime()->getCContextSimulator(), m_fsdClient, this);
104  m_fsdClient->setClientProvider(m_airspace);
112  Qt::QueuedConnection); // DBus
114  &CContextNetwork::onReadyForModelMatching); // intentionally NOT QueuedConnection
117  connect(m_airspace, &CAirspaceMonitor::changedAtisReceived, this, &CContextNetwork::onChangedAtisReceived,
119  }
120 
122  {
123  if (this->canUseAirspaceMonitor()) { m_airspace->setSimulationEnvironmentProvider(provider); }
124  if (this->canUseFsd()) { m_fsdClient->setSimulationEnvironmentProvider(provider); }
125  }
126 
128 
130  {
131  if (!this->canUseAirspaceMonitor()) { return {}; }
132  return m_airspace->remoteAircraftSituations(callsign);
133  }
134 
136  {
137  if (!this->canUseAirspaceMonitor()) { return {}; }
138  return m_airspace->remoteAircraftSituation(callsign, index);
139  }
140 
143  {
144  if (!this->canUseAirspaceMonitor()) { return {}; }
145  return m_airspace->remoteAircraftSituationsTimestampDifferenceMinMaxMean(callsign);
146  }
147 
149  {
150  if (!this->canUseAirspaceMonitor()) { return {}; }
151  return m_airspace->latestRemoteAircraftSituations();
152  }
153 
155  {
156  Q_ASSERT(m_airspace);
157  return m_airspace->latestOnGroundProviderElevations();
158  }
159 
161  {
162  if (!this->canUseAirspaceMonitor()) { return {}; }
163  return m_airspace->remoteAircraftParts(callsign);
164  }
165 
167  {
168  if (!this->canUseAirspaceMonitor()) { return 0; }
169  return m_airspace->remoteAircraftPartsCount(callsign);
170  }
171 
173  {
174  if (!this->canUseAirspaceMonitor()) { return 0; }
175  return m_airspace->remoteAircraftSituationsCount(callsign);
176  }
177 
179  {
180  if (!this->canUseAirspaceMonitor()) { return false; }
181  return m_airspace->isRemoteAircraftSupportingParts(callsign);
182  }
183 
185  {
186  if (!this->canUseAirspaceMonitor()) { return {}; }
187  return m_airspace->remoteAircraftSupportingParts();
188  }
189 
191  {
192  if (!this->canUseAirspaceMonitor()) { return {}; }
193  return m_airspace->remoteAircraftSituationChanges(callsign);
194  }
195 
197  {
198  if (!this->canUseAirspaceMonitor()) { return {}; }
199  return m_airspace->remoteAircraftSituationChangesCount(callsign);
200  }
201 
203  QObject *receiver, std::function<void(const CAircraftSituation &)> situationSlot,
204  std::function<void(const CCallsign &, const CAircraftParts &)> partsSlot,
205  std::function<void(const CCallsign &)> removedAircraftSlot,
206  std::function<void(const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
207  {
208  Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace");
209  return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot,
210  aircraftSnapshotSlot);
211  }
212 
214  {
215  this->disconnect(); // all signals
216  if (this->isConnected()) { this->disconnectFromNetwork(); }
217  if (m_fsdClient)
218  {
219  m_fsdClient->gracefulShutdown();
220  m_fsdClient->setClientProvider(nullptr);
221  m_fsdClient->deleteLater();
222  m_fsdClient = nullptr;
223  }
224 
225  if (m_airspace)
226  {
227  m_airspace->gracefulShutdown();
228  m_airspace->deleteLater();
229  m_airspace = nullptr;
230  }
231  }
232 
233  CStatusMessage CContextNetwork::connectToNetwork(const CServer &server, const QString &extraLiveryString,
234  bool sendLivery, const QString &extraModelString,
235  bool sendModelString, const CCallsign &partnerCallsign,
236  CLoginMode mode)
237  {
238  if (!this->canUseFsd())
239  {
241  u"Invalid FSD state (shutdown)") };
242  }
243  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
244 
245  QString msg;
246  if (!server.getUser().hasCredentials())
247  {
249  u"Invalid user credentials");
250  }
251  if (!this->ownAircraft().getAircraftIcaoCode().hasDesignator())
252  {
254  u"Invalid ICAO data for own aircraft");
255  }
256  if (!CNetworkUtils::canConnect(server, msg, 5000)) { return { CStatusMessage::SeverityError, msg }; }
257  if (m_fsdClient->isConnected())
258  {
260  u"Already connected");
261  }
262  if (this->isPendingConnection())
263  {
265  u"Pending connection, please wait");
266  }
267 
269  const CSimulatedAircraft ownAircraft(this->ownAircraft());
270  m_fsdClient->setPartnerCallsign(
271  isValidPartnerCallsign(ownAircraft.getCallsign(), partnerCallsign) ? partnerCallsign : CCallsign());
272 
273  // Fall back to observer mode, if no simulator is available or not simulating
274  if (!CBuildConfig::isLocalDeveloperDebugBuild() && !this->getIContextSimulator()->isSimulatorSimulating())
275  {
276  CLogMessage(this).info(
277  u"No simulator connected or connected simulator not simulating. Falling back to observer mode");
278  mode.setLoginMode(CLoginMode::Observer);
279  }
280 
281  const CSimulatorInfo sim = this->getIContextSimulator() ?
283  CSimulatorInfo();
284  const QString l =
285  extraLiveryString.isEmpty() ? ownAircraft.getModel().getSwiftLiveryString(sim) : extraLiveryString;
286  const QString m = extraModelString.isEmpty() ? ownAircraft.getModelString() : extraModelString;
287 
288  // FG fix, do not send livery and model ids for FlightGear
289  // https://discordapp.com/channels/539048679160676382/567091362030419981/698124094482415616
290  if (sim.isFG() && extraModelString.isEmpty()) { sendModelString = false; }
291 
292  m_currentMode = mode;
293  m_fsdClient->setLoginMode(mode);
294  m_fsdClient->setCallsign(ownAircraft.getCallsign());
295 
296  // set this BEFORE model string as FG has different handling
297  m_fsdClient->setSimType(sim);
298 
299  m_fsdClient->setIcaoCodes(ownAircraft);
300  m_fsdClient->setLiveryAndModelString(l, sendLivery, m, sendModelString);
301  m_fsdClient->setClientName(sApp->swiftVersionChar());
302  m_fsdClient->setVersion(CBuildConfig::getVersion().majorVersion(), CBuildConfig::getVersion().minorVersion());
303 
304 #ifdef SWIFT_VATSIM_SUPPORT
305  int clientId = 0;
306  QString clientKey;
307  if (!getCmdLineClientIdAndKey(clientId, clientKey))
308  {
309  clientId = CBuildConfig::vatsimClientId();
310  clientKey = CBuildConfig::vatsimPrivateKey();
311  }
312 
313  m_fsdClient->setClientIdAndKey(static_cast<quint16>(clientId), clientKey.toLocal8Bit());
314 #endif
315  m_fsdClient->setClientCapabilities(Capabilities::AircraftInfo | Capabilities::FastPos | Capabilities::VisPos |
316  Capabilities::AtcInfo | Capabilities::AircraftConfig |
317  Capabilities::IcaoEquipment);
318  m_fsdClient->setServer(server);
319 
320  m_fsdClient->setPilotRating(PilotRating::Student);
321  m_fsdClient->setAtcRating(AtcRating::Observer);
322 
323  m_fsdClient->connectToServer();
325  u"Connection pending " % server.getAddress() % u' ' % QString::number(server.getPort()));
326  }
327 
329  {
330  if (!this->canUseFsd()) { return {}; }
331  return this->isConnected() ? m_fsdClient->getServer() : CServer();
332  }
333 
335  {
336  if (!this->canUseFsd()) { return {}; }
337  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
338  return m_fsdClient->getLoginMode();
339  }
340 
342  {
343  if (!this->canUseFsd())
344  {
346  u"Invalid FSD state (shutdown)") };
347  }
348  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
349  if (m_fsdClient->isConnected() || m_fsdClient->isPendingConnection())
350  {
351  m_fsdClient->disconnectFromServer();
353  u"Connection terminating");
354  }
355  else
356  {
358  u"Already disconnected");
359  }
360  }
361 
363  {
364  if (!this->canUseFsd()) { return false; }
365  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
366  return m_fsdClient->isConnected();
367  }
368 
370  {
371  if (!this->canUseFsd()) { return false; }
372  return m_fsdClient->isPendingConnection();
373  }
374 
375  bool CContextNetwork::parseCommandLine(const QString &commandLine, const CIdentifier &originator)
376  {
377  Q_UNUSED(originator;)
378 
379  if (!this->canUseAirspaceMonitor()) { return false; }
380  if (!this->canUseFsd()) { return false; }
381  if (commandLine.isEmpty()) { return false; }
382 
383  static const QStringList cmds({ ".msg", ".m", ".chat", ".altos", ".altoffset", ".addtimeos", ".addtimeoffset",
384  ".wallop", ".reinit", ".reinitialize", ".enable", ".disable", ".ignore",
385  ".unignore", ".fsd" });
386  CSimpleCommandParser parser(cmds);
387  parser.parse(commandLine);
388  if (!parser.isKnownCommand()) { return false; }
389  if (parser.matchesCommand(".msg", ".m", ".chat"))
390  {
391  if (!this->getIContextNetwork() || !this->getIContextNetwork()->isConnected())
392  {
393  CLogMessage(this).validationError(u"Network needs to be connected");
394  return false;
395  }
396  else if (!this->getIContextOwnAircraft())
397  {
398  CLogMessage(this).validationError(u"No own aircraft data, no text message can be sent");
399  return false;
400  }
401  if (parser.countParts() < 3)
402  {
403  CLogMessage(this).validationError(u"Incorrect message");
404  return false;
405  }
406 
407  // set receiver
408  const CSimulatedAircraft ownAircraft(this->getIContextOwnAircraft()->getOwnAircraft());
409  const QString receiver = parser.part(1).trimmed().toLower(); // receiver
410  CCallsign ownCallsign = ownAircraft.getCallsign();
411  if (m_fsdClient)
412  {
413  // override with the preset callsign, as the own callsign can be different for partner callsign
414  // scenarios copilot scenarios
415  const CCallsign presetCallsign = m_fsdClient->getPresetCallsign();
416  if (!presetCallsign.isEmpty()) { ownCallsign = presetCallsign; }
417  }
418 
419  if (ownCallsign.isEmpty())
420  {
421  CLogMessage(this).validationError(u"No own callsign");
422  return false;
423  }
424 
425  CTextMessage tm;
426  tm.setSenderCallsign(ownCallsign);
427 
428  // based on the CPZ bug
429  // https://discordapp.com/channels/539048679160676382/539486309882789888/576765888401768449 no longer use
430  // starts/ends with
431  if (receiver == QStringView(u"c1") || receiver == QStringView(u"com1") || receiver == QStringView(u"comm1"))
432  {
433  tm.setFrequency(ownAircraft.getCom1System().getFrequencyActive());
434  }
435  else if (receiver == QStringView(u"c2") || receiver == QStringView(u"com2") ||
436  receiver == QStringView(u"comm2"))
437  {
438  tm.setFrequency(ownAircraft.getCom2System().getFrequencyActive());
439  }
440  else if (receiver == "u" || receiver == QStringView(u"uni") || receiver == QStringView(u"unicom"))
441  {
442  tm.setFrequency(CPhysicalQuantitiesConstants::FrequencyUnicom());
443  }
444  else
445  {
446  const CFrequency radioFrequency =
447  CComSystem::parseComFrequency(receiver, CPqString::SeparatorBestGuess);
448  if (!radioFrequency.isNull())
449  {
450  if (CComSystem::isValidCivilAviationFrequency(radioFrequency)) { tm.setFrequency(radioFrequency); }
451  else
452  {
453  CLogMessage(this).validationError(u"Wrong COM frequency for text message");
454  return false;
455  }
456  }
457  else
458  {
459  const CCallsign toCallsign(receiver);
460  tm.setRecipientCallsign(toCallsign);
461  }
462  }
463 
464  const QString msg(parser.partAndRemainingStringAfter(2));
465  tm.setMessage(msg);
466  if (tm.isEmpty())
467  {
468  CLogMessage(this).validationError(u"No text message body");
469  return false;
470  }
471  CTextMessageList tml(tm);
472  this->sendTextMessages(tml);
473  return true;
474  }
475  else if (parser.matchesCommand(".altos", ".altoffset"))
476  {
477  if (!m_airspace) { return false; }
478  if (parser.countParts() < 2) { return false; }
479 
480  const QString csPart(parser.part(1));
481  CCallsign cs;
482  if (csPart.contains('?'))
483  {
485  }
486  else
487  {
488  cs = CCallsign(csPart);
489  if (!m_airspace->isAircraftInRange(cs))
490  {
491  CLogMessage(this).validationError(u"Altitude offset unknown callsign");
492  return false;
493  }
494  }
495 
496  CLength os(CLength::null());
497  if (parser.hasPart(2)) { os.parseFromString(parser.part(2), CPqString::SeparatorBestGuess); }
498 
499  const bool added = this->testAddAltitudeOffset(cs, os);
500  if (added)
501  {
502  CLogMessage(this).info(u"Added altitude offset %1 for %2")
503  << os.valueRoundedWithUnit(2) << cs.asString();
504  }
505  else { CLogMessage(this).info(u"Removed altitude offset %1") << cs.asString(); }
506 
507  return true;
508  }
509  else if (parser.matchesCommand(".addtimeos", ".addtimeoffset"))
510  {
511  if (!m_airspace) { return false; }
512  if (parser.countParts() < 2) { return false; }
513 
514  CTime os(CTime::null());
515  if (parser.hasPart(2)) { os.parseFromString(parser.part(2), CPqString::SeparatorBestGuess); }
516 
517  if (!os.isNull() && os.isPositiveWithEpsilonConsidered())
518  {
519  const qint64 ost = os.valueInteger(CTimeUnit::ms());
520  CLogMessage(this).info(u"Added add offset time %1ms") << ost;
521  }
522  else { CLogMessage(this).info(u"Reset add. time offset"); }
523  }
524  else if (parser.matchesCommand(".reinit", ".reinitialize"))
525  {
526  if (!m_airspace) { return false; }
527  const int count = m_airspace->reInitializeAllAircraft();
528  if (count > 0) { CLogMessage(this).info(u"Re-init %1 aircraft") << count; }
529  }
530  else if (parser.matchesCommand(".wallop"))
531  {
532  if (parser.countParts() < 2) { return false; }
533  if (!m_fsdClient) { return false; }
534  if (!this->isConnected())
535  {
536  CLogMessage(this).validationError(u"Network needs to be connected");
537  return false;
538  }
539  const QString wallopMsg = parser.partAndRemainingStringAfter(1);
540  if (wallopMsg.isEmpty())
541  {
542  CLogMessage(this).validationError(u"No wallop message body");
543  return false;
544  }
545  m_fsdClient->sendTextMessage(TextMessageGroups::AllSups, wallopMsg);
546  return true;
547  }
548  else if (parser.matchesCommand(".enable", ".unignore"))
549  {
550  if (parser.countParts() < 2) { return false; }
551  if (!m_fsdClient) { return false; }
552  if (!this->isConnected()) { return false; }
553  const CCallsign cs(parser.part(1));
554  if (cs.isValid()) { this->updateAircraftEnabled(cs, true); }
555  }
556  else if (parser.matchesCommand(".disable", ".ignore"))
557  {
558  if (parser.countParts() < 2) { return false; }
559  if (!m_fsdClient) { return false; }
560  if (!this->isConnected()) { return false; }
561  const CCallsign cs(parser.part(1));
562  if (cs.isValid()) { this->updateAircraftEnabled(cs, false); }
563  }
564  else if (m_airspace && parser.matchesCommand(".fsd"))
565  {
566  return m_airspace->parseCommandLine(commandLine, originator);
567  }
568 
569  return false;
570  }
571 
573  {
574  if (this->isDebugEnabled())
575  {
576  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages;
577  }
578  m_fsdClient->sendTextMessages(textMessages);
579  }
580 
582  {
583  if (this->isDebugEnabled())
584  {
585  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << flightPlan;
586  }
587  m_fsdClient->sendFlightPlan(flightPlan);
588  m_fsdClient->sendClientQueryFlightPlan(this->ownAircraft().getCallsign());
589  }
590 
592  {
593  if (!this->canUseFsd()) { return {}; }
594  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
595  return m_airspace->loadFlightPlanFromNetwork(callsign);
596  }
597 
599  {
600  if (!this->canUseAirspaceMonitor()) { return {}; }
601  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
602  return m_airspace->getUsers();
603  }
604 
606  {
607  if (!this->canUseAirspaceMonitor() || callsigns.isEmpty()) { return {}; }
608  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
609  return m_airspace->getUsersForCallsigns(callsigns);
610  }
611 
613  {
614  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
615  CCallsignSet callsigns;
616  callsigns.push_back(callsign);
617  const CUserList users = this->getUsersForCallsigns(callsigns);
618  if (users.isEmpty()) { return {}; }
619  return users[0];
620  }
621 
623  {
624  if (!this->canUseAirspaceMonitor()) { return {}; }
625  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
626  return m_airspace->getClients();
627  }
628 
630  {
631  if (!this->canUseAirspaceMonitor()) { return {}; }
632  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
633  return m_airspace->getClientsForCallsigns(callsigns);
634  }
635 
637  {
638  if (!this->canUseAirspaceMonitor()) { return false; }
639  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
640  return m_airspace->setOtherClient(client);
641  }
642 
644  {
645  if (!this->canUseAirspaceMonitor()) { return 0; }
646  return m_airspace->removeClient(callsign);
647  }
648 
650  {
651  if (!this->canUseAirspaceMonitor()) { return false; }
652  return m_airspace->autoAdjustCientGndCapability(situation);
653  }
654 
656  {
657  if (!this->canUseAirspaceMonitor()) { return false; }
658  return m_airspace->addClientGndCapability(callsign);
659  }
660 
661  bool CContextNetwork::setClientGndCapability(const aviation::CCallsign &callsign, bool supportGndFlag)
662  {
663  if (!this->canUseAirspaceMonitor()) { return false; }
664  return m_airspace->setClientGndCapability(callsign, supportGndFlag);
665  }
666 
667  void CContextNetwork::markAsSwiftClient(const CCallsign &callsign) { m_airspace->markAsSwiftClient(callsign); }
668 
670  {
671  Q_ASSERT_X(sApp->getWebDataServices(), Q_FUNC_INFO, "Missing data reader");
672  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
674  }
675 
676  void CContextNetwork::onFsdConnectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
677  {
678  // if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << from
679  // << to; }
680 
681  if (to.isDisconnected())
682  {
683  // make sure airspace is really cleaned up
684  Q_ASSERT(m_airspace);
685  m_airspace->clear();
686  }
687 
688  // send 1st position
689  if (to.isConnected())
690  {
691  CLogMessage(this).info(u"Connected, own aircraft %1") << this->ownAircraft().getCallsignAsString();
692 
693  if (m_fsdClient)
694  {
695  const CServer server = m_fsdClient->getServer();
696  emit this->connectedServerChanged(server);
697  }
698  }
699 
700  // send as message
701  static const QString chgMsg("Connection status changed from '%1' to '%2'");
702  CLogMessage(this).info(chgMsg) << from.toQString() << to.toQString();
703 
704  // send as own signal
705  emit this->connectionStatusChanged(from, to);
706  }
707 
708  void CContextNetwork::onReadyForModelMatching(const CSimulatedAircraft &aircraft)
709  {
710  m_readyForModelMatching.enqueue(aircraft);
711  }
712 
713  void CContextNetwork::emitReadyForMatching()
714  {
715  if (m_readyForModelMatching.isEmpty()) { return; }
716  if (!sApp || sApp->isShuttingDown()) { return; }
717 
718  const CSimulatedAircraft aircraft = m_readyForModelMatching.dequeue();
719  if (!this->isAircraftInRange(aircraft.getCallsign())) { return; }
720  emit this->readyForModelMatching(aircraft);
721  }
722 
723  void CContextNetwork::createRelayMessageToPartnerCallsign(const CTextMessage &textMessage,
724  const CCallsign &partnerCallsign,
725  CTextMessageList &relayedMessages)
726  {
727  if (textMessage.isEmpty()) { return; }
728  if (partnerCallsign.isEmpty()) { return; }
729  if (textMessage.getSenderCallsign() == partnerCallsign) { return; } // no round trips
730 
731  CTextMessage modified(textMessage);
732  modified.makeRelayedMessage(partnerCallsign);
733  relayedMessages.push_back(modified);
734  }
735 
736  void CContextNetwork::xCtxSimulatorRenderRestrictionsChanged(bool restricted, bool enabled, int maxAircraft,
737  const CLength &maxRenderedDistance)
738  {
739  // mainly passing changed restrictions from simulator to network
740  if (!m_airspace) { return; }
741  if (!m_airspace->analyzer()) { return; }
742  m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, enabled, maxAircraft,
743  maxRenderedDistance);
744  }
745 
746  void CContextNetwork::xCtxSimulatorStatusChanged(int status)
747  {
748  const ISimulator::SimulatorStatus simStatus = static_cast<ISimulator::SimulatorStatus>(status);
749  if (ISimulator::isAnyConnectedStatus(simStatus))
750  {
752  this->setSimulationEnvironmentProvider(sim ? sim->simulator() : nullptr);
753  const CSimulatorInfo simInfo = sim ? sim->getSimulatorPluginInfo().getSimulatorInfo() : CSimulatorInfo();
754 
755  m_simulatorConnected++;
756  m_lastConnectedSim = simInfo;
757  }
758  else { this->setSimulationEnvironmentProvider(nullptr); }
759  }
760 
761  bool CContextNetwork::canUseFsd() const { return sApp && !sApp->isShuttingDown() && m_fsdClient; }
762 
763  bool CContextNetwork::canUseAirspaceMonitor() const { return sApp && !sApp->isShuttingDown() && m_airspace; }
764 
765  void CContextNetwork::updateMetars(const CMetarList &metars)
766  {
767  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
768  CLogMessage(this).info(u"%1 METARs updated") << metars.size();
769  }
770 
771  void CContextNetwork::onChangedAtisReceived(const CCallsign &callsign)
772  {
773  Q_UNUSED(callsign)
774  m_dsAtcStationsOnlineChanged.inputSignal(); // the ATIS data are stored in the station object
775  }
776 
777  void CContextNetwork::onTextMessagesReceived(const CTextMessageList &messages)
778  {
779  if (messages.isEmpty()) { return; }
780 
781  const CCallsign partnerCallsign = this->getPartnerCallsign();
782  const CCallsign ownCallsign = this->ownAircraft().getCallsign();
783 
784  CTextMessageList textMessages = messages.withRelayedToPrivateMessages();
785  CTextMessageList partnerMessages;
786 
787  if (!partnerCallsign.isEmpty())
788  {
789  partnerMessages = textMessages.findBySender(partnerCallsign);
790  const CTextMessageList relayedSentMessages =
791  partnerMessages.findByNotForRecipient(ownCallsign).markedAsSent();
792  partnerMessages =
793  partnerMessages.findByRecipient(ownCallsign); // really send to me as PM and not a forwared one
794 
795  // avoid infinite rountrips
796  textMessages = textMessages.withRemovedPrivateMessagesFromCallsign(partnerCallsign);
797 
798  // fake those as sent by myself
799  for (const CTextMessage &rsm : relayedSentMessages) { emit this->textMessageSent(rsm); }
800  }
801 
802  // 1) relayed messaged "now look like PMs"
803  // 2) all messaged of partner are EXCLUDED
804  if (!textMessages.isEmpty()) { emit this->textMessagesReceived(textMessages); }
805  if (!partnerMessages.isEmpty()) { emit this->textMessagesReceived(partnerMessages); }
806 
807  if (textMessages.containsPrivateMessages())
808  {
809  const CTextMessageList supMessages(messages.getSupervisorMessages());
810  for (const CTextMessage &m : supMessages) { emit this->supervisorTextMessageReceived(m); }
811 
812  // part to send to partner, "forward/relay" to partner
813  if (!partnerCallsign.isEmpty())
814  {
815  // IMPORTANT: partner messages already received
816  CTextMessageList relayedMessages;
817  const CTextMessageList privateMessages = messages.getPrivateMessages();
818  for (const CTextMessage &m : privateMessages)
819  {
820  this->createRelayMessageToPartnerCallsign(m, partnerCallsign, relayedMessages);
821  }
822 
823  if (!relayedMessages.isEmpty())
824  {
825  QPointer<CContextNetwork> myself(this);
826  QTimer::singleShot(10, this, [=] {
827  if (myself) { myself->sendTextMessages(relayedMessages); }
828  });
829  }
830  } // relay to partner
831  }
832  }
833 
834  void CContextNetwork::onTextMessageSent(const CTextMessage &message)
835  {
836  if (message.isEmpty()) { return; }
837  if (message.isRelayedMessage()) { return; }
838 
839  if (message.isPrivateMessage())
840  {
841  // forward messages which are NO real PMs tp the partner
842  const CCallsign partnerCallsign = this->getPartnerCallsign();
843  if (!partnerCallsign.isEmpty() && message.getRecipientCallsign() != partnerCallsign)
844  {
845  QPointer<CContextNetwork> myself(this);
846  CTextMessageList relayedMessages;
847  this->createRelayMessageToPartnerCallsign(message, partnerCallsign, relayedMessages);
848  if (!relayedMessages.isEmpty())
849  {
850  QTimer::singleShot(10, this, [=] {
851  if (myself) { myself->sendTextMessages(relayedMessages); }
852  });
853  }
854  }
855  }
856 
857  emit this->textMessageSent(message);
858  }
859 
860  CSimulatedAircraft CContextNetwork::ownAircraft() const
861  {
862  Q_ASSERT(this->getRuntime()); // must never be null
863 
864  if (!this->getRuntime()->getIContextOwnAircraft()) { return {}; }
865  return this->getRuntime()->getCContextOwnAircraft()->getOwnAircraft();
866  }
867 
869  {
870  return m_fsdClient ? m_fsdClient->getPresetPartnerCallsign() : CCallsign();
871  }
872 
873  bool CContextNetwork::isValidPartnerCallsign(const CCallsign &ownCallsign, const CCallsign &partnerCallsign)
874  {
875  if (partnerCallsign.isEmpty()) { return false; }
876  if (ownCallsign == partnerCallsign) { return false; } // MUST NOT be the same
877  return true;
878  }
879 
881  {
882  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
883  CAtcStationList stations = m_airspace->getAtcStationsOnline();
884  if (!recalculateDistance || !this->getIContextOwnAircraft()) { return stations; }
886  this->getIContextOwnAircraft()->getOwnAircraftSituation());
887  return stations;
888  }
889 
891  {
892  if (!this->getIContextOwnAircraft()) { return {}; }
893  const CAircraftSituation ownSituation = this->getIContextOwnAircraft()->getOwnAircraftSituation();
894  const CAtcStationList stations = m_airspace->getAtcStationsOnline().findClosest(number, ownSituation);
895  return stations;
896  }
897 
899  {
900  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
901  return m_airspace->getAircraftInRange();
902  }
903 
905  {
906  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
907  return m_airspace->getAircraftInRangeCallsigns();
908  }
909 
911  {
912  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
913  return m_airspace->getAircraftInRangeCount();
914  }
915 
916  bool CContextNetwork::isAircraftInRange(const CCallsign &callsign) const
917  {
918  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
919  return m_airspace->isAircraftInRange(callsign);
920  }
921 
922  bool CContextNetwork::isVtolAircraft(const CCallsign &callsign) const
923  {
924  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
925  return m_airspace->isVtolAircraft(callsign);
926  }
927 
929  {
930  if (this->isDebugEnabled())
931  {
932  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
933  }
934  return m_airspace->getAircraftInRangeForCallsign(callsign);
935  }
936 
938  {
939  if (this->isDebugEnabled())
940  {
941  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
942  }
943  return m_airspace->getAircraftInRangeModelForCallsign(callsign);
944  }
945 
947  {
948  if (this->isDebugEnabled())
949  {
950  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
951  }
952  return m_airspace->getReverseLookupMessages(callsign);
953  }
954 
956  {
957  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
958  return m_airspace->isReverseLookupMessagesEnabled();
959  }
960 
961  void CContextNetwork::enableReverseLookupMessages(ReverseLookupLogging enable)
962  {
963  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << enable; }
964  const ReverseLookupLogging revEnabled = m_airspace->isReverseLookupMessagesEnabled();
965  if (revEnabled == enable) { return; }
966  m_airspace->enableReverseLookupMessages(enable);
968  }
969 
971  {
972  if (this->isDebugEnabled())
973  {
974  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
975  }
976  return m_airspace->getAircraftPartsHistory(callsign);
977  }
978 
980  {
981  if (this->isDebugEnabled())
982  {
983  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
984  }
985  return m_airspace->remoteAircraftParts(callsign);
986  }
987 
989  {
990  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
991  return m_airspace->getRemoteAircraftSupportingPartsCount();
992  }
993 
995  {
996  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
997  return m_airspace->isAircraftPartsHistoryEnabled();
998  }
999 
1001  {
1002  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << enabled; }
1003  m_airspace->enableAircraftPartsHistory(enabled);
1005  }
1006 
1008  {
1009  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1010  return m_airspace->aircraftSituationsAdded();
1011  }
1012 
1014  {
1015  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1016  return m_airspace->aircraftPartsAdded();
1017  }
1018 
1020  {
1021  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1022  return m_airspace->situationsLastModified(callsign);
1023  }
1024 
1025  qint64 CContextNetwork::partsLastModified(const CCallsign &callsign) const
1026  {
1027  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1028  return m_airspace->partsLastModified(callsign);
1029  }
1030 
1032  {
1033  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1034  if (!m_fsdClient) { return {}; }
1035  return m_fsdClient->getNetworkStatisticsAsText(reset, separator);
1036  }
1037 
1039  {
1040  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1041  if (!m_fsdClient) { return false; }
1042  return m_fsdClient->setStatisticsEnable(enabled);
1043  }
1044 
1045  bool CContextNetwork::testAddAltitudeOffset(const CCallsign &callsign, const CLength &offset)
1046  {
1047  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1048  return m_airspace->testAddAltitudeOffset(callsign, offset);
1049  }
1050 
1052  {
1053  if (!m_fsdClient) { return {}; }
1054  return m_fsdClient->getPresetValues();
1055  }
1056 
1058  {
1059  if (this->isDebugEnabled())
1060  {
1061  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1062  }
1063  return m_airspace->getAtcStationsOnline().findFirstByCallsign(callsign);
1064  }
1065 
1067  {
1068  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1069  return m_airspace->getAtcStationsOnline().findIfFrequencyIsWithinSpacing(frequency);
1070  }
1071 
1072  bool CContextNetwork::isOnlineStation(const CCallsign &callsign) const
1073  {
1074  if (this->isDebugEnabled())
1075  {
1076  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1077  }
1078  return m_airspace->getAtcStationsOnline().containsCallsign(callsign);
1079  }
1080 
1082  {
1083  if (!canUseAirspaceMonitor()) { return; }
1084  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1085  if (!this->isConnected()) { return; }
1086 
1087  m_airspace->requestAircraftDataUpdates();
1088  if (m_requestAircraftDataTimer) { m_requestAircraftDataTimer->start(); } // restart
1089  }
1090 
1092  {
1093  if (!canUseAirspaceMonitor()) { return; }
1094  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1095  if (!this->isConnected()) { return; }
1096 
1097  m_airspace->requestAtisUpdates();
1098  if (m_requestAtisTimer) { m_requestAtisTimer->start(); } // restart
1099  }
1100 
1101  bool CContextNetwork::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering)
1102  {
1103  if (!canUseAirspaceMonitor()) { return false; }
1104  if (this->isDebugEnabled())
1105  {
1106  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << enabledForRendering;
1107  }
1108  const bool c = m_airspace->updateAircraftEnabled(callsign, enabledForRendering);
1109  if (c)
1110  {
1111  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1112  Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1113  emit this->changedRemoteAircraftEnabled(aircraft);
1114  }
1115  return c;
1116  }
1117 
1118  bool CContextNetwork::setAircraftEnabledFlag(const CCallsign &callsign, bool enabledForRendering)
1119  {
1120  if (!canUseAirspaceMonitor()) { return false; }
1121  if (this->isDebugEnabled())
1122  {
1123  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1124  }
1125  return m_airspace->setAircraftEnabledFlag(callsign, enabledForRendering);
1126  }
1127 
1129  const CIdentifier &originator)
1130  {
1131  if (!canUseAirspaceMonitor()) { return false; }
1132  if (this->isDebugEnabled())
1133  {
1134  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1135  }
1136  const bool c = m_airspace->updateAircraftModel(callsign, model, originator);
1137  if (c)
1138  {
1139  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1140  Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1141  emit this->changedRemoteAircraftModel(aircraft, originator); // update aircraft model
1142  }
1143  return c;
1144  }
1145 
1147  const CIdentifier &originator)
1148  {
1149  if (!canUseAirspaceMonitor()) { return false; }
1150  if (this->isDebugEnabled())
1151  {
1152  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1153  }
1154  const bool c = m_airspace->updateAircraftNetworkModel(callsign, model, originator);
1155  if (c)
1156  {
1157  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1158  emit this->changedRemoteAircraftModel(aircraft, originator); // updated network model
1159  }
1160  return c;
1161  }
1162 
1163  bool CContextNetwork::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates)
1164  {
1165  if (!canUseAirspaceMonitor()) { return false; }
1166  if (this->isDebugEnabled())
1167  {
1169  << Q_FUNC_INFO << callsign << enableFastPositonUpdates;
1170  }
1171  const bool c = m_airspace->updateFastPositionEnabled(callsign, enableFastPositonUpdates);
1172  if (c)
1173  {
1174  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1175  CLogMessage(this).info(u"Callsign '%1' fast positions '%2'")
1176  << aircraft.getCallsign() << swift::misc::boolToOnOff(aircraft.fastPositionUpdates());
1177  emit this->changedFastPositionUpdates(aircraft);
1178  }
1179  return c;
1180  }
1181 
1182  bool CContextNetwork::updateAircraftSupportingGndFLag(const CCallsign &callsign, bool supportGndFlag)
1183  {
1184  if (this->isDebugEnabled())
1185  {
1186  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << supportGndFlag;
1187  }
1188  const bool c = m_airspace->setClientGndCapability(callsign, supportGndFlag);
1189  if (c)
1190  {
1191  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1192  CLogMessage(this).info(u"Callsign '%1' set gnd.capability: %2")
1193  << aircraft.getCallsign() << boolToOnOff(aircraft.isSupportingGndFlag());
1194  emit this->changedGndFlagCapability(aircraft);
1195  }
1196  return c;
1197  }
1198 
1199  bool CContextNetwork::updateCG(const aviation::CCallsign &callsign, const CLength &cg)
1200  {
1201  if (!canUseAirspaceMonitor()) { return false; }
1202  if (this->isDebugEnabled())
1203  {
1205  << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1);
1206  }
1207  const bool c = m_airspace->updateCG(callsign, cg);
1208  return c;
1209  }
1210 
1212  {
1213  if (!canUseAirspaceMonitor()) { return {}; }
1214  if (this->isDebugEnabled())
1215  {
1217  << Q_FUNC_INFO << modelString << cg.valueRoundedWithUnit(1);
1218  }
1219  const CCallsignSet set = m_airspace->updateCGForModel(modelString, cg);
1220  return set;
1221  }
1222 
1224  const QString &modelString)
1225  {
1226  if (!canUseAirspaceMonitor()) { return false; }
1227  if (this->isDebugEnabled())
1228  {
1230  << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1) << modelString;
1231  }
1232  const bool c = m_airspace->updateCGAndModelString(callsign, cg, modelString);
1233  return c;
1234  }
1235 
1236  bool CContextNetwork::updateAircraftRendered(const CCallsign &callsign, bool rendered)
1237  {
1238  if (!canUseAirspaceMonitor()) { return false; }
1239  const bool c = m_airspace->updateAircraftRendered(callsign, rendered);
1240  return c;
1241  }
1242 
1244  {
1245  if (!canUseAirspaceMonitor()) { return 0; }
1246  const int c = m_airspace->updateMultipleAircraftRendered(callsigns, rendered);
1247  return c;
1248  }
1249 
1251  {
1252  if (!canUseAirspaceMonitor()) { return 0; }
1253  const int c = m_airspace->updateMultipleAircraftEnabled(callsigns, enabled);
1254  return c;
1255  }
1256 
1259  bool *setForOnGroundPosition)
1260  {
1261  if (!canUseAirspaceMonitor()) { return 0; }
1262  return m_airspace->updateAircraftGroundElevation(callsign, elevation, info, setForOnGroundPosition);
1263  }
1264 
1266  {
1267  if (!canUseAirspaceMonitor()) { return; }
1268  m_airspace->updateMarkAllAsNotRendered();
1269  }
1270 
1272  {
1273  if (!canUseAirspaceMonitor()) { return {}; }
1274  return m_airspace->getCGFromDB(callsign);
1275  }
1276 
1278  {
1279  if (!canUseAirspaceMonitor()) { return {}; }
1280  return m_airspace->getCGFromDB(modelString);
1281  }
1282 
1283  void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const CCallsign &callsign)
1284  {
1285  if (!canUseAirspaceMonitor()) { return; }
1286  m_airspace->rememberCGFromDB(cgFromDB, callsign);
1287  }
1288 
1289  void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const QString &modelString)
1290  {
1291  if (!canUseAirspaceMonitor()) { return; }
1292  m_airspace->rememberCGFromDB(cgFromDB, modelString);
1293  }
1294 
1296  {
1297  if (!canUseAirspaceMonitor()) { return 0; }
1298  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1299  return m_airspace->reInitializeAllAircraft();
1300  }
1301 
1303  {
1304  if (!canUseAirspaceMonitor()) { return {}; }
1305  return m_airspace->getLatestAirspaceAircraftSnapshot();
1306  }
1307 
1309  const CLength &range, int minValues,
1310  int sufficientValues) const
1311  {
1312  if (!canUseAirspaceMonitor()) { return {}; }
1313  return m_airspace->averageElevationOfNonMovingAircraft(reference, range, minValues, sufficientValues);
1314  }
1315 
1316  void CContextNetwork::setClients(const CClientList &clients) { m_airspace->setClients(clients); }
1317 
1319 
1321  {
1322  if (!canUseAirspaceMonitor()) { return {}; }
1323  return m_airspace->getClientOrDefaultForCallsign(callsign);
1324  }
1325 
1327  {
1328  if (!canUseAirspaceMonitor()) { return false; }
1329  return m_airspace->hasClientInfo(callsign);
1330  }
1331 
1333  {
1334  if (!canUseAirspaceMonitor()) { return false; }
1335  return m_airspace->addNewClient(client);
1336  }
1337 
1339  bool skipEqualValues)
1340  {
1341  if (!canUseAirspaceMonitor()) { return 0; }
1342  return m_airspace->updateOrAddClient(callsign, vm, skipEqualValues);
1343  }
1344 
1346  {
1347  if (this->isDebugEnabled())
1348  {
1349  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsigns;
1350  }
1351  Q_ASSERT(m_fsdClient);
1352  m_fsdClient->setInterimPositionReceivers(callsigns);
1353  }
1354 
1356  {
1357  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1358  Q_ASSERT(m_fsdClient);
1359  return m_fsdClient->getInterimPositionReceivers();
1360  }
1361 
1363  {
1364  if (!this->canUseFsd()) { return; }
1365  if (this->isDebugEnabled())
1366  {
1367  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1368  }
1369  m_fsdClient->sendClientQueryAircraftConfig(callsign);
1370  }
1371 
1373  {
1374  if (!this->canUseAirspaceMonitor()) { return; }
1375  if (this->isDebugEnabled())
1376  {
1377  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << number;
1378  }
1379  m_airspace->testCreateDummyOnlineAtcStations(number);
1380  }
1381 
1382  void CContextNetwork::testAddAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool incremental)
1383  {
1384  if (!this->canUseAirspaceMonitor()) { return; }
1385  if (this->isDebugEnabled())
1386  {
1387  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << parts << incremental;
1388  }
1389  m_airspace->testAddAircraftParts(callsign, parts, incremental);
1390  }
1391 
1393  {
1394  if (!this->canUseFsd()) { return; }
1395  if (this->isDebugEnabled())
1396  {
1397  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign.asString();
1398  }
1399  emit this->fsdClient()->atisReplyReceived(callsign, msg);
1400  }
1401 
1403  {
1404  if (!this->canUseFsd()) { return; }
1405  if (this->isDebugEnabled())
1406  {
1407  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages.toQString();
1408  }
1409  emit this->fsdClient()->textMessagesReceived(textMessages);
1410  }
1411 
1413  {
1414  if (this->isDebugEnabled())
1415  {
1416  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << airportIcaoCode;
1417  }
1418  if (!sApp || !sApp->getWebDataServices()) { return {}; }
1419  return sApp->getWebDataServices()->getMetarForAirport(airportIcaoCode);
1420  }
1421 
1424  {
1425  Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
1426 
1427  // bind does not allow to define connection type, so we use receiver as workaround
1428  const QMetaObject::Connection uc; // unconnected
1429  const QMetaObject::Connection c = rawFsdMessageReceivedSlot ? connect(m_fsdClient, &CFSDClient::rawFsdMessage,
1430  receiver, rawFsdMessageReceivedSlot) :
1431  uc;
1432  Q_ASSERT_X(c || !rawFsdMessageReceivedSlot, Q_FUNC_INFO, "connect failed");
1433  return c;
1434  }
1435 } // namespace swift::core::context
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
void setSimulatorRenderRestrictionsChanged(bool restricted, bool enabled, int maxAircraft, const swift::misc::physical_quantities::CLength &maxRenderedDistance)
Render restrictions in simulator.
Keeps track of other entities in the airspace: aircraft, ATC stations, etc. Central instance of data ...
misc::network::CUserList getUsers() const
Returns the list of users we know about.
void requestAtisUpdates()
Request to update ATC stations' ATIS data from the network.
misc::aviation::CAtcStationList getAtcStationsOnline() const
Returns the current online ATC stations.
void atcStationDisconnected(const swift::misc::aviation::CAtcStation &station)
ATC station disconnected.
misc::network::CUserList getUsersForCallsigns(const misc::aviation::CCallsignSet &callsigns) const
Returns a list of the users corresponding to the given callsigns.
void requestAircraftDataUpdates()
Request to update other clients' data from the network.
misc::aviation::CFlightPlan loadFlightPlanFromNetwork(const misc::aviation::CCallsign &callsign)
Returns the loaded flight plan for the given callsign.
CAirspaceAnalyzer * analyzer() const
Analyzer.
void readyForModelMatching(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
Ready for model matching.
void changedAtisReceived(const swift::misc::aviation::CCallsign &callsign)
An ATIS has been received.
void changedAtcStationsOnline()
Online ATC stations were changed.
int reInitializeAllAircraft()
Re-init all aircrft.
void clear()
Clear the contents.
void gracefulShutdown()
Gracefully shut down, e.g. for thread safety.
bool updateFastPositionEnabled(const misc::aviation::CCallsign &callsign, bool enableFastPositonUpdates)
Members not implenented or fully implenented by CRemoteAircraftProvider.
misc::simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const
Members not implenented or fully implenented by CRemoteAircraftProvider.
const char * swiftVersionChar()
swift info string
bool isShuttingDown() const
Is application shutting down?
CWebDataServices * getWebDataServices() const
Get the web data services.
ContextMode
How to handle a given context.
The class providing facades (the contexts) for all DBus relevant operations.
Definition: corefacade.h:57
context::CContextSimulator * getCContextSimulator()
Context for simulator.
Definition: corefacade.cpp:509
context::CContextOwnAircraft * getCContextOwnAircraft()
Context for own aircraft.
Definition: corefacade.cpp:495
swift::misc::network::CServerList getVatsimFsdServers() const
FSD servers.
swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &icao) const
Get METAR for airport.
static bool isAnyConnectedStatus(SimulatorStatus status)
Any connected status?
Definition: simulator.cpp:603
void rememberCGFromDB(const swift::misc::physical_quantities::CLength &cgFromDB, const swift::misc::aviation::CCallsign &callsign)
CG values from DB.
bool setNetworkStatisticsEnable(bool enabled)
Statistics enable/disable.
swift::misc::aviation::CCallsignSet updateCGForModel(const QString &modelString, const swift::misc::physical_quantities::CLength &cg)
Update the CG for this model string.
fsd::CFSDClient * fsdClient() const
Network library.
swift::misc::network::CLoginMode getLoginMode() const
Login mode.
void markAsSwiftClient(const swift::misc::aviation::CCallsign &callsign)
Mark as other swift client.
swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &airportIcaoCode) const
Get METAR, if not available request it (code such as EDDF, KLAX)
swift::misc::CStatusMessageList getAircraftPartsHistory(const swift::misc::aviation::CCallsign &callsign) const
Get aircraft parts history.
void setFastPositionEnabledCallsigns(swift::misc::aviation::CCallsignSet &callsigns)
Callsigns enabled for fast position updates.
int updateMultipleAircraftRendered(const swift::misc::aviation::CCallsignSet &callsigns, bool rendered)
Set aircraft rendered.
swift::misc::MillisecondsMinMaxMean remoteAircraftSituationsTimestampDifferenceMinMaxMean(const swift::misc::aviation::CCallsign &callsign) const
Average update time.
swift::misc::aviation::CCallsignSet remoteAircraftSupportingParts() const
Remote aircraft supporting parts.
bool isRemoteAircraftSupportingParts(const swift::misc::aviation::CCallsign &callsign) const
Parts supported?
swift::misc::aviation::CCallsignSet getFastPositionEnabledCallsigns() const
Callsigns enabled for fast position updates.
swift::misc::aviation::CCallsign getPartnerCallsign() const
Partner callsign if any.
swift::misc::aviation::CAircraftPartsList getRemoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
Get remote aircraft parts.
swift::misc::aviation::CAtcStationList getAtcStationsOnline(bool recalculateDistance) const
The ATC list with online ATC controllers.
int updateOrAddClient(const swift::misc::aviation::CCallsign &callsign, const swift::misc::CPropertyIndexVariantMap &vm, bool skipEqualValues=true)
Update or add a client.
bool hasClientInfo(const swift::misc::aviation::CCallsign &callsign) const
Client info for given callsign?
QStringList getNetworkPresetValues() const
Network preset values.
void enableAircraftPartsHistory(bool enabled)
Enable storing of aircraft parts.
int getRemoteAircraftSupportingPartsCount() const
Number of aircraft supporting parts.
qint64 partsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
swift::misc::geo::CElevationPlane averageElevationOfNonMovingAircraft(const swift::misc::aviation::CAircraftSituation &reference, const swift::misc::physical_quantities::CLength &range, int minValues=1, int sufficientValues=2) const
Average elevation of aircraft in given range, which are NOT moving.
swift::misc::aviation::CAircraftSituationList latestOnGroundProviderElevations() const
Latest aircraft situation "on ground" having a provider elevation.
void setClients(const swift::misc::network::CClientList &clients)
Set other clients.
bool updateAircraftEnabled(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
swift::misc::CStatusMessageList getReverseLookupMessages(const swift::misc::aviation::CCallsign &callsign) const
Get reverse lookup messages.
swift::misc::aviation::CAircraftSituationList latestRemoteAircraftSituations() const
Latest aircraft situation for all callsigns.
swift::misc::aviation::CAtcStation getOnlineStationForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign.
bool addClientGndCapability(const swift::misc::aviation::CCallsign &callsign)
Add gnd.flag capability.
int updateAircraftGroundElevation(const swift::misc::aviation::CCallsign &callsign, const swift::misc::geo::CElevationPlane &elevation, swift::misc::aviation::CAircraftSituation::GndElevationInfo info, bool *setForOnGroundPosition)
Update the ground elevation.
swift::misc::CStatusMessage disconnectFromNetwork()
Disconnect from network.
swift::misc::aviation::CAtcStationList getOnlineStationsForFrequency(const swift::misc::physical_quantities::CFrequency &frequency) const
Online stations for frequency.
swift::misc::aviation::CAircraftSituation remoteAircraftSituation(const swift::misc::aviation::CCallsign &callsign, int index) const
Rendered aircraft situations (per callsign and index)
bool isAircraftPartsHistoryEnabled() const
Is storing the aircraft parts history enabled?
swift::misc::network::CClientList getClientsForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Returns a list of other clients corresponding to the given callsigns.
void sendTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Text messages (radio and private chat messages)
int getAircraftInRangeCount() const
Aircraft count.
bool setAircraftEnabledFlag(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Set the enabled flag without any further logic like sending signals.
int removeClient(const swift::misc::aviation::CCallsign &callsign)
Remove client.
swift::misc::network::CUserList getUsers() const
Get all users.
bool setOtherClient(const swift::misc::network::CClient &client)
Set client for its callsign.
void gracefulShutdown()
Gracefully shut down, e.g. for thread safety.
swift::misc::simulation::CSimulatedAircraftList getAircraftInRange() const
Aircraft list.
swift::misc::simulation::CAircraftModel getAircraftInRangeModelForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft model for callsign.
QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
Connect to receive raw fsd messages.
bool isOnlineStation(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign?
swift::misc::network::CServerList getVatsimFsdServers() const
Known FSD servers, available when data file was first read.
swift::misc::CStatusMessage connectToNetwork(const swift::misc::network::CServer &server, const QString &extraLiveryString, bool sendLivery, const QString &extraModelString, bool sendModelString, const swift::misc::aviation::CCallsign &partnerCallsign, swift::misc::network::CLoginMode mode)
Connect to Network.
bool updateAircraftRendered(const swift::misc::aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
void requestAircraftDataUpdates()
Request data updates (pilot's frequencies, ATIS, ..)
int aircraftPartsAdded() const
Number of parts added.
void testAddAircraftParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftParts &parts, bool incremental)
Inject aircraft parts for testing.
bool addNewClient(const swift::misc::network::CClient &client)
Add a new client, if existing nothing will be added.
bool updateAircraftNetworkModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change network model.
QList< QMetaObject::Connection > connectRemoteAircraftProviderSignals(QObject *receiver, std::function< void(const swift::misc::aviation::CAircraftSituation &)> addedSituationSlot, std::function< void(const swift::misc::aviation::CCallsign &, const swift::misc::aviation::CAircraftParts &)> addedPartsSlot, std::function< void(const swift::misc::aviation::CCallsign &)> removedAircraftSlot, std::function< void(const swift::misc::simulation::CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly...
int reInitializeAllAircraft()
Re-initialize all aircraft.
swift::misc::aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes.
void testReceivedTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Inject a text message as received.
swift::misc::network::CUserList getUsersForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Users for given callsigns, e.g. for voice room resolution.
void testCreateDummyOnlineAtcStations(int number)
Create dummy ATC stations for performance tests etc.
swift::misc::physical_quantities::CLength getCGFromDB(const swift::misc::aviation::CCallsign &callsign) const
CG values from DB.
void enableReverseLookupMessages(swift::misc::simulation::ReverseLookupLogging enable)
Enable reverse lookup logging.
bool autoAdjustCientGndCapability(const swift::misc::aviation::CAircraftSituation &situation)
Adjust gnd.flag capability from situation.
swift::misc::aviation::CAtcStationList getClosestAtcStationsOnline(int number) const
The ATC list with online ATC controllers.
bool isAircraftInRange(const swift::misc::aviation::CCallsign &callsign) const
Aircraft in range.
void updateMarkAllAsNotRendered()
Mark all as not rendered.
swift::misc::simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft for given callsign.
void testRequestAircraftConfig(const swift::misc::aviation::CCallsign &callsign)
Request parts for callsign (from another client)
bool updateCGAndModelString(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &cg, const QString &modelString)
Update the CG and model string.
bool isPendingConnection() const
In transition state, e.g. connecting, disconnecting.
swift::misc::aviation::CCallsignSet getAircraftInRangeCallsigns() const
Aircraft callsigns.
swift::misc::network::CClient getClientOrDefaultForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Other client for the given callsigns.
static void registerHelp()
Register help.
bool updateAircraftSupportingGndFLag(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Enable/disable support of gnd. flag.
void sendFlightPlan(const swift::misc::aviation::CFlightPlan &flightPlan)
Send flight plan.
int remoteAircraftSituationsCount(const swift::misc::aviation::CCallsign &callsign) const
Number of remote aircraft situations for callsign.
bool updateFastPositionEnabled(const swift::misc::aviation::CCallsign &callsign, bool enableFastPositonUpdates)
Change fast position updates.
void setSimulationEnvironmentProvider(swift::misc::simulation::ISimulationEnvironmentProvider *provider)
Set the provider.
bool testAddAltitudeOffset(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &offset=swift::misc::physical_quantities::CLength::null())
Add altitude offset for testing.
int remoteAircraftPartsCount(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history)
int updateMultipleAircraftEnabled(const swift::misc::aviation::CCallsignSet &callsigns, bool enabled)
Enable/disable aircraft.
swift::misc::network::CServer getConnectedServer() const
Server which is connected, if not connected empty default object.
int remoteAircraftSituationChangesCount(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes count.
swift::misc::aviation::CFlightPlan loadFlightPlanFromNetwork(const swift::misc::aviation::CCallsign &callsign) const
Load flight plan (from network)
void testReceivedAtisMessage(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &msg)
Inject an ATIS.
bool updateAircraftModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change model.
swift::misc::network::CClientList getClients() const
Get other clients.
swift::misc::simulation::ReverseLookupLogging isReverseLookupMessagesEnabled() const
Enabled reverse lookup logging?
QString getNetworkStatistics(bool reset, const QString &separator)
Statistics info.
swift::misc::simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const
Current snapshot.
swift::misc::aviation::CAircraftSituationList remoteAircraftSituations(const swift::misc::aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history)
qint64 situationsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
bool setClientGndCapability(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Set gnd.flag capability.
swift::misc::network::CUser getUserForCallsign(const swift::misc::aviation::CCallsign &callsign) const
User for given callsign, e.g. for text messages.
int aircraftSituationsAdded() const
Number of situations added.
swift::misc::aviation::CAircraftPartsList remoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history)
bool updateCG(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &cg)
Update the CG.
bool isVtolAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is VTOL aircraft?
bool isConnected() const
Network connected?
void requestAtisUpdates()
Request ATIS updates (for all stations)
swift::misc::simulation::CSimulatedAircraft getOwnAircraft() const
Get own aircraft.
void changedLogOrDebugSettings()
Log or debug values changed.
CCoreFacade * getRuntime()
Runtime.
Definition: context.h:57
bool isUsingImplementingObject() const
Using local implementing object?
Definition: context.h:45
const IContextSimulator * getIContextSimulator() const
Context for simulator.
Definition: context.cpp:69
IContextNetwork * getIContextNetwork()
Context for network.
Definition: context.cpp:29
IContextOwnAircraft * getIContextOwnAircraft()
Context for own aircraft.
Definition: context.cpp:44
bool isDebugEnabled() const
Debug enabled?
Definition: context.cpp:59
void textMessageSent(const swift::misc::network::CTextMessage &sentMessage)
Text message sent (by me)
void changedAircraftInRange()
Aircraft list has been changed.
void supervisorTextMessageReceived(const swift::misc::network::CTextMessage &message)
A supervisor text message was received.
void connectedServerChanged(const swift::misc::network::CServer &server)
The connected server has been changed.
void changedFastPositionUpdates(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft enabled / disabled.
void addedAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
A new aircraft appeared.
void changedGndFlagCapability(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Changed gnd. flag capability.
void muteRequestReceived(bool mute)
Mute request received.
void changedRemoteAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
Aircraft model was changed.
void changedAtcStationsOnline()
ATC station (online) list has been changed.
void textMessagesReceived(const swift::misc::network::CTextMessageList &textMessages)
Text messages received (also private chat messages, radio channel messages)
void kicked(const QString &kickMessage)
User has been kicked from network.
std::function< void(const swift::misc::network::CRawFsdMessage &)> RawFsdMessageReceivedSlot
Raw FSD message receiver functor.
void changedRemoteAircraftEnabled(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft enabled / disabled.
void connectionStatusChanged(const swift::misc::network::CConnectionStatus &from, const swift::misc::network::CConnectionStatus &to)
Connection status changed.
void atcStationDisconnected(const swift::misc::aviation::CAtcStation &atcStation)
ATC station disconnected.
void severeNetworkError(const QString &errorMessage)
Network error.
void readyForModelMatching(const swift::misc::simulation::CSimulatedAircraft &renderedAircraft)
Read for model matching.
void removedAircraft(const swift::misc::aviation::CCallsign &callsign)
An aircraft disappeared.
virtual bool updateOwnAircraftPilot(const swift::misc::network::CUser &pilot)=0
Set current pilot.
virtual swift::misc::aviation::CAircraftSituation getOwnAircraftSituation() const =0
Get own aircraft.
virtual swift::misc::simulation::CSimulatorPluginInfo getSimulatorPluginInfo() const =0
Simulator info, currently loaded plugin.
FSD client Todo: Send (interim) data updates automatically Todo Check ':' in FSD messages....
Definition: fsdclient.h:85
void setCallsign(const swift::misc::aviation::CCallsign &callsign)
Preset functions.
Definition: fsdclient.cpp:160
swift::misc::aviation::CCallsign getPresetPartnerCallsign() const
Partner callsign if any.
Definition: fsdclient.h:181
void setIcaoCodes(const swift::misc::simulation::CSimulatedAircraft &ownAircraft)
Preset functions.
Definition: fsdclient.cpp:170
void textMessagesReceived(const swift::misc::network::CTextMessageList &messages)
Client responses received.
void sendFlightPlan(const swift::misc::aviation::CFlightPlan &flightPlan)
Definition: fsdclient.cpp:669
bool isConnected() const
Connection status.
Definition: fsdclient.h:254
void setAtcRating(AtcRating rating)
Preset functions.
Definition: fsdclient.h:150
void sendTextMessages(const swift::misc::network::CTextMessageList &messages)
Definition: fsdclient.cpp:568
bool isPendingConnection() const
Connection status.
Definition: fsdclient.cpp:2113
swift::misc::aviation::CCallsign getPresetCallsign() const
Callsign if any.
Definition: fsdclient.h:173
void setLoginMode(const swift::misc::network::CLoginMode &mode)
Preset functions.
Definition: fsdclient.h:129
swift::misc::aviation::CCallsignSet getInterimPositionReceivers() const
Interim pos.receivers.
Definition: fsdclient.cpp:2103
void setClientName(const QString &clientName)
Preset functions.
Definition: fsdclient.h:102
void gracefulShutdown()
Gracefully shut down FSD client.
Definition: fsdclient.cpp:2191
void setServer(const swift::misc::network::CServer &server)
Preset functions.
Definition: fsdclient.cpp:141
void setClientCapabilities(Capabilities capabilities)
Preset functions.
Definition: fsdclient.h:123
void setLiveryAndModelString(const QString &livery, bool sendLiveryString, const QString &modelString, bool sendModelString)
Preset functions.
Definition: fsdclient.cpp:189
void setPartnerCallsign(const swift::misc::aviation::CCallsign &callsign)
Preset functions.
Definition: fsdclient.h:135
const swift::misc::network::CServer & getServer() const
Get the server.
Definition: fsdclient.h:161
swift::misc::network::CLoginMode getLoginMode() const
Mode.
Definition: fsdclient.h:189
void disconnectFromServer()
Connect/disconnect.
Definition: fsdclient.cpp:264
bool setStatisticsEnable(bool enabled)
Statistics enable functions.
Definition: fsdclient.h:261
void atisReplyReceived(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &atis)
We received a reply to one of our ATIS queries.
void setInterimPositionReceivers(const swift::misc::aviation::CCallsignSet &interimPositionReceivers)
Interim pos.receivers.
Definition: fsdclient.cpp:2108
QStringList getPresetValues() const
List of all preset values.
Definition: fsdclient.cpp:218
void setPilotRating(PilotRating rating)
Preset functions.
Definition: fsdclient.h:145
void setSimType(const swift::misc::simulation::CSimulatorInfo &simInfo)
Preset functions.
Definition: fsdclient.cpp:199
void sendClientQueryAircraftConfig(const swift::misc::aviation::CCallsign &callsign)
Definition: fsdclient.cpp:485
void sendTextMessage(const swift::misc::network::CTextMessage &message)
Definition: fsdclient.cpp:614
void setVersion(int major, int minor)
Preset functions.
Definition: fsdclient.h:112
void sendClientQueryFlightPlan(const swift::misc::aviation::CCallsign &callsign)
Definition: fsdclient.cpp:480
void connectToServer()
Connect/disconnect.
Definition: fsdclient.cpp:230
QString getNetworkStatisticsAsText(bool reset, const QString &separator="\n")
Text statistics.
Definition: fsdclient.cpp:2145
bool isEmpty() const
Synonym for empty.
Definition: collection.h:191
iterator push_back(const T &value)
Synonym for insert.
Definition: collection.h:238
void start(QThread::Priority priority=QThread::InheritPriority)
Starts a thread and moves the worker into it.
Definition: worker.cpp:165
void inputSignal()
Received input signal, or manually trigger.
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition: identifier.h:29
static const QString & contextSlot()
Context slots.
Definition: logcategories.h:87
static const QString & validation()
Validation.
Definition: logcategories.h:38
Class for emitting a log message.
Definition: logmessage.h:27
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, providing a format string, and adding the validation category.
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Specialized value object compliant map for variants, based on indexes.
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition: sequence.h:305
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Utility methods for simple line parsing used with the command line.
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityInfo
Status severities.
constexpr static auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
bool hasDesignator() const
Aircraft designator?
Value object encapsulating information of aircraft's parts.
Definition: aircraftparts.h:26
Value object encapsulating a list of aircraft parts.
Value object encapsulating a list of aircraft parts.
Value object encapsulating information of an aircraft's situation.
GndElevationInfo
Where did we get elevation from?
Value object encapsulating information of airport ICAO data.
Value object encapsulating information about an ATC station.
Definition: atcstation.h:38
Value object for a list of ATC stations.
CAtcStationList findIfFrequencyIsWithinSpacing(const physical_quantities::CFrequency &frequency)
Find 0..n stations with frequency (with 5 kHz spacing for .x20/.x25 and .x70/.x75)
Value object encapsulating information of a callsign.
Definition: callsign.h:30
const QString & asString() const
Get callsign (normalized)
Definition: callsign.h:96
bool isEmpty() const
Is empty?
Definition: callsign.h:63
bool isValid() const
Valid callsign?
Definition: callsign.cpp:359
Value object for a set of callsigns.
Definition: callsignset.h:26
Value object for a flight plan.
Definition: flightplan.h:148
Value object encapsulating information message (ATIS, METAR, TAF)
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
Active frequency.
Definition: modulator.cpp:30
OBJ findFirstByCallsign(const CCallsign &callsign, const OBJ &ifNotFound={}) const
Find the first aircraft by callsign, if none return given one.
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
Plane of same elevation, can be a single point or larger area (e.g. airport)
CONTAINER findClosest(int number, const ICoordinateGeodetic &coordinate) const
Find 0..n objects closest to the given coordinate.
void calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position)
Calculate distances.
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
void setClientProvider(CClientProvider *provider)
Provider.
Another client software.
Definition: client.h:27
Value object encapsulating a list of voice rooms.
Definition: clientlist.h:27
int removeClient(const aviation::CCallsign &callsign)
Remove client.
int updateOrAddClient(const aviation::CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues=true)
Update or add a client.
bool hasClientInfo(const aviation::CCallsign &callsign) const
Client info for given callsign?
bool addClientGndCapability(const aviation::CCallsign &callsign)
Add gnd.flag capability.
CClientList getClientsForCallsigns(const aviation::CCallsignSet &callsigns) const
Returns a list of other clients corresponding to the given callsigns.
void markAsSwiftClient(const aviation::CCallsign &callsign)
Mark as other swift client.
bool setOtherClient(const swift::misc::network::CClient &client)
Set client for its callsign.
bool addNewClient(const CClient &client)
Add a new client, if existing nothing will be added.
void setClients(const CClientList &clients)
Set other clients.
CClientList getClients() const
clientprovider
void clearClients()
Set other clients.
CClient getClientOrDefaultForCallsign(const aviation::CCallsign &callsign) const
Other client for the given callsigns.
bool setClientGndCapability(const aviation::CCallsign &callsign, bool supportGndFlag)
Set gnd.flag capability.
bool autoAdjustCientGndCapability(const aviation::CAircraftSituation &situation)
Adjust gnd.flag capability from situation.
Value object encapsulating information about a connection status.
bool isConnected() const
Query status.
bool isDisconnected() const
Query status.
Value object encapsulating information about login mode.
Definition: loginmode.h:18
void setLoginMode(LoginMode mode)
Set login mode.
Definition: loginmode.h:43
Value object encapsulating information of a server.
Definition: server.h:28
int getPort() const
Get port.
Definition: server.h:116
const QString & getAddress() const
Get address.
Definition: server.h:80
const CUser & getUser() const
Get user.
Definition: server.h:86
Value object encapsulating a list of servers.
Definition: serverlist.h:23
Value object encapsulating information of a text message.
Definition: textmessage.h:31
bool isRelayedMessage() const
Is relayed message.
Definition: textmessage.cpp:73
void setMessage(const QString &message)
Set message.
bool isPrivateMessage() const
Is private message?
Definition: textmessage.cpp:53
void setSenderCallsign(const aviation::CCallsign &callsign)
Set callsign (from)
Definition: textmessage.h:57
bool isEmpty() const
Empty message.
Definition: textmessage.h:90
void setRecipientCallsign(const aviation::CCallsign &callsign)
Set callsign (recipient)
Definition: textmessage.h:63
const aviation::CCallsign & getSenderCallsign() const
Get callsign (from)
Definition: textmessage.h:54
void setFrequency(const physical_quantities::CFrequency &frequency)
Set frequency.
Definition: textmessage.h:99
const aviation::CCallsign & getRecipientCallsign() const
Get callsign (to)
Definition: textmessage.h:60
Value object encapsulating a list of text messages.
CTextMessageList withRemovedPrivateMessagesFromCallsign(const aviation::CCallsign &callsign) const
With removed private messages from callsign.
bool containsPrivateMessages() const
Contains private messages?
CTextMessageList findByNotForRecipient(const swift::misc::aviation::CCallsign &recipient) const
Find by recipient is NOT addressed.
CTextMessageList findBySender(const swift::misc::aviation::CCallsign &sender) const
Find by sender.
CTextMessageList getPrivateMessages() const
Private messages.
CTextMessageList getSupervisorMessages() const
Supervisor messages.
CTextMessageList withRelayedToPrivateMessages() const
List with relayed messages (if any) as private messages.
CTextMessageList findByRecipient(const swift::misc::aviation::CCallsign &recipient) const
Find by recipient.
CTextMessageList markedAsSent()
Marked as sent.
Value object encapsulating information of a user.
Definition: user.h:28
bool hasCredentials() const
Valid credentials?
Definition: user.h:77
Value object encapsulating a list of voice rooms.
Definition: userlist.h:26
Physical unit length (length)
Definition: length.h:18
void parseFromString(const QString &value)
Parse value from string.
int valueInteger(MU unit) const
As integer value.
QString valueRoundedWithUnit(const MU &unit, int digits=-1, bool withGroupSeparator=false, bool i18n=false) const
Value to QString with the given unit, e.g. "5.00m".
bool isPositiveWithEpsilonConsidered() const
Value >= 0 epsilon considered.
void parseFromString(const QString &time)
From string hh:mm, or hh:mm:ss, or time units such as s, min.
Definition: time.cpp:39
Aircraft model (used by another pilot, my models on disk)
Definition: aircraftmodel.h:71
QString getSwiftLiveryString(bool aircraftIcao=true, bool livery=true, bool model=true) const
swift livery string (to be sent via network)
swift::misc::CStatusMessageList getReverseLookupMessages(const swift::misc::aviation::CCallsign &callsign) const
Get reverse lookup meesages.
bool isAircraftInRange(const aviation::CCallsign &callsign) const
Is aircraft in range?
int remoteAircraftSituationChangesCount(const aviation::CCallsign &callsign) const
Aircraft changes count.
int updateMultipleAircraftRendered(const aviation::CCallsignSet &callsigns, bool rendered)
Set aircraft rendered.
CSimulatedAircraftList getAircraftInRange() const
All remote aircraft.
bool updateCGAndModelString(const aviation::CCallsign &callsign, const physical_quantities::CLength &cg, const QString &modelString)
Update the CG and model string.
bool setAircraftEnabledFlag(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Just set enable/disable aircraft flag, no further logic.
aviation::CCallsignSet remoteAircraftSupportingParts() const
Remote aircraft supporting parts.
int getRemoteAircraftSupportingPartsCount() const
Number of aircraft supporting parts.
qint64 situationsLastModified(const aviation::CCallsign &callsign) const
When last modified.
void changedAircraftInRange()
Aircraft were changed.
bool isAircraftPartsHistoryEnabled() const
Is storing aircraft parts history enabled?
int remoteAircraftSituationsCount(const aviation::CCallsign &callsign) const
Number of remote aircraft situations for callsign.
aviation::CAircraftSituation remoteAircraftSituation(const aviation::CCallsign &callsign, int index) const
Rendered aircraft situations (per callsign and index)
geo::CElevationPlane averageElevationOfNonMovingAircraft(const aviation::CAircraftSituation &reference, const physical_quantities::CLength &range, int minValues=1, int sufficientValues=2) const
Average elevation of aircraft in given range, which are NOT moving.
aviation::CAircraftSituationList remoteAircraftSituations(const aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history)
bool isVtolAircraft(const aviation::CCallsign &callsign) const
Is VTOL aircraft?
aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const aviation::CCallsign &callsign) const
Aircraft changes.
MillisecondsMinMaxMean remoteAircraftSituationsTimestampDifferenceMinMaxMean(const aviation::CCallsign &callsign) const
Average update time.
aviation::CCallsignSet updateCGForModel(const QString &modelString, const physical_quantities::CLength &cg)
Update the CG for this model string.
void enableAircraftPartsHistory(bool enabled)
Enable storing of aircraft parts history.
CStatusMessageList getAircraftPartsHistory(const aviation::CCallsign &callsign) const
Get aircraft parts history.
void addedAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
A new aircraft appeared.
int remoteAircraftPartsCount(const aviation::CCallsign &callsign) const
All parts (per callsign, time history)
bool updateAircraftEnabled(const aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
void rememberCGFromDB(const physical_quantities::CLength &cgFromDB, const aviation::CCallsign &callsign)
CG values from DB.
aviation::CAircraftSituationList latestRemoteAircraftSituations() const
Latest aircraft situation for all callsigns.
bool updateAircraftNetworkModel(const aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator)
Change network model.
bool updateAircraftModel(const aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator)
Change model.
physical_quantities::CLength getCGFromDB(const aviation::CCallsign &callsign) const
CG values from DB.
qint64 partsLastModified(const aviation::CCallsign &callsign) const
When last modified.
QList< QMetaObject::Connection > connectRemoteAircraftProviderSignals(QObject *receiver, std::function< void(const aviation::CAircraftSituation &)> addedSituationSlot, std::function< void(const aviation::CCallsign &, const aviation::CAircraftParts &)> addedPartsSlot, std::function< void(const aviation::CCallsign &)> removedAircraftSlot, std::function< void(const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly...
bool updateAircraftRendered(const aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
aviation::CAircraftSituationList latestOnGroundProviderElevations() const
Latest aircraft situation "on ground" having a provider elevation.
aviation::CCallsignSet getAircraftInRangeCallsigns() const
Unique callsigns for aircraft in range.
ReverseLookupLogging isReverseLookupMessagesEnabled() const
Enabled reverse lookup logging?
CAircraftModel getAircraftInRangeModelForCallsign(const aviation::CCallsign &callsign) const
Aircraft model for callsign.
CSimulatedAircraft getAircraftInRangeForCallsign(const aviation::CCallsign &callsign) const
Aircraft for callsign.
int aircraftSituationsAdded() const
Number of situations added.
aviation::CAircraftPartsList remoteAircraftParts(const aviation::CCallsign &callsign) const
All parts (per callsign, time history)
void enableReverseLookupMessages(ReverseLookupLogging enable)
Enable reverse lookup logging.
int updateMultipleAircraftEnabled(const aviation::CCallsignSet &callsigns, bool enabledForRendering)
Enable/disable aircraft.
bool updateCG(const aviation::CCallsign &callsign, const physical_quantities::CLength &cg)
Update the CG.
bool isRemoteAircraftSupportingParts(const aviation::CCallsign &callsign) const
Is remote aircraft supporting parts?
int getAircraftInRangeCount() const
Count remote aircraft.
bool testAddAltitudeOffset(const aviation::CCallsign &callsign, const physical_quantities::CLength &offset)
Offset for callsign.
void removedAircraft(const swift::misc::aviation::CCallsign &callsign)
An aircraft disappeared.
int updateAircraftGroundElevation(const aviation::CCallsign &callsign, const geo::CElevationPlane &elevation, aviation::CAircraftSituation::GndElevationInfo info, bool *setForOnGroundPosition)
Update the ground elevation.
Comprehensive information of an aircraft.
const aviation::CComSystem & getCom2System() const
Get COM2 system.
bool isSupportingGndFlag() const
Is supporting gnd.flag?
bool fastPositionUpdates() const
Support fast position updates.
const aviation::CCallsign & getCallsign() const
Get callsign.
const aviation::CAircraftIcaoCode & getAircraftIcaoCode() const
Get aircraft ICAO info.
const simulation::CAircraftModel & getModel() const
Get model (model used for mapping)
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.
void setSimulationEnvironmentProvider(ISimulationEnvironmentProvider *provider)
Set the provider.
Simple hardcoded info about the corresponding simulator.
Definition: simulatorinfo.h:41
const CSimulatorInfo & getSimulatorInfo() const
Simulator info object.
static const aviation::CCallsign & testAltitudeOffsetCallsign()
Wildcard callsign.
Value object encapsulating information about METAR FIXME: runway visibilities FIXME: runway wind shea...
Definition: metar.h:38
Sequence of Metars.
Definition: metarlist.h:24
bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)
Parse a given command line.
bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)
Parse a given command line.
Free functions in swift::misc.
SWIFT_MISC_EXPORT const QString & boolToOnOff(bool v)
Bool to on/off.
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
bool disconnect(const QMetaObject::Connection &connection)
void setObjectName(QAnyStringView name)
T dequeue()
void enqueue(T &&t)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QByteArray toLocal8Bit() const const
QueuedConnection
void start()
void timeout()
Milliseconds minimum/maximum/mean.