AirMapManager.cc 9.63 KB
Newer Older
1 2
/****************************************************************************
 *
3
 *   (c) 2017 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 76
    connect(&_settingsTimer,        &QTimer::timeout,       this, &AirMapManager::_settingsTimeout);
    _settingsTimeout();
77 78
}

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

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

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

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

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

193
//-----------------------------------------------------------------------------
194 195
AirspaceVehicleManager*
AirMapManager::instantiateVehicle(const Vehicle& vehicle)
196
{
197
    AirMapVehicleManager* manager = new AirMapVehicleManager(_shared, vehicle);
198
    connect(manager, &AirMapVehicleManager::error, this, &AirMapManager::_error);
199
    return manager;
200 201
}

202
//-----------------------------------------------------------------------------
203
AirspaceRulesetsProvider*
204
AirMapManager::_instantiateRulesetsProvider()
Gus Grubba's avatar
Gus Grubba committed
205 206 207 208 209 210
{
    AirMapRulesetsManager* rulesetsManager = new AirMapRulesetsManager(_shared);
    connect(rulesetsManager, &AirMapRulesetsManager::error, this, &AirMapManager::_error);
    return rulesetsManager;
}

211
//-----------------------------------------------------------------------------
212
AirspaceWeatherInfoProvider*
213
AirMapManager::_instatiateAirspaceWeatherInfoProvider()
Gus Grubba's avatar
Gus Grubba committed
214
{
Gus Grubba's avatar
Gus Grubba committed
215 216
    AirMapWeatherInfoManager* weatherInfo = new AirMapWeatherInfoManager(_shared);
    connect(weatherInfo, &AirMapWeatherInfoManager::error, this, &AirMapManager::_error);
217
    return weatherInfo;
Gus Grubba's avatar
Gus Grubba committed
218
}
Gus Grubba's avatar
Gus Grubba committed
219

220
//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
221
AirspaceAdvisoryProvider*
222
AirMapManager::_instatiateAirspaceAdvisoryProvider()
Gus Grubba's avatar
Gus Grubba committed
223
{
Gus Grubba's avatar
Gus Grubba committed
224 225
    AirMapAdvisoryManager* advisories = new AirMapAdvisoryManager(_shared);
    connect(advisories, &AirMapAdvisoryManager::error, this, &AirMapManager::_error);
Gus Grubba's avatar
Gus Grubba committed
226 227
    return advisories;
}
228

229
//-----------------------------------------------------------------------------
230
AirspaceRestrictionProvider*
231
AirMapManager::_instantiateAirspaceRestrictionProvider()
232 233 234 235 236
{
    AirMapRestrictionManager* airspaces = new AirMapRestrictionManager(_shared);
    connect(airspaces, &AirMapRestrictionManager::error, this, &AirMapManager::_error);
    return airspaces;
}
237 238

//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
239 240
AirspaceFlightPlanProvider*
AirMapManager::_instantiateAirspaceFlightPlanProvider()
241
{
Gus Grubba's avatar
Gus Grubba committed
242 243 244
    AirMapFlightPlanManager* flightPlan = new AirMapFlightPlanManager(_shared);
    connect(flightPlan, &AirMapFlightPlanManager::error, this, &AirMapManager::_error);
    return flightPlan;
245
}