swift
afvmapreader.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2019 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "core/afv/model/afvmapreader.h"
5 
6 #include <QEventLoop>
7 #include <QJsonArray>
8 #include <QJsonDocument>
9 #include <QJsonObject>
10 #include <QNetworkReply>
11 
12 #include "core/afv/dto.h"
13 #include "core/application.h"
14 #include "misc/aviation/callsign.h"
15 
16 using namespace swift::misc::aviation;
17 
18 namespace swift::core::afv::model
19 {
20  CAfvMapReader::CAfvMapReader(QObject *parent) : QObject(parent)
21  {
22  m_model = new CSampleAtcStationModel(this);
23  m_timer = new QTimer(this);
24  connect(m_timer, &QTimer::timeout, this, &CAfvMapReader::updateFromMap);
25  m_timer->start(3000);
26  }
27 
29  {
30  if (!sApp || !sApp->getNetworkAccessManager() || sApp->isShuttingDown()) { return; }
31 
32  QEventLoop loop(sApp);
33  connect(sApp->getNetworkAccessManager(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
34  connect(sApp, &CApplication::aboutToShutdown, &loop, &QEventLoop::quit);
35  const QUrl url =
36  sApp->getGlobalSetup().getAfvApiServerUrl().withAppendedPath("/api/v1/network/online/callsigns");
37  QNetworkReply *reply = sApp->getNetworkAccessManager()->get(QNetworkRequest(url));
38  while (reply && !reply->isFinished() && sApp && !sApp->isShuttingDown()) { loop.exec(); }
39  const QByteArray jsonData = reply ? reply->readAll() : QByteArray {};
40  if (reply) { reply->deleteLater(); }
41 
42  if (jsonData.isEmpty()) { return; }
43 
44  QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
45  if (jsonDoc.isArray())
46  {
47  const QJsonArray rootArray = jsonDoc.array();
48  QVector<CSampleAtcStation> transceivers;
49  QString callsign;
50 
51  for (auto it = rootArray.begin(); it != rootArray.end(); ++it)
52  {
53  if (it->isObject())
54  {
55  const QJsonObject stationObject = it->toObject();
56 
57  if (stationObject.contains("callsign")) { callsign = stationObject.value("callsign").toString(); }
58 
59  if (callsign.isEmpty() || !CCallsign::looksLikeAtcCallsign(callsign)) { continue; }
60 
61  if (stationObject.contains("transceivers"))
62  {
63  QJsonArray txArray = stationObject.value("transceivers").toArray();
64  for (auto jt = txArray.begin(); jt != txArray.end(); ++jt)
65  {
66  const TransceiverDto transceiver = TransceiverDto::fromJson(jt->toObject());
67  transceivers.push_back({ callsign, transceiver });
68  }
69  }
70  }
71  }
72 
73  if (transceivers.isEmpty()) { return; }
74  transceivers.erase(
75  std::remove_if(transceivers.begin(), transceivers.end(),
76  [this](const CSampleAtcStation &s) { return s.callsign() == m_callsign; }),
77  transceivers.end());
78  m_model->updateAtcStations(transceivers);
79  }
80  }
81 } // namespace swift::core::afv::model
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
void aboutToShutdown()
About to shutdown.
const QNetworkAccessManager * getNetworkAccessManager() const
Access to access manager.
Definition: application.h:427
data::CGlobalSetup getGlobalSetup() const
Global setup.
bool isShuttingDown() const
Is application shutting down?
void updateFromMap()
Update ATC stations in model.
void updateAtcStations(const QVector< CSampleAtcStation > &atcStations)
Update the stations.
swift::misc::network::CUrl getAfvApiServerUrl() const
AFV voice server URL.
Definition: globalsetup.h:137
CUrl withAppendedPath(const QString &path) const
Append path.
Definition: url.cpp:115
Transceiver DTO.
Definition: dto.h:117
static TransceiverDto fromJson(const QJsonObject &json)
From JSON.
Definition: dto.h:143