AirMapManager.cc 10 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

Gus Grubba's avatar
Gus Grubba committed
10
#include "AirMapAdvisoryManager.h"
Gus Grubba's avatar
Gus Grubba committed
11 12 13
#include "AirMapFlightPlanManager.h"
#include "AirMapManager.h"
#include "AirMapRestrictionManager.h"
14 15 16 17
#include "AirMapRulesetsManager.h"
#include "AirMapSettings.h"
#include "AirMapTelemetry.h"
#include "AirMapTrafficMonitor.h"
Gus Grubba's avatar
Gus Grubba committed
18
#include "AirMapVehicleManager.h"
Gus Grubba's avatar
Gus Grubba committed
19
#include "AirMapWeatherInfoManager.h"
20

21 22 23 24
#include "QmlObjectListModel.h"
#include "JsonHelper.h"
#include "SettingsManager.h"
#include "AppSettings.h"
25
#include "QGCQGeoCoordinate.h"
26
#include "QGCApplication.h"
27

28
#include <airmap/authenticator.h>
29

Gus Grubba's avatar
Gus Grubba committed
30 31 32 33 34
//-- Hardwired API key
#if defined(QGC_AIRMAP_KEY_AVAILABLE)
#include "Airmap_api_key.h"
#endif

35
using namespace airmap;
36

37
QGC_LOGGING_CATEGORY(AirMapManagerLog, "AirMapManagerLog")
38

39
//-----------------------------------------------------------------------------
40 41
AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox)
    : AirspaceManager(app, toolbox)
42
    , _authStatus(Unknown)
43
{
44
    _logger = std::make_shared<qt::Logger>();
45
    qt::register_types(); // TODO: still needed?
46 47 48
    _logger->logging_category().setEnabled(QtDebugMsg,   false);
    _logger->logging_category().setEnabled(QtInfoMsg,    false);
    _logger->logging_category().setEnabled(QtWarningMsg, false);
49 50
    _dispatchingLogger = std::make_shared<qt::DispatchingLogger>(_logger);
    connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error);
51
    connect(&_shared, &AirMapSharedState::authStatus, this, &AirMapManager::_authStatusChanged);
52 53
}

54
//-----------------------------------------------------------------------------
55 56 57 58 59
AirMapManager::~AirMapManager()
{
    if (_shared.client()) {
        delete _shared.client();
    }
60 61
}

62
//-----------------------------------------------------------------------------
63 64
void
AirMapManager::setToolbox(QGCToolbox* toolbox)
65
{
66
    _settingsTimer.setSingleShot(true);
67
    AirspaceManager::setToolbox(toolbox);
68
    AirMapSettings* ap = toolbox->settingsManager()->airMapSettings();
Gus Grubba's avatar
Gus Grubba committed
69
    connect(ap->enableAirMap(),     &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
70 71 72 73 74
    connect(ap->usePersonalApiKey(),&Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
    connect(ap->apiKey(),           &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
    connect(ap->clientID(),         &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
    connect(ap->userName(),         &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
    connect(ap->password(),         &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged);
75
    connect(ap->enableAirspace(),   &Fact::rawValueChanged, this, &AirMapManager::_airspaceEnabled);
76 77
    connect(&_settingsTimer,        &QTimer::timeout,       this, &AirMapManager::_settingsTimeout);
    _settingsTimeout();
78 79
}

Gus Grubba's avatar
Gus Grubba committed
80 81 82 83
//-----------------------------------------------------------------------------
bool
AirMapManager::connected() const
{
84
    return _shared.client() != nullptr;
Gus Grubba's avatar
Gus Grubba committed
85 86
}

87
//-----------------------------------------------------------------------------
88 89
void
AirMapManager::_error(const QString& what, const QString& airmapdMessage, const QString& airmapdDetails)
90
{
91
    qCDebug(AirMapManagerLog) << "Error: "<<what<<", msg: "<<airmapdMessage<<", details: "<<airmapdDetails;
92
    qgcApp()->showMessage(QString("Error: %1. %2").arg(what).arg(airmapdMessage));
93 94
}

95 96 97 98 99 100 101 102
//-----------------------------------------------------------------------------
void
AirMapManager::_authStatusChanged(AirspaceManager::AuthStatus status)
{
    _authStatus = status;
    emit authStatusChanged();
}

103
//-----------------------------------------------------------------------------
104 105
void
AirMapManager::_settingsChanged()
106 107 108 109
{
    _settingsTimer.start(1000);
}

110 111 112 113 114 115 116 117 118 119 120
//-----------------------------------------------------------------------------
void
AirMapManager::_airspaceEnabled()
{
    if(qgcApp()->toolbox()->settingsManager()->airMapSettings()->enableAirspace()->rawValue().toBool()) {
        if(_airspaces) {
            _airspaces->setROI(_roi, true);
        }
    }
}

121 122 123
//-----------------------------------------------------------------------------
void
AirMapManager::_settingsTimeout()
124 125
{
    qCDebug(AirMapManagerLog) << "AirMap settings changed";
Gus Grubba's avatar
Gus Grubba committed
126 127
    _connectStatus.clear();
    emit connectStatusChanged();
128
    AirMapSettings* ap = _toolbox->settingsManager()->airMapSettings();
Gus Grubba's avatar
Gus Grubba committed
129 130
    //-- If we are disabled, there is nothing else to do.
    if (!ap->enableAirMap()->rawValue().toBool()) {
131
        _shared.logout();
Gus Grubba's avatar
Gus Grubba committed
132 133 134 135 136 137 138
        if(_shared.client()) {
            delete _shared.client();
            _shared.setClient(nullptr);
            emit connectedChanged();
        }
        return;
    }
139
    AirMapSharedState::Settings settings;
Gus Grubba's avatar
Gus Grubba committed
140 141 142 143 144
    if(ap->usePersonalApiKey()->rawValue().toBool()) {
        settings.apiKey     = ap->apiKey()->rawValueString();
        settings.clientID   = ap->clientID()->rawValueString();
    }
    //-- If we have a hardwired key (and no custom key is present), set it.
Gus Grubba's avatar
Gus Grubba committed
145
#if defined(QGC_AIRMAP_KEY_AVAILABLE)
Gus Grubba's avatar
Gus Grubba committed
146
    if(!ap->usePersonalApiKey()->rawValue().toBool()) {
147 148
        settings.apiKey     = AirmapAPIKey();
        settings.clientID   = AirmapClientID();
Gus Grubba's avatar
Gus Grubba committed
149
    }
150
    bool authChanged = settings.apiKey != _shared.settings().apiKey || settings.apiKey.isEmpty();
Gus Grubba's avatar
Gus Grubba committed
151
#else
152
    bool authChanged = settings.apiKey != _shared.settings().apiKey;
Gus Grubba's avatar
Gus Grubba committed
153
#endif
154 155 156 157 158
    settings.userName = ap->userName()->rawValueString();
    settings.password = ap->password()->rawValueString();
    if(settings.userName != _shared.settings().userName || settings.password != _shared.settings().password) {
        authChanged = true;
    }
159
    _shared.setSettings(settings);
160 161
    //-- Need to re-create the client if the API key or user name/password changed
    if ((_shared.client() && authChanged) || !ap->enableAirMap()->rawValue().toBool()) {
162 163
        delete _shared.client();
        _shared.setClient(nullptr);
Gus Grubba's avatar
Gus Grubba committed
164
        emit connectedChanged();
165
    }
166 167 168 169
    if (!_shared.client() && settings.apiKey != "") {
        qCDebug(AirMapManagerLog) << "Creating AirMap client";
        auto credentials    = Credentials{};
        credentials.api_key = _shared.settings().apiKey.toStdString();
170
        auto configuration  = Client::default_production_configuration(credentials);
171 172
        configuration.telemetry.host = "udp.telemetry.k8s.airmap.io";
        configuration.telemetry.port = 7070;
Gus Grubba's avatar
Gus Grubba committed
173
        qt::Client::create(configuration, _dispatchingLogger, this, [this](const qt::Client::CreateResult& result) {
174 175 176
            if (result) {
                qCDebug(AirMapManagerLog) << "Successfully created airmap::qt::Client instance";
                _shared.setClient(result.value());
Gus Grubba's avatar
Gus Grubba committed
177 178 179
                emit connectedChanged();
                _connectStatus = tr("AirMap Enabled");
                emit connectStatusChanged();
180 181
                //-- Now test authentication
                _shared.login();
182 183
            } else {
                qWarning("Failed to create airmap::qt::Client instance");
184
                QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
Gus Grubba's avatar
Gus Grubba committed
185 186 187 188 189 190 191 192 193
                QString error = QString::fromStdString(result.error().message());
                _error(tr("Failed to create airmap::qt::Client instance"),
                        error, description);
                _connectStatus = error;
                if(!description.isEmpty()) {
                    _connectStatus += "\n";
                    _connectStatus += description;
                }
                emit connectStatusChanged();
194 195
            }
        });
196 197
    } else {
        if(settings.apiKey == "") {
Gus Grubba's avatar
Gus Grubba committed
198 199 200
            _connectStatus = tr("No API key for AirMap");
            emit connectStatusChanged();
            qCDebug(AirMapManagerLog) << _connectStatus;
201
        }
202 203 204
    }
}

205
//-----------------------------------------------------------------------------
206 207
AirspaceVehicleManager*
AirMapManager::instantiateVehicle(const Vehicle& vehicle)
208
{
209
    AirMapVehicleManager* manager = new AirMapVehicleManager(_shared, vehicle);
210
    connect(manager, &AirMapVehicleManager::error, this, &AirMapManager::_error);
211
    return manager;
212 213
}

214
//-----------------------------------------------------------------------------
215
AirspaceRulesetsProvider*
216
AirMapManager::_instantiateRulesetsProvider()
Gus Grubba's avatar
Gus Grubba committed
217 218 219 220 221 222
{
    AirMapRulesetsManager* rulesetsManager = new AirMapRulesetsManager(_shared);
    connect(rulesetsManager, &AirMapRulesetsManager::error, this, &AirMapManager::_error);
    return rulesetsManager;
}

223
//-----------------------------------------------------------------------------
224
AirspaceWeatherInfoProvider*
225
AirMapManager::_instatiateAirspaceWeatherInfoProvider()
Gus Grubba's avatar
Gus Grubba committed
226
{
Gus Grubba's avatar
Gus Grubba committed
227 228
    AirMapWeatherInfoManager* weatherInfo = new AirMapWeatherInfoManager(_shared);
    connect(weatherInfo, &AirMapWeatherInfoManager::error, this, &AirMapManager::_error);
229
    return weatherInfo;
Gus Grubba's avatar
Gus Grubba committed
230
}
Gus Grubba's avatar
Gus Grubba committed
231

232
//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
233
AirspaceAdvisoryProvider*
234
AirMapManager::_instatiateAirspaceAdvisoryProvider()
Gus Grubba's avatar
Gus Grubba committed
235
{
Gus Grubba's avatar
Gus Grubba committed
236 237
    AirMapAdvisoryManager* advisories = new AirMapAdvisoryManager(_shared);
    connect(advisories, &AirMapAdvisoryManager::error, this, &AirMapManager::_error);
Gus Grubba's avatar
Gus Grubba committed
238 239
    return advisories;
}
240

241
//-----------------------------------------------------------------------------
242
AirspaceRestrictionProvider*
243
AirMapManager::_instantiateAirspaceRestrictionProvider()
244 245 246 247 248
{
    AirMapRestrictionManager* airspaces = new AirMapRestrictionManager(_shared);
    connect(airspaces, &AirMapRestrictionManager::error, this, &AirMapManager::_error);
    return airspaces;
}
249 250

//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
251 252
AirspaceFlightPlanProvider*
AirMapManager::_instantiateAirspaceFlightPlanProvider()
253
{
Gus Grubba's avatar
Gus Grubba committed
254 255 256
    AirMapFlightPlanManager* flightPlan = new AirMapFlightPlanManager(_shared);
    connect(flightPlan, &AirMapFlightPlanManager::error, this, &AirMapManager::_error);
    return flightPlan;
257
}