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 <stdbool.h>
7 
8 #include <QStringBuilder>
9 #include <QTimer>
10 
11 #include "config/buildconfig.h"
12 #include "core/airspaceanalyzer.h"
13 #include "core/airspacemonitor.h"
14 #include "core/application.h"
18 #include "core/corefacade.h"
19 #include "core/fsd/fsdclient.h"
20 #include "core/webdataservices.h"
24 #include "misc/aviation/callsign.h"
26 #include "misc/dbusserver.h"
27 #include "misc/logcategories.h"
28 #include "misc/logmessage.h"
32 #include "misc/pq/constants.h"
33 #include "misc/pq/frequency.h"
34 #include "misc/pq/time.h"
35 #include "misc/pq/units.h"
36 #include "misc/sequence.h"
39 #include "misc/stringutils.h"
40 
41 using namespace swift::config;
42 using namespace swift::misc;
43 using namespace swift::misc::physical_quantities;
44 using namespace swift::misc::aviation;
45 using namespace swift::misc::network;
46 using namespace swift::misc::geo;
47 using namespace swift::misc::simulation;
48 using namespace swift::misc::weather;
49 using namespace swift::core::fsd;
50 using namespace swift::core::vatsim;
51 
52 namespace swift::core::context
53 {
54  CContextNetwork::CContextNetwork(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime)
55  : IContextNetwork(mode, runtime)
56  {
58  Q_ASSERT(this->getRuntime());
59  Q_ASSERT(this->getIContextOwnAircraft());
62 
63  // 1. Init by "network driver"
64  m_fsdClient = new CFSDClient(this, // client provider
65  this->getRuntime()->getCContextOwnAircraft(), // own aircraft provider
66  this, // remote aircraft provider
67  this); // thread owner
68  m_fsdClient->start(); // FSD thread
69  connect(m_fsdClient, &CFSDClient::connectionStatusChanged, this, &CContextNetwork::onFsdConnectionStatusChanged,
70  Qt::QueuedConnection);
71  connect(m_fsdClient, &CFSDClient::killRequestReceived, this, &CContextNetwork::kicked, Qt::QueuedConnection);
72  connect(m_fsdClient, &CFSDClient::textMessagesReceived, this, &CContextNetwork::onTextMessagesReceived,
73  Qt::QueuedConnection);
74  connect(m_fsdClient, &CFSDClient::textMessageSent, this, &CContextNetwork::onTextMessageSent,
75  Qt::QueuedConnection);
76  connect(m_fsdClient, &CFSDClient::severeNetworkError, this, &CContextNetwork::severeNetworkError,
77  Qt::QueuedConnection);
78  connect(m_fsdClient, &CFSDClient::muteRequestReceived, this, &CContextNetwork::muteRequestReceived,
79  Qt::QueuedConnection);
80 
81  // 2. Update timer for data (network data such as frequency)
82  // we use 2 timers so we can query at different times (not too many queirs at once)
83  m_requestAircraftDataTimer = new QTimer(this);
84  connect(m_requestAircraftDataTimer, &QTimer::timeout, this, &CContextNetwork::requestAircraftDataUpdates);
85  m_requestAircraftDataTimer->start(30 * 1000);
86  m_requestAircraftDataTimer->setObjectName("CContextNetwork::m_requestAircraftDataTimer");
87 
88  m_requestAtisTimer = new QTimer(this);
89  connect(m_requestAtisTimer, &QTimer::timeout, this, &CContextNetwork::requestAtisUpdates);
90  m_requestAtisTimer->start(13 * 1000); // should not be called at the same time as above
91  m_requestAtisTimer->setObjectName("CContextNetwork::m_requestAtisTimer");
92 
93  // 3. send staggered model matching signals, to avoid to many matchings at the same time
94  m_staggeredMatchingTimer = new QTimer(this);
95  connect(m_staggeredMatchingTimer, &QTimer::timeout, this, &CContextNetwork::emitReadyForMatching);
96  m_staggeredMatchingTimer->start(200);
97  m_staggeredMatchingTimer->setObjectName("CContextNetwork::m_staggeredMatchingTimer");
98 
99  // 4. Airspace contents
100  Q_ASSERT_X(this->getRuntime()->getCContextOwnAircraft(), Q_FUNC_INFO,
101  "this and own aircraft context must be local");
102  Q_ASSERT_X(this->getRuntime()->getCContextSimulator(), Q_FUNC_INFO,
103  "this and own simulator context must be local");
104  m_airspace = new CAirspaceMonitor(this->getRuntime()->getCContextOwnAircraft(),
105  this->getRuntime()->getCContextSimulator(), m_fsdClient, this);
106  m_fsdClient->setClientProvider(m_airspace);
108  Qt::QueuedConnection);
109  connect(m_airspace, &CAirspaceMonitor::changedAtcStationsOnline, this,
110  &CContextNetwork::changedAtcStationsOnline, Qt::QueuedConnection);
112  Qt::QueuedConnection);
114  Qt::QueuedConnection); // DBus
115  connect(m_airspace, &CAirspaceMonitor::readyForModelMatching, this,
116  &CContextNetwork::onReadyForModelMatching); // intentionally NOT QueuedConnection
118  Qt::QueuedConnection);
119  connect(m_airspace, &CAirspaceMonitor::changedAtisReceived, this, &CContextNetwork::onChangedAtisReceived,
120  Qt::QueuedConnection);
121  }
122 
124  {
125  if (this->canUseAirspaceMonitor()) { m_airspace->setSimulationEnvironmentProvider(provider); }
126  if (this->canUseFsd()) { m_fsdClient->setSimulationEnvironmentProvider(provider); }
127  }
128 
130 
132  {
133  if (!this->canUseAirspaceMonitor()) { return {}; }
134  return m_airspace->remoteAircraftSituations(callsign);
135  }
136 
138  {
139  if (!this->canUseAirspaceMonitor()) { return {}; }
140  return m_airspace->remoteAircraftSituation(callsign, index);
141  }
142 
145  {
146  if (!this->canUseAirspaceMonitor()) { return {}; }
147  return m_airspace->remoteAircraftSituationsTimestampDifferenceMinMaxMean(callsign);
148  }
149 
151  {
152  if (!this->canUseAirspaceMonitor()) { return {}; }
153  return m_airspace->latestRemoteAircraftSituations();
154  }
155 
157  {
158  Q_ASSERT(m_airspace);
159  return m_airspace->latestOnGroundProviderElevations();
160  }
161 
163  {
164  if (!this->canUseAirspaceMonitor()) { return {}; }
165  return m_airspace->remoteAircraftParts(callsign);
166  }
167 
169  {
170  if (!this->canUseAirspaceMonitor()) { return 0; }
171  return m_airspace->remoteAircraftPartsCount(callsign);
172  }
173 
175  {
176  if (!this->canUseAirspaceMonitor()) { return 0; }
177  return m_airspace->remoteAircraftSituationsCount(callsign);
178  }
179 
181  {
182  if (!this->canUseAirspaceMonitor()) { return false; }
183  return m_airspace->isRemoteAircraftSupportingParts(callsign);
184  }
185 
187  {
188  if (!this->canUseAirspaceMonitor()) { return {}; }
189  return m_airspace->remoteAircraftSupportingParts();
190  }
191 
193  {
194  if (!this->canUseAirspaceMonitor()) { return {}; }
195  return m_airspace->remoteAircraftSituationChanges(callsign);
196  }
197 
199  {
200  if (!this->canUseAirspaceMonitor()) { return {}; }
201  return m_airspace->remoteAircraftSituationChangesCount(callsign);
202  }
203 
205  QObject *receiver, std::function<void(const CAircraftSituation &)> situationSlot,
206  std::function<void(const CCallsign &, const CAircraftParts &)> partsSlot,
207  std::function<void(const CCallsign &)> removedAircraftSlot,
208  std::function<void(const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
209  {
210  Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace");
211  return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot,
212  aircraftSnapshotSlot);
213  }
214 
216  {
217  this->disconnect(); // all signals
218  if (this->isConnected()) { this->disconnectFromNetwork(); }
219  if (m_fsdClient)
220  {
221  m_fsdClient->gracefulShutdown();
222  m_fsdClient->setClientProvider(nullptr);
223  m_fsdClient->deleteLater();
224  m_fsdClient = nullptr;
225  }
226 
227  if (m_airspace)
228  {
229  m_airspace->gracefulShutdown();
230  m_airspace->deleteLater();
231  m_airspace = nullptr;
232  }
233  }
234 
235  CStatusMessage CContextNetwork::connectToNetwork(const CServer &server, const QString &extraLiveryString,
236  bool sendLivery, const QString &extraModelString,
237  bool sendModelString, const CCallsign &partnerCallsign,
238  CLoginMode mode)
239  {
240  if (!this->canUseFsd())
241  {
243  u"Invalid FSD state (shutdown)") };
244  }
245  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
246 
247  QString msg;
248  if (!server.getUser().hasCredentials())
249  {
251  u"Invalid user credentials");
252  }
253  if (!this->ownAircraft().getAircraftIcaoCode().hasDesignator())
254  {
256  u"Invalid ICAO data for own aircraft");
257  }
258  if (!CNetworkUtils::canConnect(server, msg, 5000))
259  {
261  }
262  if (m_fsdClient->isConnected())
263  {
265  u"Already connected");
266  }
267  if (this->isPendingConnection())
268  {
270  u"Pending connection, please wait");
271  }
272 
274  const CSimulatedAircraft ownAircraft(this->ownAircraft());
275  m_fsdClient->setPartnerCallsign(
276  isValidPartnerCallsign(ownAircraft.getCallsign(), partnerCallsign) ? partnerCallsign : CCallsign());
277 
278  // Fall back to observer mode, if no simulator is available or not simulating
279  if (!CBuildConfig::isLocalDeveloperDebugBuild() && !this->getIContextSimulator()->isSimulatorSimulating())
280  {
281  CLogMessage(this).info(
282  u"No simulator connected or connected simulator not simulating. Falling back to observer mode");
283  mode.setLoginMode(CLoginMode::Observer);
284  }
285 
286  const CSimulatorInfo sim = this->getIContextSimulator() ?
288  CSimulatorInfo();
289  const QString l =
290  extraLiveryString.isEmpty() ? ownAircraft.getModel().getSwiftLiveryString(sim) : extraLiveryString;
291  const QString m = extraModelString.isEmpty() ? ownAircraft.getModelString() : extraModelString;
292 
293  // FG fix, do not send livery and model ids for FlightGear
294  // https://discordapp.com/channels/539048679160676382/567091362030419981/698124094482415616
295  if (sim.isFG() && extraModelString.isEmpty()) { sendModelString = false; }
296 
297  m_currentMode = mode;
298  m_fsdClient->setLoginMode(mode);
299  m_fsdClient->setCallsign(ownAircraft.getCallsign());
300 
301  // set this BEFORE model string as FG has different handling
302  m_fsdClient->setSimType(sim);
303 
304  m_fsdClient->setIcaoCodes(ownAircraft);
305  m_fsdClient->setLiveryAndModelString(l, sendLivery, m, sendModelString);
306  m_fsdClient->setClientName(sApp->swiftVersionChar());
307  m_fsdClient->setVersion(CBuildConfig::getVersion().majorVersion(), CBuildConfig::getVersion().minorVersion());
308 
309 #ifdef SWIFT_VATSIM_SUPPORT
310  int clientId = 0;
311  QString clientKey;
312  if (!getCmdLineClientIdAndKey(clientId, clientKey))
313  {
314  clientId = CBuildConfig::vatsimClientId();
315  clientKey = CBuildConfig::vatsimPrivateKey();
316  }
317 
318  m_fsdClient->setClientIdAndKey(static_cast<quint16>(clientId), clientKey.toLocal8Bit());
319 #endif
320  m_fsdClient->setClientCapabilities(Capabilities::AircraftInfo | Capabilities::FastPos | Capabilities::VisPos |
321  Capabilities::AtcInfo | Capabilities::AircraftConfig |
322  Capabilities::IcaoEquipment);
323  m_fsdClient->setServer(server);
324 
325  m_fsdClient->setPilotRating(PilotRating::Student);
326  m_fsdClient->setAtcRating(AtcRating::Observer);
327 
328  m_fsdClient->connectToServer();
330  u"Connection pending " % server.getAddress() % u' ' % QString::number(server.getPort()));
331  }
332 
334  {
335  if (!this->canUseFsd()) { return {}; }
336  return this->isConnected() ? m_fsdClient->getServer() : CServer();
337  }
338 
340  {
341  if (!this->canUseFsd()) { return {}; }
342  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
343  return m_fsdClient->getLoginMode();
344  }
345 
347  {
348  if (!this->canUseFsd())
349  {
351  u"Invalid FSD state (shutdown)") };
352  }
353  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
354  if (m_fsdClient->isConnected() || m_fsdClient->isPendingConnection())
355  {
356  m_fsdClient->disconnectFromServer();
358  u"Connection terminating");
359  }
360  else
361  {
363  u"Already disconnected");
364  }
365  }
366 
368  {
369  if (!this->canUseFsd()) { return false; }
370  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
371  return m_fsdClient->isConnected();
372  }
373 
375  {
376  if (!this->canUseFsd()) { return false; }
377  return m_fsdClient->isPendingConnection();
378  }
379 
380  bool CContextNetwork::parseCommandLine(const QString &commandLine, const CIdentifier &originator)
381  {
382  Q_UNUSED(originator;)
383 
384  if (!this->canUseAirspaceMonitor()) { return false; }
385  if (!this->canUseFsd()) { return false; }
386  if (commandLine.isEmpty()) { return false; }
387 
388  static const QStringList cmds({ ".msg", ".m", ".chat", ".altos", ".altoffset", ".addtimeos", ".addtimeoffset",
389  ".wallop", ".reinit", ".reinitialize", ".enable", ".disable", ".ignore",
390  ".unignore", ".fsd" });
391  CSimpleCommandParser parser(cmds);
392  parser.parse(commandLine);
393  if (!parser.isKnownCommand()) { return false; }
394  if (parser.matchesCommand(".msg", ".m", ".chat"))
395  {
396  if (!this->getIContextNetwork() || !this->getIContextNetwork()->isConnected())
397  {
398  CLogMessage(this).validationError(u"Network needs to be connected");
399  return false;
400  }
401  else if (!this->getIContextOwnAircraft())
402  {
403  CLogMessage(this).validationError(u"No own aircraft data, no text message can be sent");
404  return false;
405  }
406  if (parser.countParts() < 3)
407  {
408  CLogMessage(this).validationError(u"Incorrect message");
409  return false;
410  }
411 
412  // set receiver
413  const CSimulatedAircraft ownAircraft(this->getIContextOwnAircraft()->getOwnAircraft());
414  const QString receiver = parser.part(1).trimmed().toLower(); // receiver
415  CCallsign ownCallsign = ownAircraft.getCallsign();
416  if (m_fsdClient)
417  {
418  // override with the preset callsign, as the own callsign can be different for partner callsign
419  // scenarios copilot scenarios
420  const CCallsign presetCallsign = m_fsdClient->getPresetCallsign();
421  if (!presetCallsign.isEmpty()) { ownCallsign = presetCallsign; }
422  }
423 
424  if (ownCallsign.isEmpty())
425  {
426  CLogMessage(this).validationError(u"No own callsign");
427  return false;
428  }
429 
430  CTextMessage tm;
431  tm.setSenderCallsign(ownCallsign);
432 
433  // based on the CPZ bug
434  // https://discordapp.com/channels/539048679160676382/539486309882789888/576765888401768449 no longer use
435  // starts/ends with
436  if (receiver == QStringView(u"c1") || receiver == QStringView(u"com1") || receiver == QStringView(u"comm1"))
437  {
438  tm.setFrequency(ownAircraft.getCom1System().getFrequencyActive());
439  }
440  else if (receiver == QStringView(u"c2") || receiver == QStringView(u"com2") ||
441  receiver == QStringView(u"comm2"))
442  {
443  tm.setFrequency(ownAircraft.getCom2System().getFrequencyActive());
444  }
445  else if (receiver == "u" || receiver == QStringView(u"uni") || receiver == QStringView(u"unicom"))
446  {
447  tm.setFrequency(CPhysicalQuantitiesConstants::FrequencyUnicom());
448  }
449  else
450  {
451  const CFrequency radioFrequency =
452  CComSystem::parseComFrequency(receiver, CPqString::SeparatorBestGuess);
453  if (!radioFrequency.isNull())
454  {
455  if (CComSystem::isValidCivilAviationFrequency(radioFrequency)) { tm.setFrequency(radioFrequency); }
456  else
457  {
458  CLogMessage(this).validationError(u"Wrong COM frequency for text message");
459  return false;
460  }
461  }
462  else
463  {
464  const CCallsign toCallsign(receiver);
465  tm.setRecipientCallsign(toCallsign);
466  }
467  }
468 
469  const QString msg(parser.partAndRemainingStringAfter(2));
470  tm.setMessage(msg);
471  if (tm.isEmpty())
472  {
473  CLogMessage(this).validationError(u"No text message body");
474  return false;
475  }
476  CTextMessageList tml(tm);
477  this->sendTextMessages(tml);
478  return true;
479  }
480  else if (parser.matchesCommand(".altos", ".altoffset"))
481  {
482  if (!m_airspace) { return false; }
483  if (parser.countParts() < 2) { return false; }
484 
485  const QString csPart(parser.part(1));
486  CCallsign cs;
487  if (csPart.contains('?'))
488  {
490  }
491  else
492  {
493  cs = CCallsign(csPart);
494  if (!m_airspace->isAircraftInRange(cs))
495  {
496  CLogMessage(this).validationError(u"Altitude offset unknown callsign");
497  return false;
498  }
499  }
500 
501  CLength os(CLength::null());
502  if (parser.hasPart(2)) { os.parseFromString(parser.part(2), CPqString::SeparatorBestGuess); }
503 
504  const bool added = this->testAddAltitudeOffset(cs, os);
505  if (added)
506  {
507  CLogMessage(this).info(u"Added altitude offset %1 for %2")
508  << os.valueRoundedWithUnit(2) << cs.asString();
509  }
510  else { CLogMessage(this).info(u"Removed altitude offset %1") << cs.asString(); }
511 
512  return true;
513  }
514  else if (parser.matchesCommand(".addtimeos", ".addtimeoffset"))
515  {
516  if (!m_airspace) { return false; }
517  if (parser.countParts() < 2) { return false; }
518 
519  CTime os(CTime::null());
520  if (parser.hasPart(2)) { os.parseFromString(parser.part(2), CPqString::SeparatorBestGuess); }
521 
522  if (!os.isNull() && os.isPositiveWithEpsilonConsidered())
523  {
524  const qint64 ost = os.valueInteger(CTimeUnit::ms());
525  CLogMessage(this).info(u"Added add offset time %1ms") << ost;
526  }
527  else { CLogMessage(this).info(u"Reset add. time offset"); }
528  }
529  else if (parser.matchesCommand(".reinit", ".reinitialize"))
530  {
531  if (!m_airspace) { return false; }
532  const int count = m_airspace->reInitializeAllAircraft();
533  if (count > 0) { CLogMessage(this).info(u"Re-init %1 aircraft") << count; }
534  }
535  else if (parser.matchesCommand(".wallop"))
536  {
537  if (parser.countParts() < 2) { return false; }
538  if (!m_fsdClient) { return false; }
539  if (!this->isConnected())
540  {
541  CLogMessage(this).validationError(u"Network needs to be connected");
542  return false;
543  }
544  const QString wallopMsg = parser.partAndRemainingStringAfter(1);
545  if (wallopMsg.isEmpty())
546  {
547  CLogMessage(this).validationError(u"No wallop message body");
548  return false;
549  }
550  m_fsdClient->sendTextMessage(TextMessageGroups::AllSups, wallopMsg);
551  return true;
552  }
553  else if (parser.matchesCommand(".enable", ".unignore"))
554  {
555  if (parser.countParts() < 2) { return false; }
556  if (!m_fsdClient) { return false; }
557  if (!this->isConnected()) { return false; }
558  const CCallsign cs(parser.part(1));
559  if (cs.isValid()) { this->updateAircraftEnabled(cs, true); }
560  }
561  else if (parser.matchesCommand(".disable", ".ignore"))
562  {
563  if (parser.countParts() < 2) { return false; }
564  if (!m_fsdClient) { return false; }
565  if (!this->isConnected()) { return false; }
566  const CCallsign cs(parser.part(1));
567  if (cs.isValid()) { this->updateAircraftEnabled(cs, false); }
568  }
569  else if (m_airspace && parser.matchesCommand(".fsd"))
570  {
571  return m_airspace->parseCommandLine(commandLine, originator);
572  }
573 
574  return false;
575  }
576 
578  {
579  if (this->isDebugEnabled())
580  {
581  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages;
582  }
583  m_fsdClient->sendTextMessages(textMessages);
584  }
585 
587  {
588  if (this->isDebugEnabled())
589  {
590  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << flightPlan;
591  }
592  m_fsdClient->sendFlightPlan(flightPlan);
593  m_fsdClient->sendClientQueryFlightPlan(this->ownAircraft().getCallsign());
594  }
595 
597  {
598  if (!this->canUseFsd()) { return {}; }
599  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
600  return m_airspace->loadFlightPlanFromNetwork(callsign);
601  }
602 
604  {
605  if (!this->canUseAirspaceMonitor()) { return {}; }
606  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
607  return m_airspace->getUsers();
608  }
609 
611  {
612  if (!this->canUseAirspaceMonitor() || callsigns.isEmpty()) { return {}; }
613  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
614  return m_airspace->getUsersForCallsigns(callsigns);
615  }
616 
618  {
619  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
620  CCallsignSet callsigns;
621  callsigns.push_back(callsign);
622  const CUserList users = this->getUsersForCallsigns(callsigns);
623  if (users.isEmpty()) { return CUser(); }
624  return users[0];
625  }
626 
628  {
629  if (!this->canUseAirspaceMonitor()) { return {}; }
630  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
631  return m_airspace->getClients();
632  }
633 
635  {
636  if (!this->canUseAirspaceMonitor()) { return {}; }
637  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
638  return m_airspace->getClientsForCallsigns(callsigns);
639  }
640 
642  {
643  if (!this->canUseAirspaceMonitor()) { return false; }
644  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
645  return m_airspace->setOtherClient(client);
646  }
647 
649  {
650  if (!this->canUseAirspaceMonitor()) { return 0; }
651  return m_airspace->removeClient(callsign);
652  }
653 
655  {
656  if (!this->canUseAirspaceMonitor()) { return false; }
657  return m_airspace->autoAdjustCientGndCapability(situation);
658  }
659 
661  {
662  if (!this->canUseAirspaceMonitor()) { return false; }
663  return m_airspace->addClientGndCapability(callsign);
664  }
665 
666  bool CContextNetwork::setClientGndCapability(const aviation::CCallsign &callsign, bool supportGndFlag)
667  {
668  if (!this->canUseAirspaceMonitor()) { return false; }
669  return m_airspace->setClientGndCapability(callsign, supportGndFlag);
670  }
671 
672  void CContextNetwork::markAsSwiftClient(const CCallsign &callsign) { m_airspace->markAsSwiftClient(callsign); }
673 
675  {
676  Q_ASSERT_X(sApp->getWebDataServices(), Q_FUNC_INFO, "Missing data reader");
677  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
679  }
680 
681  void CContextNetwork::onFsdConnectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
682  {
683  // if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << from
684  // << to; }
685 
686  if (to.isDisconnected())
687  {
688  // make sure airspace is really cleaned up
689  Q_ASSERT(m_airspace);
690  m_airspace->clear();
691  }
692 
693  // send 1st position
694  if (to.isConnected())
695  {
696  CLogMessage(this).info(u"Connected, own aircraft %1") << this->ownAircraft().getCallsignAsString();
697 
698  if (m_fsdClient)
699  {
700  const CServer server = m_fsdClient->getServer();
701  emit this->connectedServerChanged(server);
702  }
703  }
704 
705  // send as message
706  static const QString chgMsg("Connection status changed from '%1' to '%2'");
707  CLogMessage(this).info(chgMsg) << from.toQString() << to.toQString();
708 
709  // send as own signal
710  emit this->connectionStatusChanged(from, to);
711  }
712 
713  void CContextNetwork::onReadyForModelMatching(const CSimulatedAircraft &aircraft)
714  {
715  m_readyForModelMatching.enqueue(aircraft);
716  }
717 
718  void CContextNetwork::emitReadyForMatching()
719  {
720  if (m_readyForModelMatching.isEmpty()) { return; }
721  if (!sApp || sApp->isShuttingDown()) { return; }
722 
723  const CSimulatedAircraft aircraft = m_readyForModelMatching.dequeue();
724  if (!this->isAircraftInRange(aircraft.getCallsign())) { return; }
725  emit this->readyForModelMatching(aircraft);
726  }
727 
728  void CContextNetwork::createRelayMessageToPartnerCallsign(const CTextMessage &textMessage,
729  const CCallsign &partnerCallsign,
730  CTextMessageList &relayedMessages)
731  {
732  if (textMessage.isEmpty()) { return; }
733  if (partnerCallsign.isEmpty()) { return; }
734  if (textMessage.getSenderCallsign() == partnerCallsign) { return; } // no round trips
735 
736  CTextMessage modified(textMessage);
737  modified.makeRelayedMessage(partnerCallsign);
738  relayedMessages.push_back(modified);
739  }
740 
741  void CContextNetwork::xCtxSimulatorRenderRestrictionsChanged(bool restricted, bool enabled, int maxAircraft,
742  const CLength &maxRenderedDistance)
743  {
744  // mainly passing changed restrictions from simulator to network
745  if (!m_airspace) { return; }
746  if (!m_airspace->analyzer()) { return; }
747  m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, enabled, maxAircraft,
748  maxRenderedDistance);
749  }
750 
751  void CContextNetwork::xCtxSimulatorStatusChanged(int status)
752  {
753  const ISimulator::SimulatorStatus simStatus = static_cast<ISimulator::SimulatorStatus>(status);
754  if (ISimulator::isAnyConnectedStatus(simStatus))
755  {
756  const QPointer<CContextSimulator> sim = this->getRuntime()->getCContextSimulator();
757  this->setSimulationEnvironmentProvider(sim ? sim->simulator() : nullptr);
758  const CSimulatorInfo simInfo = sim ? sim->getSimulatorPluginInfo().getSimulatorInfo() : CSimulatorInfo();
759 
760  m_simulatorConnected++;
761  m_lastConnectedSim = simInfo;
762  }
763  else { this->setSimulationEnvironmentProvider(nullptr); }
764  }
765 
766  bool CContextNetwork::canUseFsd() const { return sApp && !sApp->isShuttingDown() && m_fsdClient; }
767 
768  bool CContextNetwork::canUseAirspaceMonitor() const { return sApp && !sApp->isShuttingDown() && m_airspace; }
769 
770  void CContextNetwork::updateMetars(const CMetarList &metars)
771  {
772  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
773  CLogMessage(this).info(u"%1 METARs updated") << metars.size();
774  }
775 
776  void CContextNetwork::onChangedAtisReceived(const CCallsign &callsign)
777  {
778  Q_UNUSED(callsign)
779  m_dsAtcStationsOnlineChanged.inputSignal(); // the ATIS data are stored in the station object
780  }
781 
782  void CContextNetwork::onTextMessagesReceived(const CTextMessageList &messages)
783  {
784  if (messages.isEmpty()) { return; }
785 
786  const CCallsign partnerCallsign = this->getPartnerCallsign();
787  const CCallsign ownCallsign = this->ownAircraft().getCallsign();
788 
789  CTextMessageList textMessages = messages.withRelayedToPrivateMessages();
790  CTextMessageList partnerMessages;
791 
792  if (!partnerCallsign.isEmpty())
793  {
794  partnerMessages = textMessages.findBySender(partnerCallsign);
795  const CTextMessageList relayedSentMessages =
796  partnerMessages.findByNotForRecipient(ownCallsign).markedAsSent();
797  partnerMessages =
798  partnerMessages.findByRecipient(ownCallsign); // really send to me as PM and not a forwared one
799 
800  // avoid infinite rountrips
801  textMessages = textMessages.withRemovedPrivateMessagesFromCallsign(partnerCallsign);
802 
803  // fake those as sent by myself
804  for (const CTextMessage &rsm : relayedSentMessages) { emit this->textMessageSent(rsm); }
805  }
806 
807  // 1) relayed messaged "now look like PMs"
808  // 2) all messaged of partner are EXCLUDED
809  if (!textMessages.isEmpty()) { emit this->textMessagesReceived(textMessages); }
810  if (!partnerMessages.isEmpty()) { emit this->textMessagesReceived(partnerMessages); }
811 
812  if (textMessages.containsPrivateMessages())
813  {
814  const CTextMessageList supMessages(messages.getSupervisorMessages());
815  for (const CTextMessage &m : supMessages) { emit this->supervisorTextMessageReceived(m); }
816 
817  // part to send to partner, "forward/relay" to partner
818  if (!partnerCallsign.isEmpty())
819  {
820  // IMPORTANT: partner messages already received
821  CTextMessageList relayedMessages;
822  const CTextMessageList privateMessages = messages.getPrivateMessages();
823  for (const CTextMessage &m : privateMessages)
824  {
825  this->createRelayMessageToPartnerCallsign(m, partnerCallsign, relayedMessages);
826  }
827 
828  if (!relayedMessages.isEmpty())
829  {
830  QPointer<CContextNetwork> myself(this);
831  QTimer::singleShot(10, this, [=] {
832  if (myself) { myself->sendTextMessages(relayedMessages); }
833  });
834  }
835  } // relay to partner
836  }
837  }
838 
839  void CContextNetwork::onTextMessageSent(const CTextMessage &message)
840  {
841  if (message.isEmpty()) { return; }
842  if (message.isRelayedMessage()) { return; }
843 
844  if (message.isPrivateMessage())
845  {
846  // forward messages which are NO real PMs tp the partner
847  const CCallsign partnerCallsign = this->getPartnerCallsign();
848  if (!partnerCallsign.isEmpty() && message.getRecipientCallsign() != partnerCallsign)
849  {
850  QPointer<CContextNetwork> myself(this);
851  CTextMessageList relayedMessages;
852  this->createRelayMessageToPartnerCallsign(message, partnerCallsign, relayedMessages);
853  if (!relayedMessages.isEmpty())
854  {
855  QTimer::singleShot(10, this, [=] {
856  if (myself) { myself->sendTextMessages(relayedMessages); }
857  });
858  }
859  }
860  }
861 
862  emit this->textMessageSent(message);
863  }
864 
865  CSimulatedAircraft CContextNetwork::ownAircraft() const
866  {
867  Q_ASSERT(this->getRuntime()); // must never be null
868 
869  if (!this->getRuntime()->getIContextOwnAircraft()) { return {}; }
870  return this->getRuntime()->getCContextOwnAircraft()->getOwnAircraft();
871  }
872 
874  {
875  return m_fsdClient ? m_fsdClient->getPresetPartnerCallsign() : CCallsign();
876  }
877 
878  bool CContextNetwork::isValidPartnerCallsign(const CCallsign &ownCallsign, const CCallsign &partnerCallsign)
879  {
880  if (partnerCallsign.isEmpty()) { return false; }
881  if (ownCallsign == partnerCallsign) { return false; } // MUST NOT be the same
882  return true;
883  }
884 
886  {
887  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
888  CAtcStationList stations = m_airspace->getAtcStationsOnline();
889  if (!recalculateDistance || !this->getIContextOwnAircraft()) { return stations; }
891  this->getIContextOwnAircraft()->getOwnAircraftSituation());
892  return stations;
893  }
894 
896  {
897  if (!this->getIContextOwnAircraft()) { return CAtcStationList(); }
898  const CAircraftSituation ownSituation = this->getIContextOwnAircraft()->getOwnAircraftSituation();
899  const CAtcStationList stations = m_airspace->getAtcStationsOnline().findClosest(number, ownSituation);
900  return stations;
901  }
902 
904  {
905  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
906  return m_airspace->getAircraftInRange();
907  }
908 
910  {
911  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
912  return m_airspace->getAircraftInRangeCallsigns();
913  }
914 
916  {
917  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
918  return m_airspace->getAircraftInRangeCount();
919  }
920 
921  bool CContextNetwork::isAircraftInRange(const CCallsign &callsign) const
922  {
923  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
924  return m_airspace->isAircraftInRange(callsign);
925  }
926 
927  bool CContextNetwork::isVtolAircraft(const CCallsign &callsign) const
928  {
929  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
930  return m_airspace->isVtolAircraft(callsign);
931  }
932 
934  {
935  if (this->isDebugEnabled())
936  {
937  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
938  }
939  return m_airspace->getAircraftInRangeForCallsign(callsign);
940  }
941 
943  {
944  if (this->isDebugEnabled())
945  {
946  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
947  }
948  return m_airspace->getAircraftInRangeModelForCallsign(callsign);
949  }
950 
952  {
953  if (this->isDebugEnabled())
954  {
955  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
956  }
957  return m_airspace->getReverseLookupMessages(callsign);
958  }
959 
961  {
962  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
963  return m_airspace->isReverseLookupMessagesEnabled();
964  }
965 
966  void CContextNetwork::enableReverseLookupMessages(ReverseLookupLogging enable)
967  {
968  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << enable; }
969  const ReverseLookupLogging revEnabled = m_airspace->isReverseLookupMessagesEnabled();
970  if (revEnabled == enable) { return; }
971  m_airspace->enableReverseLookupMessages(enable);
973  }
974 
976  {
977  if (this->isDebugEnabled())
978  {
979  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
980  }
981  return m_airspace->getAircraftPartsHistory(callsign);
982  }
983 
985  {
986  if (this->isDebugEnabled())
987  {
988  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
989  }
990  return m_airspace->remoteAircraftParts(callsign);
991  }
992 
994  {
995  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
996  return m_airspace->getRemoteAircraftSupportingPartsCount();
997  }
998 
1000  {
1001  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1002  return m_airspace->isAircraftPartsHistoryEnabled();
1003  }
1004 
1006  {
1007  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << enabled; }
1008  m_airspace->enableAircraftPartsHistory(enabled);
1010  }
1011 
1013  {
1014  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1015  return m_airspace->aircraftSituationsAdded();
1016  }
1017 
1019  {
1020  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1021  return m_airspace->aircraftPartsAdded();
1022  }
1023 
1025  {
1026  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1027  return m_airspace->situationsLastModified(callsign);
1028  }
1029 
1030  qint64 CContextNetwork::partsLastModified(const CCallsign &callsign) const
1031  {
1032  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1033  return m_airspace->partsLastModified(callsign);
1034  }
1035 
1036  QString CContextNetwork::getNetworkStatistics(bool reset, const QString &separator)
1037  {
1038  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1039  if (!m_fsdClient) { return QString(); }
1040  return m_fsdClient->getNetworkStatisticsAsText(reset, separator);
1041  }
1042 
1044  {
1045  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1046  if (!m_fsdClient) { return false; }
1047  return m_fsdClient->setStatisticsEnable(enabled);
1048  }
1049 
1050  bool CContextNetwork::testAddAltitudeOffset(const CCallsign &callsign, const CLength &offset)
1051  {
1052  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1053  return m_airspace->testAddAltitudeOffset(callsign, offset);
1054  }
1055 
1057  {
1058  if (!m_fsdClient) { return {}; }
1059  return m_fsdClient->getPresetValues();
1060  }
1061 
1063  {
1064  if (this->isDebugEnabled())
1065  {
1066  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1067  }
1068  return m_airspace->getAtcStationsOnline().findFirstByCallsign(callsign);
1069  }
1070 
1072  {
1073  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1074  return m_airspace->getAtcStationsOnline().findIfFrequencyIsWithinSpacing(frequency);
1075  }
1076 
1077  bool CContextNetwork::isOnlineStation(const CCallsign &callsign) const
1078  {
1079  if (this->isDebugEnabled())
1080  {
1081  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1082  }
1083  return m_airspace->getAtcStationsOnline().containsCallsign(callsign);
1084  }
1085 
1087  {
1088  if (!canUseAirspaceMonitor()) { return; }
1089  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1090  if (!this->isConnected()) { return; }
1091 
1092  m_airspace->requestAircraftDataUpdates();
1093  if (m_requestAircraftDataTimer) { m_requestAircraftDataTimer->start(); } // restart
1094  }
1095 
1097  {
1098  if (!canUseAirspaceMonitor()) { return; }
1099  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1100  if (!this->isConnected()) { return; }
1101 
1102  m_airspace->requestAtisUpdates();
1103  if (m_requestAtisTimer) { m_requestAtisTimer->start(); } // restart
1104  }
1105 
1106  bool CContextNetwork::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering)
1107  {
1108  if (!canUseAirspaceMonitor()) { return false; }
1109  if (this->isDebugEnabled())
1110  {
1111  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << enabledForRendering;
1112  }
1113  const bool c = m_airspace->updateAircraftEnabled(callsign, enabledForRendering);
1114  if (c)
1115  {
1116  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1117  Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1118  emit this->changedRemoteAircraftEnabled(aircraft);
1119  }
1120  return c;
1121  }
1122 
1123  bool CContextNetwork::setAircraftEnabledFlag(const CCallsign &callsign, bool enabledForRendering)
1124  {
1125  if (!canUseAirspaceMonitor()) { return false; }
1126  if (this->isDebugEnabled())
1127  {
1128  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1129  }
1130  return m_airspace->setAircraftEnabledFlag(callsign, enabledForRendering);
1131  }
1132 
1134  const CIdentifier &originator)
1135  {
1136  if (!canUseAirspaceMonitor()) { return false; }
1137  if (this->isDebugEnabled())
1138  {
1139  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1140  }
1141  const bool c = m_airspace->updateAircraftModel(callsign, model, originator);
1142  if (c)
1143  {
1144  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1145  Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1146  emit this->changedRemoteAircraftModel(aircraft, originator); // update aircraft model
1147  }
1148  return c;
1149  }
1150 
1152  const CIdentifier &originator)
1153  {
1154  if (!canUseAirspaceMonitor()) { return false; }
1155  if (this->isDebugEnabled())
1156  {
1157  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1158  }
1159  const bool c = m_airspace->updateAircraftNetworkModel(callsign, model, originator);
1160  if (c)
1161  {
1162  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1163  emit this->changedRemoteAircraftModel(aircraft, originator); // updated network model
1164  }
1165  return c;
1166  }
1167 
1168  bool CContextNetwork::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates)
1169  {
1170  if (!canUseAirspaceMonitor()) { return false; }
1171  if (this->isDebugEnabled())
1172  {
1174  << Q_FUNC_INFO << callsign << enableFastPositonUpdates;
1175  }
1176  const bool c = m_airspace->updateFastPositionEnabled(callsign, enableFastPositonUpdates);
1177  if (c)
1178  {
1179  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1180  CLogMessage(this).info(u"Callsign '%1' fast positions '%2'")
1181  << aircraft.getCallsign() << swift::misc::boolToOnOff(aircraft.fastPositionUpdates());
1182  emit this->changedFastPositionUpdates(aircraft);
1183  }
1184  return c;
1185  }
1186 
1187  bool CContextNetwork::updateAircraftSupportingGndFLag(const CCallsign &callsign, bool supportGndFlag)
1188  {
1189  if (this->isDebugEnabled())
1190  {
1191  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << supportGndFlag;
1192  }
1193  const bool c = m_airspace->setClientGndCapability(callsign, supportGndFlag);
1194  if (c)
1195  {
1196  const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1197  CLogMessage(this).info(u"Callsign '%1' set gnd.capability: %2")
1198  << aircraft.getCallsign() << boolToOnOff(aircraft.isSupportingGndFlag());
1199  emit this->changedGndFlagCapability(aircraft);
1200  }
1201  return c;
1202  }
1203 
1204  bool CContextNetwork::updateCG(const aviation::CCallsign &callsign, const CLength &cg)
1205  {
1206  if (!canUseAirspaceMonitor()) { return false; }
1207  if (this->isDebugEnabled())
1208  {
1210  << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1);
1211  }
1212  const bool c = m_airspace->updateCG(callsign, cg);
1213  return c;
1214  }
1215 
1216  CCallsignSet CContextNetwork::updateCGForModel(const QString &modelString, const CLength &cg)
1217  {
1218  if (!canUseAirspaceMonitor()) { return {}; }
1219  if (this->isDebugEnabled())
1220  {
1222  << Q_FUNC_INFO << modelString << cg.valueRoundedWithUnit(1);
1223  }
1224  const CCallsignSet set = m_airspace->updateCGForModel(modelString, cg);
1225  return set;
1226  }
1227 
1229  const QString &modelString)
1230  {
1231  if (!canUseAirspaceMonitor()) { return false; }
1232  if (this->isDebugEnabled())
1233  {
1235  << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1) << modelString;
1236  }
1237  const bool c = m_airspace->updateCGAndModelString(callsign, cg, modelString);
1238  return c;
1239  }
1240 
1241  bool CContextNetwork::updateAircraftRendered(const CCallsign &callsign, bool rendered)
1242  {
1243  if (!canUseAirspaceMonitor()) { return false; }
1244  const bool c = m_airspace->updateAircraftRendered(callsign, rendered);
1245  return c;
1246  }
1247 
1249  {
1250  if (!canUseAirspaceMonitor()) { return 0; }
1251  const int c = m_airspace->updateMultipleAircraftRendered(callsigns, rendered);
1252  return c;
1253  }
1254 
1256  {
1257  if (!canUseAirspaceMonitor()) { return 0; }
1258  const int c = m_airspace->updateMultipleAircraftEnabled(callsigns, enabled);
1259  return c;
1260  }
1261 
1264  bool *setForOnGroundPosition)
1265  {
1266  if (!canUseAirspaceMonitor()) { return 0; }
1267  return m_airspace->updateAircraftGroundElevation(callsign, elevation, info, setForOnGroundPosition);
1268  }
1269 
1271  {
1272  if (!canUseAirspaceMonitor()) { return; }
1273  m_airspace->updateMarkAllAsNotRendered();
1274  }
1275 
1277  {
1278  if (!canUseAirspaceMonitor()) { return {}; }
1279  return m_airspace->getCGFromDB(callsign);
1280  }
1281 
1282  CLength CContextNetwork::getCGFromDB(const QString &modelString) const
1283  {
1284  if (!canUseAirspaceMonitor()) { return {}; }
1285  return m_airspace->getCGFromDB(modelString);
1286  }
1287 
1288  void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const CCallsign &callsign)
1289  {
1290  if (!canUseAirspaceMonitor()) { return; }
1291  m_airspace->rememberCGFromDB(cgFromDB, callsign);
1292  }
1293 
1294  void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const QString &modelString)
1295  {
1296  if (!canUseAirspaceMonitor()) { return; }
1297  m_airspace->rememberCGFromDB(cgFromDB, modelString);
1298  }
1299 
1301  {
1302  if (!canUseAirspaceMonitor()) { return 0; }
1303  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1304  return m_airspace->reInitializeAllAircraft();
1305  }
1306 
1308  {
1309  if (!canUseAirspaceMonitor()) { return {}; }
1310  return m_airspace->getLatestAirspaceAircraftSnapshot();
1311  }
1312 
1314  const CLength &range, int minValues,
1315  int sufficientValues) const
1316  {
1317  if (!canUseAirspaceMonitor()) { return {}; }
1318  return m_airspace->averageElevationOfNonMovingAircraft(reference, range, minValues, sufficientValues);
1319  }
1320 
1321  void CContextNetwork::setClients(const CClientList &clients) { m_airspace->setClients(clients); }
1322 
1324 
1326  {
1327  if (!canUseAirspaceMonitor()) { return {}; }
1328  return m_airspace->getClientOrDefaultForCallsign(callsign);
1329  }
1330 
1332  {
1333  if (!canUseAirspaceMonitor()) { return false; }
1334  return m_airspace->hasClientInfo(callsign);
1335  }
1336 
1338  {
1339  if (!canUseAirspaceMonitor()) { return false; }
1340  return m_airspace->addNewClient(client);
1341  }
1342 
1344  bool skipEqualValues)
1345  {
1346  if (!canUseAirspaceMonitor()) { return 0; }
1347  return m_airspace->updateOrAddClient(callsign, vm, skipEqualValues);
1348  }
1349 
1351  {
1352  if (this->isDebugEnabled())
1353  {
1354  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsigns;
1355  }
1356  Q_ASSERT(m_fsdClient);
1357  m_fsdClient->setInterimPositionReceivers(callsigns);
1358  }
1359 
1361  {
1362  if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO; }
1363  Q_ASSERT(m_fsdClient);
1364  return m_fsdClient->getInterimPositionReceivers();
1365  }
1366 
1368  {
1369  if (!this->canUseFsd()) { return; }
1370  if (this->isDebugEnabled())
1371  {
1372  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1373  }
1374  m_fsdClient->sendClientQueryAircraftConfig(callsign);
1375  }
1376 
1378  {
1379  if (!this->canUseAirspaceMonitor()) { return; }
1380  if (this->isDebugEnabled())
1381  {
1382  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << number;
1383  }
1384  m_airspace->testCreateDummyOnlineAtcStations(number);
1385  }
1386 
1387  void CContextNetwork::testAddAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool incremental)
1388  {
1389  if (!this->canUseAirspaceMonitor()) { return; }
1390  if (this->isDebugEnabled())
1391  {
1392  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << parts << incremental;
1393  }
1394  m_airspace->testAddAircraftParts(callsign, parts, incremental);
1395  }
1396 
1398  {
1399  if (!this->canUseFsd()) { return; }
1400  if (this->isDebugEnabled())
1401  {
1402  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign.asString();
1403  }
1404  emit this->fsdClient()->atisReplyReceived(callsign, msg);
1405  }
1406 
1408  {
1409  if (!this->canUseFsd()) { return; }
1410  if (this->isDebugEnabled())
1411  {
1412  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages.toQString();
1413  }
1414  emit this->fsdClient()->textMessagesReceived(textMessages);
1415  }
1416 
1418  {
1419  if (this->isDebugEnabled())
1420  {
1421  CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << airportIcaoCode;
1422  }
1423  if (!sApp || !sApp->getWebDataServices()) { return {}; }
1424  return sApp->getWebDataServices()->getMetarForAirport(airportIcaoCode);
1425  }
1426 
1427  QMetaObject::Connection
1428  CContextNetwork::connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
1429  {
1430  Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
1431 
1432  // bind does not allow to define connection type, so we use receiver as workaround
1433  const QMetaObject::Connection uc; // unconnected
1434  const QMetaObject::Connection c = rawFsdMessageReceivedSlot ? connect(m_fsdClient, &CFSDClient::rawFsdMessage,
1435  receiver, rawFsdMessageReceivedSlot) :
1436  uc;
1437  Q_ASSERT_X(c || !rawFsdMessageReceivedSlot, Q_FUNC_INFO, "connect failed");
1438  return c;
1439  }
1440 } // 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:515
context::CContextOwnAircraft * getCContextOwnAircraft()
Context for own aircraft.
Definition: corefacade.cpp:501
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:597
virtual void rememberCGFromDB(const swift::misc::physical_quantities::CLength &cgFromDB, const swift::misc::aviation::CCallsign &callsign)
CG values from DB.
virtual bool setNetworkStatisticsEnable(bool enabled)
Statistics enable/disable.
virtual 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.
virtual swift::misc::network::CLoginMode getLoginMode() const
Login mode.
virtual 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)
virtual swift::misc::CStatusMessageList getAircraftPartsHistory(const swift::misc::aviation::CCallsign &callsign) const
Get aircraft parts history.
virtual void setFastPositionEnabledCallsigns(swift::misc::aviation::CCallsignSet &callsigns)
Callsigns enabled for fast position updates.
virtual int updateMultipleAircraftRendered(const swift::misc::aviation::CCallsignSet &callsigns, bool rendered)
Set aircraft rendered.
virtual swift::misc::MillisecondsMinMaxMean remoteAircraftSituationsTimestampDifferenceMinMaxMean(const swift::misc::aviation::CCallsign &callsign) const
Average update time.
virtual swift::misc::aviation::CCallsignSet remoteAircraftSupportingParts() const
Remote aircraft supporting parts.
virtual bool isRemoteAircraftSupportingParts(const swift::misc::aviation::CCallsign &callsign) const
Parts supported?
virtual swift::misc::aviation::CCallsignSet getFastPositionEnabledCallsigns() const
Callsigns enabled for fast position updates.
virtual swift::misc::aviation::CCallsign getPartnerCallsign() const
Partner callsign if any.
virtual swift::misc::aviation::CAircraftPartsList getRemoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
Get remote aircraft parts.
virtual swift::misc::aviation::CAtcStationList getAtcStationsOnline(bool recalculateDistance) const
The ATC list with online ATC controllers.
virtual int updateOrAddClient(const swift::misc::aviation::CCallsign &callsign, const swift::misc::CPropertyIndexVariantMap &vm, bool skipEqualValues=true)
Update or add a client.
virtual bool hasClientInfo(const swift::misc::aviation::CCallsign &callsign) const
Client info for given callsign?
virtual QStringList getNetworkPresetValues() const
Network preset values.
virtual void enableAircraftPartsHistory(bool enabled)
Enable storing of aircraft parts.
virtual int getRemoteAircraftSupportingPartsCount() const
Number of aircraft supporting parts.
virtual qint64 partsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
virtual 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.
virtual swift::misc::aviation::CAircraftSituationList latestOnGroundProviderElevations() const
Latest aircraft situation "on ground" having a provider elevation.
virtual void setClients(const swift::misc::network::CClientList &clients)
Set other clients.
virtual bool updateAircraftEnabled(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
virtual swift::misc::CStatusMessageList getReverseLookupMessages(const swift::misc::aviation::CCallsign &callsign) const
Get reverse lookup messages.
virtual swift::misc::aviation::CAircraftSituationList latestRemoteAircraftSituations() const
Latest aircraft situation for all callsigns.
virtual swift::misc::aviation::CAtcStation getOnlineStationForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign.
virtual bool addClientGndCapability(const swift::misc::aviation::CCallsign &callsign)
Add gnd.flag capability.
virtual 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.
virtual swift::misc::CStatusMessage disconnectFromNetwork()
Disconnect from network.
virtual swift::misc::aviation::CAtcStationList getOnlineStationsForFrequency(const swift::misc::physical_quantities::CFrequency &frequency) const
Online stations for frequency.
virtual swift::misc::aviation::CAircraftSituation remoteAircraftSituation(const swift::misc::aviation::CCallsign &callsign, int index) const
Rendered aircraft situations (per callsign and index)
virtual bool isAircraftPartsHistoryEnabled() const
Is storing the aircraft parts history enabled?
virtual swift::misc::network::CClientList getClientsForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Returns a list of other clients corresponding to the given callsigns.
virtual void sendTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Text messages (radio and private chat messages)
virtual int getAircraftInRangeCount() const
Aircraft count.
virtual bool setAircraftEnabledFlag(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Set the enabled flag without any further logic like sending signals.
virtual int removeClient(const swift::misc::aviation::CCallsign &callsign)
Remove client.
virtual swift::misc::network::CUserList getUsers() const
Get all users.
virtual bool setOtherClient(const swift::misc::network::CClient &client)
Set client for its callsign.
void gracefulShutdown()
Gracefully shut down, e.g. for thread safety.
virtual swift::misc::simulation::CSimulatedAircraftList getAircraftInRange() const
Aircraft list.
virtual swift::misc::simulation::CAircraftModel getAircraftInRangeModelForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft model for callsign.
virtual QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
Connect to receive raw fsd messages.
virtual bool isOnlineStation(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign?
virtual swift::misc::network::CServerList getVatsimFsdServers() const
Known FSD servers, available when data file was first read.
virtual 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.
virtual bool updateAircraftRendered(const swift::misc::aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
virtual void requestAircraftDataUpdates()
Request data updates (pilot's frequencies, ATIS, ..)
virtual int aircraftPartsAdded() const
Number of parts added.
virtual void testAddAircraftParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftParts &parts, bool incremental)
Inject aircraft parts for testing.
virtual bool addNewClient(const swift::misc::network::CClient &client)
Add a new client, if existing nothing will be added.
virtual bool updateAircraftNetworkModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change network model.
virtual 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...
virtual int reInitializeAllAircraft()
Re-initialize all aircraft.
virtual swift::misc::aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes.
virtual void testReceivedTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Inject a text message as received.
virtual swift::misc::network::CUserList getUsersForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Users for given callsigns, e.g. for voice room resolution.
virtual void testCreateDummyOnlineAtcStations(int number)
Create dummy ATC stations for performance tests etc.
virtual swift::misc::physical_quantities::CLength getCGFromDB(const swift::misc::aviation::CCallsign &callsign) const
CG values from DB.
virtual void enableReverseLookupMessages(swift::misc::simulation::ReverseLookupLogging enable)
Enable reverse lookup logging.
virtual bool autoAdjustCientGndCapability(const swift::misc::aviation::CAircraftSituation &situation)
Adjust gnd.flag capability from situation.
virtual swift::misc::aviation::CAtcStationList getClosestAtcStationsOnline(int number) const
The ATC list with online ATC controllers.
virtual bool isAircraftInRange(const swift::misc::aviation::CCallsign &callsign) const
Aircraft in range.
virtual void updateMarkAllAsNotRendered()
Mark all as not rendered.
virtual swift::misc::simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft for given callsign.
virtual void testRequestAircraftConfig(const swift::misc::aviation::CCallsign &callsign)
Request parts for callsign (from another client)
virtual 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.
virtual swift::misc::aviation::CCallsignSet getAircraftInRangeCallsigns() const
Aircraft callsigns.
virtual swift::misc::network::CClient getClientOrDefaultForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Other client for the given callsigns.
static void registerHelp()
Register help.
virtual bool updateAircraftSupportingGndFLag(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Enable/disable support of gnd. flag.
virtual void sendFlightPlan(const swift::misc::aviation::CFlightPlan &flightPlan)
Send flight plan.
virtual int remoteAircraftSituationsCount(const swift::misc::aviation::CCallsign &callsign) const
Number of remote aircraft situations for callsign.
virtual bool updateFastPositionEnabled(const swift::misc::aviation::CCallsign &callsign, bool enableFastPositonUpdates)
Change fast position updates.
void setSimulationEnvironmentProvider(swift::misc::simulation::ISimulationEnvironmentProvider *provider)
Set the provider.
virtual 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.
virtual int remoteAircraftPartsCount(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history)
virtual int updateMultipleAircraftEnabled(const swift::misc::aviation::CCallsignSet &callsigns, bool enabled)
Enable/disable aircraft.
virtual swift::misc::network::CServer getConnectedServer() const
Server which is connected, if not connected empty default object.
virtual int remoteAircraftSituationChangesCount(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes count.
virtual swift::misc::aviation::CFlightPlan loadFlightPlanFromNetwork(const swift::misc::aviation::CCallsign &callsign) const
Load flight plan (from network)
virtual void testReceivedAtisMessage(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &msg)
Inject an ATIS.
virtual bool updateAircraftModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change model.
virtual swift::misc::network::CClientList getClients() const
Get other clients.
virtual swift::misc::simulation::ReverseLookupLogging isReverseLookupMessagesEnabled() const
Enabled reverse lookup logging?
virtual QString getNetworkStatistics(bool reset, const QString &separator)
Statistics info.
virtual void clearClients()
Set other clients.
virtual swift::misc::simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const
Current snapshot.
virtual swift::misc::aviation::CAircraftSituationList remoteAircraftSituations(const swift::misc::aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history)
virtual qint64 situationsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
virtual bool setClientGndCapability(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Set gnd.flag capability.
virtual swift::misc::network::CUser getUserForCallsign(const swift::misc::aviation::CCallsign &callsign) const
User for given callsign, e.g. for text messages.
virtual int aircraftSituationsAdded() const
Number of situations added.
virtual swift::misc::aviation::CAircraftPartsList remoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history)
virtual bool updateCG(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &cg)
Update the CG.
virtual bool isVtolAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is VTOL aircraft?
virtual bool isConnected() const
Network connected?
virtual void requestAtisUpdates()
Request ATIS updates (for all stations)
virtual 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:2110
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:2100
void setClientName(const QString &clientName)
Preset functions.
Definition: fsdclient.h:102
void gracefulShutdown()
Gracefully shut down FSD client.
Definition: fsdclient.cpp:2188
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:2105
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:2142
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
virtual int removeClient(const aviation::CCallsign &callsign)
Remove client.
virtual int updateOrAddClient(const aviation::CCallsign &callsign, const CPropertyIndexVariantMap &vm, bool skipEqualValues=true)
Update or add a client.
virtual bool hasClientInfo(const aviation::CCallsign &callsign) const
Client info for given callsign?
virtual bool addClientGndCapability(const aviation::CCallsign &callsign)
Add gnd.flag capability.
virtual CClientList getClientsForCallsigns(const aviation::CCallsignSet &callsigns) const
Returns a list of other clients corresponding to the given callsigns.
virtual void markAsSwiftClient(const aviation::CCallsign &callsign)
Mark as other swift client.
virtual bool setOtherClient(const swift::misc::network::CClient &client)
Set client for its callsign.
virtual bool addNewClient(const CClient &client)
Add a new client, if existing nothing will be added.
virtual void setClients(const CClientList &clients)
Set other clients.
virtual CClientList getClients() const
clientprovider
virtual void clearClients()
Set other clients.
virtual CClient getClientOrDefaultForCallsign(const aviation::CCallsign &callsign) const
Other client for the given callsigns.
virtual bool setClientGndCapability(const aviation::CCallsign &callsign, bool supportGndFlag)
Set gnd.flag capability.
virtual 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)
virtual swift::misc::CStatusMessageList getReverseLookupMessages(const swift::misc::aviation::CCallsign &callsign) const
Get reverse lookup meesages.
virtual bool isAircraftInRange(const aviation::CCallsign &callsign) const
Is aircraft in range?
virtual int remoteAircraftSituationChangesCount(const aviation::CCallsign &callsign) const
Aircraft changes count.
virtual void updateMarkAllAsNotRendered()
Mark all as not rendered.
virtual int updateMultipleAircraftRendered(const aviation::CCallsignSet &callsigns, bool rendered)
Set aircraft rendered.
virtual CSimulatedAircraftList getAircraftInRange() const
All remote aircraft.
virtual bool updateCGAndModelString(const aviation::CCallsign &callsign, const physical_quantities::CLength &cg, const QString &modelString)
Update the CG and model string.
virtual bool setAircraftEnabledFlag(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Just set enable/disable aircraft flag, no further logic.
virtual aviation::CCallsignSet remoteAircraftSupportingParts() const
Remote aircraft supporting parts.
virtual int getRemoteAircraftSupportingPartsCount() const
Number of aircraft supporting parts.
virtual qint64 situationsLastModified(const aviation::CCallsign &callsign) const
When last modified.
void changedAircraftInRange()
Aircraft were changed.
virtual bool isAircraftPartsHistoryEnabled() const
Is storing aircraft parts history enabled?
virtual int remoteAircraftSituationsCount(const aviation::CCallsign &callsign) const
Number of remote aircraft situations for callsign.
virtual aviation::CAircraftSituation remoteAircraftSituation(const aviation::CCallsign &callsign, int index) const
Rendered aircraft situations (per callsign and index)
virtual 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.
virtual aviation::CAircraftSituationList remoteAircraftSituations(const aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history)
virtual bool isVtolAircraft(const aviation::CCallsign &callsign) const
Is VTOL aircraft?
virtual aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const aviation::CCallsign &callsign) const
Aircraft changes.
virtual MillisecondsMinMaxMean remoteAircraftSituationsTimestampDifferenceMinMaxMean(const aviation::CCallsign &callsign) const
Average update time.
virtual aviation::CCallsignSet updateCGForModel(const QString &modelString, const physical_quantities::CLength &cg)
Update the CG for this model string.
virtual void enableAircraftPartsHistory(bool enabled)
Enable storing of aircraft parts history.
virtual CStatusMessageList getAircraftPartsHistory(const aviation::CCallsign &callsign) const
Get aircraft parts history.
void addedAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
A new aircraft appeared.
virtual int remoteAircraftPartsCount(const aviation::CCallsign &callsign) const
All parts (per callsign, time history)
virtual bool updateAircraftEnabled(const aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
virtual void rememberCGFromDB(const physical_quantities::CLength &cgFromDB, const aviation::CCallsign &callsign)
CG values from DB.
virtual int aircraftPartsAdded() const
Number of parts added.
virtual aviation::CAircraftSituationList latestRemoteAircraftSituations() const
Latest aircraft situation for all callsigns.
virtual bool updateAircraftNetworkModel(const aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator)
Change network model.
virtual bool updateAircraftModel(const aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator)
Change model.
virtual physical_quantities::CLength getCGFromDB(const aviation::CCallsign &callsign) const
CG values from DB.
virtual qint64 partsLastModified(const aviation::CCallsign &callsign) const
When last modified.
virtual 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...
virtual bool updateAircraftRendered(const aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
virtual aviation::CAircraftSituationList latestOnGroundProviderElevations() const
Latest aircraft situation "on ground" having a provider elevation.
virtual aviation::CCallsignSet getAircraftInRangeCallsigns() const
Unique callsigns for aircraft in range.
virtual ReverseLookupLogging isReverseLookupMessagesEnabled() const
Enabled reverse lookup logging?
virtual CAircraftModel getAircraftInRangeModelForCallsign(const aviation::CCallsign &callsign) const
Aircraft model for callsign.
virtual CSimulatedAircraft getAircraftInRangeForCallsign(const aviation::CCallsign &callsign) const
Aircraft for callsign.
virtual int aircraftSituationsAdded() const
Number of situations added.
virtual aviation::CAircraftPartsList remoteAircraftParts(const aviation::CCallsign &callsign) const
All parts (per callsign, time history)
virtual void enableReverseLookupMessages(ReverseLookupLogging enable)
Enable reverse lookup logging.
virtual int updateMultipleAircraftEnabled(const aviation::CCallsignSet &callsigns, bool enabledForRendering)
Enable/disable aircraft.
virtual bool updateCG(const aviation::CCallsign &callsign, const physical_quantities::CLength &cg)
Update the CG.
virtual bool isRemoteAircraftSupportingParts(const aviation::CCallsign &callsign) const
Is remote aircraft supporting parts?
virtual 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.
virtual 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
virtual 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.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30
Milliseconds minimum/maximum/mean.