Commit 92b353bd authored by Don Gagne's avatar Don Gagne

Rework param loading

parent fa1f02fd
......@@ -310,7 +310,6 @@ HEADERS += \
src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \
src/AutoPilotPlugins/APM/APMAirframeLoader.h \
src/QmlControls/QGCImageProvider.h \
src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \
src/PositionManager/PositionManager.h
......@@ -463,7 +462,6 @@ SOURCES += \
src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \
src/AutoPilotPlugins/APM/APMAirframeLoader.cc \
src/QmlControls/QGCImageProvider.cc \
src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \
src/PositionManager/SimulatedPosition.cc \
src/PositionManager/PositionManager.cpp
......
......@@ -61,9 +61,6 @@ QGCView {
onCurrentAirframeTypeChanged: {
airframePicker.model = controller.currentAirframeType.airframes;
}
onCurrentAirframeChanged : {
hideDialog();
}
}
QGCLabel {
......@@ -73,7 +70,7 @@ QGCView {
anchors.right: parent.right
anchors.margins: _margins
wrapMode: Text.WordWrap
text: qsTr("Select you drone to load the default parameters for it. ")
text: qsTr("Select your drone to load the default parameters for it. ")
}
Flow {
......@@ -95,7 +92,10 @@ QGCView {
height: (ScreenTools.defaultFontPixelHeight * 14) / 5
text: controller.currentAirframeType.airframes[index].name;
onClicked : controller.currentAirframe = controller.currentAirframeType.airframes[index]
onClicked : {
controller.loadParameters(controller.currentAirframeType.airframes[index].params)
hideDialog()
}
}
}
}
......
......@@ -26,16 +26,18 @@
#include "APMAirframeComponentController.h"
#include "APMAirframeComponentAirframes.h"
#include "APMRemoteParamsDownloader.h"
#include "QGCMAVLink.h"
#include "MultiVehicleManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCApplication.h"
#include "QGCFileDownload.h"
#include <QVariant>
#include <QQmlProperty>
#include <QStandardPaths>
#include <QDir>
#include <QJsonParseError>
#include <QJsonObject>
bool APMAirframeComponentController::_typesRegistered = false;
......@@ -94,12 +96,14 @@ void APMAirframeComponentController::_fillAirFrames()
emit loadAirframesCompleted();
}
void APMAirframeComponentController::_finishVehicleSetup() {
QDir dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0)
+ QDir::separator() + qApp->applicationName();
QFile parametersFile(dataLocation.absoluteFilePath(_currentAirframe->params()));
parametersFile.open(QIODevice::ReadOnly);
void APMAirframeComponentController::_loadParametersFromDownloadFile(const QString& downloadedParamFile)
{
QFile parametersFile(downloadedParamFile);
if (!parametersFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open downloaded parameter file" << downloadedParamFile << parametersFile.errorString();
qgcApp()->restoreOverrideCursor();
return;
}
QTextStream reader(&parametersFile);
......@@ -115,9 +119,7 @@ void APMAirframeComponentController::_finishVehicleSetup() {
param->setRawValue(QVariant::fromValue(aux.at(1)));
}
}
qgcApp()->setOverrideCursor(Qt::ArrowCursor);
sender()->deleteLater();
emit currentAirframeChanged(_currentAirframe);
qgcApp()->restoreOverrideCursor();
}
APMAirframeType::APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent) :
......@@ -193,23 +195,68 @@ QString APMAirframeComponentController::currentAirframeTypeName() const
return _vehicle->vehicleTypeName();
}
APMAirframe *APMAirframeComponentController::currentAirframe() const
void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t)
{
return _currentAirframe;
Fact *param = getParameterFact(-1, QStringLiteral("FRAME"));
Q_ASSERT(param);
param->setRawValue(t->type());
}
void APMAirframeComponentController::setCurrentAirframe(APMAirframe *t)
void APMAirframeComponentController::loadParameters(const QString& paramFile)
{
_currentAirframe = t;
qgcApp()->setOverrideCursor(Qt::WaitCursor);
APMRemoteParamsDownloader *paramDownloader = new APMRemoteParamsDownloader(_currentAirframe->params());
connect(paramDownloader, &APMRemoteParamsDownloader::finished, this, &APMAirframeComponentController::_finishVehicleSetup);
QString paramFileUrl = QStringLiteral("https://api.github.com/repos/ArduPilot/ardupilot/contents/Tools/Frame_params/%1?ref=master");
QGCFileDownload* downloader = new QGCFileDownload(this);
connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_githubJsonDownloadFinished);
connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_githubJsonDownloadError);
downloader->download(paramFileUrl.arg(paramFile));
}
void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t)
void APMAirframeComponentController::_githubJsonDownloadFinished(QString remoteFile, QString localFile)
{
Fact *param = getParameterFact(-1, QStringLiteral("FRAME"));
Q_ASSERT(param);
param->setRawValue(t->type());
Q_UNUSED(remoteFile);
QFile jsonFile(localFile);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Unable to open github json file" << localFile << jsonFile.errorString();
qgcApp()->restoreOverrideCursor();
return;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << "Unable to open json document" << localFile << jsonParseError.errorString();
qgcApp()->restoreOverrideCursor();
return;
}
QJsonObject json = doc.object();
QGCFileDownload* downloader = new QGCFileDownload(this);
connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_paramFileDownloadFinished);
connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_paramFileDownloadError);
downloader->download(json["download_url"].toString());
}
void APMAirframeComponentController::_githubJsonDownloadError(QString errorMsg)
{
qgcApp()->showMessage(tr("Param file github json download failed: % 1").arg(errorMsg));
qgcApp()->restoreOverrideCursor();
}
void APMAirframeComponentController::_paramFileDownloadFinished(QString remoteFile, QString localFile)
{
Q_UNUSED(remoteFile);
_loadParametersFromDownloadFile(localFile);
}
void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg)
{
qgcApp()->showMessage(tr("Param file download failed: % 1").arg(errorMsg));
qgcApp()->restoreOverrideCursor();
}
......@@ -58,7 +58,8 @@ public:
Q_PROPERTY(QmlObjectListModel* airframeTypesModel MEMBER _airframeTypesModel CONSTANT)
Q_PROPERTY(APMAirframeType* currentAirframeType READ currentAirframeType WRITE setCurrentAirframeType NOTIFY currentAirframeTypeChanged)
Q_PROPERTY(APMAirframe* currentAirframe READ currentAirframe WRITE setCurrentAirframe NOTIFY currentAirframeChanged)
Q_INVOKABLE void loadParameters(const QString& paramFile);
int currentAirframeIndex(void);
void setCurrentAirframeIndex(int newIndex);
......@@ -66,25 +67,25 @@ public:
signals:
void loadAirframesCompleted();
void currentAirframeTypeChanged(APMAirframeType* airframeType);
void currentAirframeChanged(APMAirframe* airframe);
public slots:
APMAirframeType *currentAirframeType() const;
Q_INVOKABLE QString currentAirframeTypeName() const;
APMAirframe *currentAirframe() const;
void setCurrentAirframeType(APMAirframeType *t);
void setCurrentAirframe(APMAirframe *t);
private slots:
void _fillAirFrames(void);
void _finishVehicleSetup(void);
void _factFrameChanged(QVariant v);
void _githubJsonDownloadFinished(QString remoteFile, QString localFile);
void _githubJsonDownloadError(QString errorMsg);
void _paramFileDownloadFinished(QString remoteFile, QString localFile);
void _paramFileDownloadError(QString errorMsg);
private:
void _loadParametersFromDownloadFile(const QString& downloadedParamFile);
static bool _typesRegistered;
APMAirframeType *_currentAirframeType;
APMAirframe *_currentAirframe;
int _waitParamWriteSignalCount;
QmlObjectListModel *_airframeTypesModel;
};
......
......@@ -32,7 +32,6 @@
#include "APMAirframeComponentAirframes.h"
#include "APMAirframeComponentController.h"
#include "APMAirframeLoader.h"
#include "APMRemoteParamsDownloader.h"
#include "APMFlightModesComponent.h"
#include "APMRadioComponent.h"
#include "APMSafetyComponent.h"
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "APMRemoteParamsDownloader.h"
#include <QMessageBox>
#include <QDesktopServices>
#include <QFile>
#include <QFileDialog>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QCryptographicHash>
#include <QApplication>
#include "APMRemoteParamsDownloader.h"
#define FRAME_PARAMS_LIST QUrl("https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params")
#define FRAME_PARAMS_URL "https://raw.github.com/diydrones/ardupilot/master/Tools/Frame_params/"
static QString dataLocation;
APMRemoteParamsDownloader::APMRemoteParamsDownloader(const QString& file) :
m_fileToDownload(file),
m_networkReply(NULL),
m_downloadedParamFile(NULL)
{
dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0)
+ QDir::separator() + qApp->applicationName();
refreshParamList();
}
QString APMRemoteParamsDownloader::statusText() const
{
return m_statusText;
}
void APMRemoteParamsDownloader::setStatusText(const QString& text)
{
m_statusText = text;
}
void APMRemoteParamsDownloader::refreshParamList()
{
setStatusText(tr("Refresh Param file list"));
QUrl url = FRAME_PARAMS_LIST;
m_networkReply->deleteLater();
m_networkReply = m_networkAccessManager.get(QNetworkRequest(url));
connect(m_networkReply, &QNetworkReply::finished, this, &APMRemoteParamsDownloader::httpParamListFinished);
connect(m_networkReply, &QNetworkReply::downloadProgress, this, &APMRemoteParamsDownloader::updateDataReadProgress);
}
/* Returned Json Example
"_links": {
"git":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d",
"html":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param",
"self":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master"
},
"download_url":"https://raw.githubusercontent.com/diydrones/ardupilot/master/Tools/Frame_params/Parrot_Bebop.param",
"git_url":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d",
"html_url":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param",
"name":"Parrot_Bebop.param","path":"Tools/Frame_params/Parrot_Bebop.param",""
"sha":"a7074e606d695566f9a8c87724ad52e5e3baba7d",
"size":533,
"type":"file",
"url":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master"
*/
void APMRemoteParamsDownloader::startFileDownloadRequest()
{
QUrl url;
QJsonObject obj;
// Find the correct file from the json file list.
while(curr != end) {
obj = (*curr).toObject();
url = QUrl(obj["download_url"].toString());
QString name = obj["name"].toString();
if (name == m_fileToDownload) {
break;
}
curr++;
}
if (curr == end)
return;
QDir parameterDir(dataLocation);
if (!parameterDir.exists())
parameterDir.mkpath(dataLocation);
QString filename = parameterDir.absoluteFilePath(obj["name"].toString());
if(m_downloadedParamFile)
m_downloadedParamFile->deleteLater();
m_downloadedParamFile = new QFile(filename);
m_downloadedParamFile->open(QIODevice::WriteOnly);
m_networkReply = m_networkAccessManager.get(QNetworkRequest(url));
connect(m_networkReply, &QNetworkReply::finished, this, &APMRemoteParamsDownloader::httpFinished);
connect(m_networkReply, &QNetworkReply::readyRead, this, &APMRemoteParamsDownloader::httpReadyRead);
connect(m_networkReply, &QNetworkReply::downloadProgress, this, &APMRemoteParamsDownloader::updateDataReadProgress);
curr++;
}
void APMRemoteParamsDownloader::httpFinished()
{
m_downloadedParamFile->flush();
m_downloadedParamFile->close();
if (m_networkReply->error()) {
m_downloadedParamFile->remove();
setStatusText(tr("Download failed: %1.").arg(m_networkReply->errorString()));
}
m_networkReply->deleteLater();
m_networkReply = NULL;
delete m_downloadedParamFile;
m_downloadedParamFile = NULL;
emit finished();
}
void APMRemoteParamsDownloader::httpReadyRead()
{
if (m_downloadedParamFile)
m_downloadedParamFile->write(m_networkReply->readAll());
}
void APMRemoteParamsDownloader::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
Q_UNUSED(bytesRead);
Q_UNUSED(totalBytes);
}
void APMRemoteParamsDownloader::httpParamListFinished()
{
if (m_networkReply->error()) {
qDebug() << "Download failed:" << m_networkReply->errorString();
return;
}
processDownloadedVersionObject(m_networkReply->readAll());
startFileDownloadRequest();
}
void APMRemoteParamsDownloader::processDownloadedVersionObject(const QByteArray &listObject)
{
QJsonParseError jsonErrorChecker;
QJsonDocument jsonDocument = QJsonDocument::fromJson(listObject, &jsonErrorChecker);
if (jsonErrorChecker.error != QJsonParseError::NoError) {
qDebug() << "Json error while parsing document:" << jsonErrorChecker.errorString();
return;
}
m_documentArray = jsonDocument.array();
curr = m_documentArray.constBegin();
end = m_documentArray.constEnd();
}
#ifndef APMREMOTEPARAMSCONTROLLER_H
#define APMREMOTEPARAMSCONTROLLER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QJsonArray>
class QNetworkReply;
class QFile;
class QUrl;
class APMRemoteParamsDownloader : public QObject
{
Q_OBJECT
Q_PROPERTY(QString statusText READ statusText)
public:
explicit APMRemoteParamsDownloader(const QString& file);
QString statusText() const;
void refreshParamList();
void httpParamListFinished();
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);
private:
void setStatusText(const QString& text);
void startFileDownloadRequest();
void manualListSetup();
void processDownloadedVersionObject(const QByteArray& listObject);
void startDownloadingRemoteParams();
signals:
void finished();
private:
QString m_fileToDownload;
QString m_statusText;
QNetworkAccessManager m_networkAccessManager;
QNetworkReply* m_networkReply;
QFile* m_downloadedParamFile;
// the list of needed documents.
QJsonArray m_documentArray;
QJsonArray::const_iterator curr;
QJsonArray::const_iterator end;
};
#endif // APMREMOTEPARAMSCONTROLLER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment