From bc10a8d29a3c3a7f0ab7dd80cde5bbf725251d11 Mon Sep 17 00:00:00 2001 From: Gus Grubba Date: Thu, 19 Jul 2018 17:38:29 -0400 Subject: [PATCH] Connection management --- src/Airmap/AirMapManager.cc | 64 ++++++++++++---- src/Airmap/AirMapManager.h | 3 + src/Airmap/AirmapSettings.qml | 86 +++++++++++++++++----- src/Airmap/AirspaceControl.qml | 22 ++++-- src/AirspaceManagement/AirspaceManager.h | 6 ++ src/FlightDisplay/FlightDisplayViewMap.qml | 6 +- src/GPS/Drivers | 2 +- src/PlanView/PlanView.qml | 3 +- 8 files changed, 146 insertions(+), 46 deletions(-) diff --git a/src/Airmap/AirMapManager.cc b/src/Airmap/AirMapManager.cc index bf099a9d9..734bce71f 100644 --- a/src/Airmap/AirMapManager.cc +++ b/src/Airmap/AirMapManager.cc @@ -42,9 +42,9 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox) { _logger = std::make_shared(); qt::register_types(); // TODO: still needed? - _logger->logging_category().setEnabled(QtDebugMsg, false); - _logger->logging_category().setEnabled(QtInfoMsg, false); - _logger->logging_category().setEnabled(QtWarningMsg, false); + _logger->logging_category().setEnabled(QtDebugMsg, true); + _logger->logging_category().setEnabled(QtInfoMsg, true); + _logger->logging_category().setEnabled(QtWarningMsg, true); _dispatchingLogger = std::make_shared(_logger); connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error); } @@ -63,6 +63,7 @@ AirMapManager::setToolbox(QGCToolbox* toolbox) { AirspaceManager::setToolbox(toolbox); AirMapSettings* ap = toolbox->settingsManager()->airMapSettings(); + connect(ap->enableAirMap(), &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged); connect(ap->usePersonalApiKey(),&Fact::rawValueChanged, this, &AirMapManager::_settingsChanged); connect(ap->apiKey(), &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged); connect(ap->clientID(), &Fact::rawValueChanged, this, &AirMapManager::_settingsChanged); @@ -71,6 +72,13 @@ AirMapManager::setToolbox(QGCToolbox* toolbox) _settingsChanged(); } +//----------------------------------------------------------------------------- +bool +AirMapManager::connected() const +{ + return _shared.client() != NULL; +} + //----------------------------------------------------------------------------- void AirMapManager::_error(const QString& what, const QString& airmapdMessage, const QString& airmapdDetails) @@ -84,29 +92,41 @@ void AirMapManager::_settingsChanged() { qCDebug(AirMapManagerLog) << "AirMap settings changed"; + _connectStatus.clear(); + emit connectStatusChanged(); AirMapSettings* ap = _toolbox->settingsManager()->airMapSettings(); + //-- If we are disabled, there is nothing else to do. + if (!ap->enableAirMap()->rawValue().toBool()) { + if(_shared.client()) { + delete _shared.client(); + _shared.setClient(nullptr); + emit connectedChanged(); + } + return; + } AirMapSharedState::Settings settings; - settings.apiKey = ap->apiKey()->rawValueString(); -#if defined(QGC_AIRMAP_KEY_AVAILABLE) - bool apiKeyChanged = settings.apiKey != _shared.settings().apiKey || settings.apiKey.isEmpty(); -#else - bool apiKeyChanged = settings.apiKey != _shared.settings().apiKey; -#endif - settings.clientID = ap->clientID()->rawValueString(); + if(ap->usePersonalApiKey()->rawValue().toBool()) { + settings.apiKey = ap->apiKey()->rawValueString(); + settings.clientID = ap->clientID()->rawValueString(); + } settings.userName = ap->userName()->rawValueString(); settings.password = ap->password()->rawValueString(); - //-- If we have a hardwired key (and no custom key is present or enabled), set it. + //-- If we have a hardwired key (and no custom key is present), set it. #if defined(QGC_AIRMAP_KEY_AVAILABLE) - if(!ap->usePersonalApiKey()->rawValue().toBool() && (settings.apiKey.isEmpty() || settings.clientID.isEmpty())) { + if(!ap->usePersonalApiKey()->rawValue().toBool()) { settings.apiKey = kAirmapAPIKey; settings.clientID = kAirmapClientID; } + bool apiKeyChanged = settings.apiKey != _shared.settings().apiKey || settings.apiKey.isEmpty(); +#else + bool apiKeyChanged = settings.apiKey != _shared.settings().apiKey; #endif _shared.setSettings(settings); //-- Need to re-create the client if the API key changed - if (_shared.client() && apiKeyChanged) { + if ((_shared.client() && apiKeyChanged) || !ap->enableAirMap()->rawValue().toBool()) { delete _shared.client(); _shared.setClient(nullptr); + emit connectedChanged(); } if (!_shared.client() && settings.apiKey != "") { qCDebug(AirMapManagerLog) << "Creating AirMap client"; @@ -119,16 +139,28 @@ AirMapManager::_settingsChanged() if (result) { qCDebug(AirMapManagerLog) << "Successfully created airmap::qt::Client instance"; _shared.setClient(result.value()); + emit connectedChanged(); + _connectStatus = tr("AirMap Enabled"); + emit connectStatusChanged(); } else { qWarning("Failed to create airmap::qt::Client instance"); QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); - _error("Failed to create airmap::qt::Client instance", - QString::fromStdString(result.error().message()), description); + 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(); } }); } else { if(settings.apiKey == "") { - qCDebug(AirMapManagerLog) << "No API key for AirMap"; + _connectStatus = tr("No API key for AirMap"); + emit connectStatusChanged(); + qCDebug(AirMapManagerLog) << _connectStatus; } } } diff --git a/src/Airmap/AirMapManager.h b/src/Airmap/AirMapManager.h index b3d48f975..1820a41c5 100644 --- a/src/Airmap/AirMapManager.h +++ b/src/Airmap/AirMapManager.h @@ -39,6 +39,8 @@ public: QString providerName () const override { return QString("AirMap"); } AirspaceVehicleManager* instantiateVehicle (const Vehicle& vehicle) override; + bool connected () const override; + QString connectStatus () const override { return _connectStatus; } protected: AirspaceRulesetsProvider* _instantiateRulesetsProvider () override; @@ -52,6 +54,7 @@ private slots: void _settingsChanged (); private: + QString _connectStatus; AirMapSharedState _shared; std::shared_ptr _logger; std::shared_ptr _dispatchingLogger; diff --git a/src/Airmap/AirmapSettings.qml b/src/Airmap/AirmapSettings.qml index 0a9e5df56..a7a901c4b 100644 --- a/src/Airmap/AirmapSettings.qml +++ b/src/Airmap/AirmapSettings.qml @@ -37,7 +37,7 @@ QGCView { anchors.margins: ScreenTools.defaultFontPixelWidth property real _labelWidth: ScreenTools.defaultFontPixelWidth * 20 - property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30 + property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20 property real _buttonWidth: ScreenTools.defaultFontPixelWidth * 18 property real _panelWidth: _qgcView.width * _internalWidthRatio property Fact _enableAirMapFact: QGroundControl.settingsManager.airMapSettings.enableAirMap @@ -99,6 +99,47 @@ QGCView { } } //----------------------------------------------------------------- + //-- Connection Status + Item { + width: _panelWidth + height: statusLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.appSettings.visible && _airMapEnabled + QGCLabel { + id: statusLabel + text: qsTr("Connection Status") + font.family: ScreenTools.demiboldFontFamily + } + } + Rectangle { + height: statusCol.height + (ScreenTools.defaultFontPixelHeight * 2) + width: _panelWidth + color: qgcPal.windowShade + visible: QGroundControl.settingsManager.appSettings.visible && _airMapEnabled + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: statusCol + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + width: parent.width + anchors.centerIn: parent + QGCLabel { + text: QGroundControl.airspaceManager.connected ? qsTr("Connected") : qsTr("Not Connected") + color: QGroundControl.airspaceManager.connected ? qgcPal.colorGreen : qgcPal.colorRed + anchors.horizontalCenter: parent.horizontalCenter + } + QGCLabel { + text: QGroundControl.airspaceManager.connectStatus + visible: QGroundControl.airspaceManager.connectStatus != "" + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + width: parent.width * 0.8 + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + //----------------------------------------------------------------- //-- Login / Registration Item { width: _panelWidth @@ -128,6 +169,8 @@ QGCView { width: _editFieldWidth enabled: _airMapEnabled visible: _usernameFact.visible + Layout.fillWidth: true + Layout.minimumWidth: _editFieldWidth property Fact _usernameFact: QGroundControl.settingsManager.airMapSettings.userName } QGCLabel { text: qsTr("Password:") } @@ -137,6 +180,8 @@ QGCView { enabled: _airMapEnabled visible: _passwordFact.visible echoMode: TextInput.Password + Layout.fillWidth: true + Layout.minimumWidth: _editFieldWidth property Fact _passwordFact: QGroundControl.settingsManager.airMapSettings.password } Item { @@ -168,11 +213,12 @@ QGCView { //----------------------------------------------------------------- //-- Pilot Profile Item { + //-- Disabled for now width: _panelWidth height: profileLabel.height anchors.margins: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter - visible: QGroundControl.settingsManager.appSettings.visible + visible: false // QGroundControl.settingsManager.appSettings.visible QGCLabel { id: profileLabel text: qsTr("Pilot Profile (WIP)") @@ -180,9 +226,11 @@ QGCView { } } Rectangle { + //-- Disabled for now height: profileGrid.height + (ScreenTools.defaultFontPixelHeight * 2) width: _panelWidth color: qgcPal.windowShade + visible: false // QGroundControl.settingsManager.appSettings.visible anchors.margins: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter GridLayout { @@ -208,11 +256,11 @@ QGCView { height: licenseLabel.height anchors.margins: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter - visible: QGroundControl.settingsManager.appSettings.visible + visible: QGroundControl.settingsManager.airMapSettings.usePersonalApiKey.visible QGCLabel { - id: licenseLabel - text: qsTr("License") - font.family: ScreenTools.demiboldFontFamily + id: licenseLabel + text: qsTr("License") + font.family: ScreenTools.demiboldFontFamily } } Rectangle { @@ -221,20 +269,18 @@ QGCView { color: qgcPal.windowShade anchors.margins: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter + visible: QGroundControl.settingsManager.airMapSettings.usePersonalApiKey.visible GridLayout { - id: licenseGrid - columns: 2 - columnSpacing: ScreenTools.defaultFontPixelHeight * 2 - rowSpacing: ScreenTools.defaultFontPixelWidth * 0.25 - anchors.centerIn: parent - QGCCheckBox { - id: hasPrivateKey - text: qsTr("Personal API Key") - onClicked: QGroundControl.settingsManager.airMapSettings.usePersonalApiKey = checked + id: licenseGrid + columns: 2 + columnSpacing: ScreenTools.defaultFontPixelHeight * 2 + rowSpacing: ScreenTools.defaultFontPixelWidth * 0.25 + anchors.centerIn: parent + FactCheckBox { + id: hasPrivateKey + text: qsTr("Personal API Key") + fact: QGroundControl.settingsManager.airMapSettings.usePersonalApiKey Layout.columnSpan: 2 - Component.onCompleted: { - checked = QGroundControl.settingsManager.airMapSettings.usePersonalApiKey - } } Item { width: 1 @@ -243,9 +289,9 @@ QGCView { Layout.columnSpan: 2 } QGCLabel { text: qsTr("API Key:"); visible: hasPrivateKey.checked; } - FactTextField { fact: QGroundControl.settingsManager.airMapSettings.apiKey; width: _editFieldWidth * 2; visible: hasPrivateKey.checked; } + FactTextField { fact: QGroundControl.settingsManager.airMapSettings.apiKey; width: _editFieldWidth * 2; visible: hasPrivateKey.checked; Layout.fillWidth: true; Layout.minimumWidth: _editFieldWidth * 2; } QGCLabel { text: qsTr("Client ID:"); visible: hasPrivateKey.checked; } - FactTextField { fact: QGroundControl.settingsManager.airMapSettings.clientID; width: _editFieldWidth * 2; visible: hasPrivateKey.checked; } + FactTextField { fact: QGroundControl.settingsManager.airMapSettings.clientID; width: _editFieldWidth * 2; visible: hasPrivateKey.checked; Layout.fillWidth: true; Layout.minimumWidth: _editFieldWidth * 2; } } } //----------------------------------------------------------------- diff --git a/src/Airmap/AirspaceControl.qml b/src/Airmap/AirspaceControl.qml index 8c3eda8a5..ae77edbfd 100644 --- a/src/Airmap/AirspaceControl.qml +++ b/src/Airmap/AirspaceControl.qml @@ -24,11 +24,11 @@ Item { property bool planView: true property color _airspaceColor: _validAdvisories ? getAispaceColor(QGroundControl.airspaceManager.advisories.airspaceColor) : _colorGray - property bool _validRules: QGroundControl.airspaceManager.ruleSets.valid - property bool _validAdvisories: QGroundControl.airspaceManager.advisories.valid + property bool _validRules: QGroundControl.airspaceManager.connected && QGroundControl.airspaceManager.ruleSets.valid + property bool _validAdvisories: QGroundControl.airspaceManager.connected && QGroundControl.airspaceManager.advisories.valid property color _textColor: qgcPal.text - property bool _colapsed: !QGroundControl.airspaceManager.airspaceVisible - property var _flightPermit: QGroundControl.airspaceManager.flightPlan.flightPermitStatus + property bool _colapsed: !QGroundControl.airspaceManager.airspaceVisible || !QGroundControl.airspaceManager.connected + property int _flightPermit: QGroundControl.airspaceManager.flightPlan.flightPermitStatus property bool _dirty: false readonly property real _radius: ScreenTools.defaultFontPixelWidth * 0.5 @@ -84,7 +84,7 @@ Item { id: colapsedRect width: parent.width height: _colapsed ? colapsedRow.height + ScreenTools.defaultFontPixelHeight : 0 - color: _validAdvisories ? getAispaceColor(QGroundControl.airspaceManager.advisories.airspaceColor) : _colorGray + color: QGroundControl.airspaceManager.connected ? (_validAdvisories ? getAispaceColor(QGroundControl.airspaceManager.advisories.airspaceColor) : _colorGray) : _colorGray radius: _radius visible: _colapsed Row { @@ -121,10 +121,16 @@ Item { } AirspaceWeather { iconHeight: ScreenTools.defaultFontPixelHeight * 2 - visible: QGroundControl.airspaceManager.weatherInfo.valid + visible: QGroundControl.airspaceManager.weatherInfo.valid && QGroundControl.airspaceManager.connected contentColor: _textColor anchors.verticalCenter: parent.verticalCenter } + QGCLabel { + text: qsTr("Not Connected") + color: qgcPal.text + visible: !QGroundControl.airspaceManager.connected + anchors.verticalCenter: parent.verticalCenter + } } QGCColoredImage { width: height @@ -133,12 +139,14 @@ Item { source: "qrc:/airmap/expand.svg" color: _textColor fillMode: Image.PreserveAspectFit + visible: QGroundControl.airspaceManager.connected anchors.right: parent.right anchors.rightMargin: ScreenTools.defaultFontPixelWidth anchors.verticalCenter: parent.verticalCenter } MouseArea { - anchors.fill: parent + anchors.fill: parent + enabled: QGroundControl.airspaceManager.connected onClicked: { QGroundControl.airspaceManager.airspaceVisible = true } diff --git a/src/AirspaceManagement/AirspaceManager.h b/src/AirspaceManagement/AirspaceManager.h index 7991aac73..5f94aeff4 100644 --- a/src/AirspaceManagement/AirspaceManager.h +++ b/src/AirspaceManagement/AirspaceManager.h @@ -63,6 +63,8 @@ public: Q_PROPERTY(AirspaceRulesetsProvider* ruleSets READ ruleSets CONSTANT) Q_PROPERTY(AirspaceRestrictionProvider* airspaces READ airspaces CONSTANT) Q_PROPERTY(AirspaceFlightPlanProvider* flightPlan READ flightPlan CONSTANT) + Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) + Q_PROPERTY(QString connectStatus READ connectStatus NOTIFY connectStatusChanged) Q_PROPERTY(bool airspaceVisible READ airspaceVisible WRITE setAirspaceVisible NOTIFY airspaceVisibleChanged) Q_INVOKABLE void setROI (const QGeoCoordinate& pointNW, const QGeoCoordinate& pointSE, bool planView); @@ -79,6 +81,8 @@ public: virtual bool airspaceVisible () { return _airspaceVisible; } virtual void setAirspaceVisible (bool set) { _airspaceVisible = set; emit airspaceVisibleChanged(); } + virtual bool connected () const = 0; + virtual QString connectStatus () const { return QString(); } /** * Factory method to create an AirspaceVehicleManager object @@ -87,6 +91,8 @@ public: signals: void airspaceVisibleChanged (); + void connectedChanged (); + void connectStatusChanged (); protected: /** diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index 9852951d5..5285e0e40 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -51,7 +51,7 @@ FlightMap { property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate() property real _toolButtonTopMargin: parent.height - ScreenTools.availableHeight + (ScreenTools.defaultFontPixelHeight / 2) - property bool _airspaceEnabled: QGroundControl.airmapSupported ? QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue : false + property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false property bool _disableVehicleTracking: false property bool _keepVehicleCentered: _mainIsMap ? false : true @@ -87,6 +87,10 @@ FlightMap { } } + on_AirspaceEnabledChanged: { + updateAirspace() + } + function pointInRect(point, rect) { return point.x > rect.x && point.x < rect.x + rect.width && diff --git a/src/GPS/Drivers b/src/GPS/Drivers index d7854b7bc..e84bb0a7a 160000 --- a/src/GPS/Drivers +++ b/src/GPS/Drivers @@ -1 +1 @@ -Subproject commit d7854b7bcf1610bb42d89f4bae553744cbe4408c +Subproject commit e84bb0a7a702320fedade6c83bbdf2324e3be8fb diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index c13e0fbf5..8d5bc7016 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -47,7 +47,7 @@ QGCView { readonly property var _defaultVehicleCoordinate: QtPositioning.coordinate(37.803784, -122.462276) readonly property bool _waypointsOnlyMode: QGroundControl.corePlugin.options.missionWaypointsOnly - property bool _airspaceEnabled: QGroundControl.airmapSupported ? QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue : false + property bool _airspaceEnabled: QGroundControl.airmapSupported ? (QGroundControl.settingsManager.airMapSettings.enableAirMap.rawValue && QGroundControl.airspaceManager.connected): false property var _planMasterController: masterController property var _missionController: _planMasterController.missionController property var _geoFenceController: _planMasterController.geoFenceController @@ -115,6 +115,7 @@ QGCView { if(QGroundControl.airmapSupported) { if(_airspaceEnabled) { planControlColapsed = QGroundControl.airspaceManager.airspaceVisible + updateAirspace() } else { planControlColapsed = false } -- 2.22.0