11#include <QtCore/QJsonObject>
12#include <QtCore/QJsonParseError>
13#include <QtCore/QVariant>
14#include <QtGui/QCursor>
15#include <QtGui/QGuiApplication>
17QGC_LOGGING_CATEGORY(APMAirframeComponentControllerLog,
"AutoPilotPlugins.APMAirframeComponentController")
23 , _frameClassFact(getParameterFact(
ParameterManager::defaultComponentId, QStringLiteral("FRAME_CLASS"), false ))
24 , _frameTypeFact(getParameterFact(
ParameterManager::defaultComponentId, QStringLiteral("FRAME_TYPE"), false ))
32APMAirframeComponentController::~APMAirframeComponentController()
37void APMAirframeComponentController::_fillFrameClasses()
41 if (qobject_cast<ArduCopterFirmwarePlugin*>(fwPlugin)) {
42 static const QList<int> frameTypeNotSupported = {
51 for (qsizetype i = 1; i < _frameClassFact->enumStrings().count(); i++) {
52 const QString frameClassName = _frameClassFact->enumStrings()[i];
53 const int frameClass = _frameClassFact->enumValues()[i].toInt();
60 _frameClassModel->
append(
new APMFrameClass(frameClassName,
true , frameClass, _frameTypeFact, _frameClassModel));
62 }
else if (qobject_cast<ArduRoverFirmwarePlugin*>(fwPlugin)) {
63 for (qsizetype i = 1; i < _frameClassFact->enumStrings().count(); i++) {
64 const QString frameClassName = _frameClassFact->enumStrings()[i];
65 const int frameClass = _frameClassFact->enumValues()[i].toInt();
66 _frameClassModel->
append(
new APMFrameClass(frameClassName,
false , frameClass, _frameTypeFact, _frameClassModel));
71void APMAirframeComponentController::_loadParametersFromDownloadFile(
const QString &downloadedParamFile)
73 QFile parametersFile(downloadedParamFile);
74 if (!parametersFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
75 qCWarning(APMAirframeComponentControllerLog) <<
"Unable to open downloaded parameter file" << downloadedParamFile << parametersFile.errorString();
76 QGuiApplication::restoreOverrideCursor();
80 QTextStream reader(¶metersFile);
81 while (!reader.atEnd()) {
82 const QString line = reader.readLine().trimmed();
83 if (line.isEmpty() || (line.at(0) == QChar(
'#'))) {
87 const QStringList aux = line.split(
',');
88 if (parameterExists(-1, aux.at(0))) {
89 Fact *
const param = getParameterFact(-1, aux.at(0));
90 param->setRawValue(QVariant::fromValue(aux.at(1)));
93 QGuiApplication::restoreOverrideCursor();
97void APMAirframeComponentController::loadParameters(
const QString ¶mFile)
99 QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
103 (void) connect(downloader, &
QGCFileDownload::finished,
this, &APMAirframeComponentController::_githubJsonDownloadComplete);
104 const QString paramFileUrl = QStringLiteral(
"https://api.github.com/repos/ArduPilot/ardupilot/contents/Tools/Frame_params/%1?ref=master");
105 if (!downloader->
start(paramFileUrl.arg(paramFile))) {
106 qgcApp()->showAppMessage(tr(
"Param file github json download failed to start: %1").arg(downloader->errorString()));
107 QGuiApplication::restoreOverrideCursor();
108 downloader->deleteLater();
112void APMAirframeComponentController::_githubJsonDownloadComplete(
bool success,
const QString &localFile,
const QString &errorMsg)
115 QFile jsonFile(localFile);
116 if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
117 qCWarning(APMAirframeComponentControllerLog) <<
"Unable to open github json file" << localFile << jsonFile.errorString();
118 QGuiApplication::restoreOverrideCursor();
121 const QByteArray bytes = jsonFile.readAll();
124 QJsonParseError jsonParseError;
125 const QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
126 if (jsonParseError.error != QJsonParseError::NoError) {
127 qCWarning(APMAirframeComponentControllerLog) <<
"Unable to open json document" << localFile << jsonParseError.errorString();
128 QGuiApplication::restoreOverrideCursor();
134 (void) connect(downloader, &
QGCFileDownload::finished,
this, &APMAirframeComponentController::_paramFileDownloadComplete);
135 const QJsonObject json = doc.object();
136 if (!downloader->
start(json[QLatin1String(
"download_url")].toString())) {
137 qgcApp()->showAppMessage(tr(
"Param file download failed to start: %1").arg(downloader->errorString()));
138 QGuiApplication::restoreOverrideCursor();
139 downloader->deleteLater();
141 }
else if (!errorMsg.isEmpty()) {
142 qgcApp()->showAppMessage(tr(
"Param file github json download failed: %1").arg(errorMsg));
143 QGuiApplication::restoreOverrideCursor();
147void APMAirframeComponentController::_paramFileDownloadComplete(
bool success,
const QString &localFile,
const QString &errorMsg)
150 _loadParametersFromDownloadFile(localFile);
151 }
else if (!errorMsg.isEmpty()) {
152 qgcApp()->showAppMessage(tr(
"Param file download failed: %1").arg(errorMsg));
153 QGuiApplication::restoreOverrideCursor();
159APMFrameClass::APMFrameClass(
const QString &name,
bool copter,
int frameClass,
Fact *frameTypeFact, QObject *parent)
163 , _frameClass(frameClass)
164 , _frameTypeFact(frameTypeFact)
172 QList<int> rgSupportedFrameTypes;
174 for (
const FrameToImageInfo &pFrameToImageInfo : _rgFrameToImageCopter) {
175 if (pFrameToImageInfo.frameClass == frameClass) {
176 if (_defaultFrameType == -1) {
178 _defaultFrameType = pFrameToImageInfo.frameType;
179 _imageResourceDefault = QStringLiteral(
"/qmlimages/Airframe/%1").arg(pFrameToImageInfo.imageResource);
182 if (pFrameToImageInfo.frameType != -1) {
184 rgSupportedFrameTypes.append(pFrameToImageInfo.frameType);
189 if (_imageResourceDefault.isEmpty()) {
190 _imageResourceDefault = QStringLiteral(
"/qmlimages/Airframe/AirframeUnknown.svg");
194 for (
const int frameType: rgSupportedFrameTypes) {
195 const int index = frameTypeFact->enumValues().indexOf(frameType);
197 _frameTypeEnumValues.append(frameType);
198 _frameTypeEnumStrings.append(frameTypeFact->enumStrings()[index]);
202 _imageResourceDefault = imageResource();
206 _frameTypeSupported = _defaultFrameType != -1;
209APMFrameClass::~APMFrameClass()
214int APMFrameClass::frameType()
const
216 return _frameTypeFact->rawValue().toInt();
219QString APMFrameClass::imageResource()
const
221 int frameType = _frameTypeFact ? _frameTypeFact->rawValue().toInt() : -1;
223 QString imageResource;
225 imageResource = _findImageResourceCopter(_frameClass, frameType);
227 imageResource = _findImageResourceRover(_frameClass, frameType);
230 return QStringLiteral(
"/qmlimages/Airframe/%1").arg(imageResource);
234QString APMFrameClass::_findImageResourceCopter(
int frameClass,
int &frameType)
236 for (
const FrameToImageInfo &pFrameToImageInfo : _rgFrameToImageCopter) {
237 if (((pFrameToImageInfo.frameClass == frameClass) && (frameType == -1)) ||
238 ((pFrameToImageInfo.frameClass == frameClass) && (pFrameToImageInfo.frameType == frameType))) {
239 frameType = pFrameToImageInfo.frameType;
240 return pFrameToImageInfo.imageResource;
244 return QStringLiteral(
"AirframeUnknown");
247QString APMFrameClass::_findImageResourceRover(
int frameClass,
int frameType)
251 static const QList<FrameToImageInfo> s_rgFrameToImageRover = {
256 for (
const FrameToImageInfo &pFrameToImageInfo : s_rgFrameToImageRover) {
257 if (pFrameToImageInfo.frameClass == frameClass) {
258 return pFrameToImageInfo.imageResource;
262 return QStringLiteral(
"AirframeUnknown");
#define FRAME_CLASS_BICOPTER
#define FRAME_CLASS_ROVER
#define FRAME_CLASS_COAXCOPTER
#define FRAME_CLASS_HELI_DUAL
#define FRAME_CLASS_HELIQUAD
#define FRAME_CLASS_SINGLECOPTER
Unified file download utility with decompression, verification, and QML support.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
MVC Controller for APMAirframeComponent.qml.
void imageResourceChanged()
Used for handling missing Facts from C++ code.
A Fact is used to hold a single value within the system.
void rawValueChanged(const QVariant &value)
void refreshAllParameters(uint8_t componentID=MAV_COMP_ID_ALL)
Re-request the full set of parameters from the autopilot.
void finished(bool success, const QString &localPath, const QString &errorMessage)
bool start(const QString &remoteUrl)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
ParameterManager * parameterManager()