QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
FirmwarePlugin.cc
Go to the documentation of this file.
1#include "FirmwarePlugin.h"
2
3#include <QtCore/QDir>
4#include <QtCore/QFile>
5#include <QtCore/QRegularExpression>
6#include <QtCore/QSettings>
7#include <QtCore/QStandardPaths>
8#include <QtCore/QThread>
9
10#include "AppMessages.h"
11#include "AutoPilotPlugin.h"
12#include "Autotune.h"
14#include "MAVLinkLib.h"
15#include "MAVLinkProtocol.h"
16#include "ParameterMetaData.h"
17#include "QGCApplication.h"
18#include "QGCCameraManager.h"
19#include "QGCCompression.h"
20#include "QGCFileDownload.h"
21#include "QGCFileHelper.h"
22#include "QGCLoggingCategory.h"
23#include "QGCMAVLink.h"
24#include "QGCVersionCheck.h"
25#include "Vehicle.h"
27#include "VehicleComponent.h"
28#include "VehicleLinkManager.h"
29
30QGC_LOGGING_CATEGORY(FirmwarePluginLog, "FirmwarePlugin.FirmwarePlugin")
31
32static const QString guided_mode_not_supported_by_vehicle = QObject::tr("Guided mode not supported by Vehicle.");
33
35 : QObject(parent)
36{
37 qCDebug(FirmwarePluginLog) << this;
38}
39
41{
42 qCDebug(FirmwarePluginLog) << this;
43}
44
46{
47 return new GenericAutoPilotPlugin(vehicle, vehicle);
48}
49
50QString FirmwarePlugin::flightMode(uint8_t base_mode, uint32_t custom_mode) const
51{
52 Q_UNUSED(custom_mode);
53
54 struct Bit2Name {
55 const uint8_t baseModeBit;
56 const char *name;
57 };
58
59 static constexpr Bit2Name rgBit2Name[] = {
60 { MAV_MODE_FLAG_MANUAL_INPUT_ENABLED, "Manual" },
61 { MAV_MODE_FLAG_STABILIZE_ENABLED, "Stabilize" },
62 { MAV_MODE_FLAG_GUIDED_ENABLED, "Guided" },
63 { MAV_MODE_FLAG_AUTO_ENABLED, "Auto" },
64 { MAV_MODE_FLAG_TEST_ENABLED, "Test" },
65 };
66
67 QString flightMode;
68 if (base_mode == 0) {
69 flightMode = "PreFlight";
70 } else if (base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
71 flightMode = _modeEnumToString.value(custom_mode, QStringLiteral("Custom:0x%1").arg(custom_mode, 0, 16));
72 } else {
73 for (size_t i = 0; i < std::size(rgBit2Name); i++) {
74 if (base_mode & rgBit2Name[i].baseModeBit) {
75 if (i != 0) {
76 flightMode += " ";
77 }
78 flightMode += rgBit2Name[i].name;
79 }
80 }
81 }
82
83 return flightMode;
84}
85
86bool FirmwarePlugin::setFlightMode(const QString &flightMode, uint8_t *base_mode, uint32_t *custom_mode) const
87{
88 Q_UNUSED(flightMode);
89 Q_UNUSED(base_mode);
90 Q_UNUSED(custom_mode);
91
92 qCWarning(FirmwarePluginLog) << "FirmwarePlugin::setFlightMode called on base class, not supported";
93
94 return false;
95}
96
98{
99 switch (vehicleClass) {
101 return QStringLiteral(":/json/MavCmdInfoCommon.json");
103 return QStringLiteral(":/json/MavCmdInfoFixedWing.json");
105 return QStringLiteral(":/json/MavCmdInfoMultiRotor.json");
107 return QStringLiteral(":/json/MavCmdInfoVTOL.json");
109 return QStringLiteral(":/json/MavCmdInfoSub.json");
111 return QStringLiteral(":/json/MavCmdInfoRover.json");
112 default:
113 qCWarning(FirmwarePluginLog) << "FirmwarePlugin::missionCommandOverrides called with bad VehicleClass_t:" << vehicleClass;
114 return QString();
115 }
116}
117
118void FirmwarePlugin::setGuidedMode(Vehicle *vehicle, bool guidedMode) const
119{
120 Q_UNUSED(vehicle);
121 Q_UNUSED(guidedMode);
123}
124
126{
127 Q_UNUSED(vehicle);
129}
130
131void FirmwarePlugin::guidedModeRTL(Vehicle *vehicle, bool smartRTL) const
132{
133 Q_UNUSED(vehicle);
134 Q_UNUSED(smartRTL);
136}
137
139{
140 Q_UNUSED(vehicle);
142}
143
144void FirmwarePlugin::guidedModeTakeoff(Vehicle *vehicle, double takeoffAltRel) const
145{
146 Q_UNUSED(vehicle);
147 Q_UNUSED(takeoffAltRel);
149}
150
151bool FirmwarePlugin::guidedModeGotoLocation(Vehicle *vehicle, const QGeoCoordinate &gotoCoord, double forwardFlightLoiterRadius) const
152{
153 Q_UNUSED(vehicle);
154 Q_UNUSED(gotoCoord);
155 Q_UNUSED(forwardFlightLoiterRadius);
157 return false;
158}
159
165
170
175
176void FirmwarePlugin::guidedModeChangeHeading(Vehicle *vehicle, const QGeoCoordinate &/*headingCoord*/) const
177{
178 Q_UNUSED(vehicle);
180}
181
182bool FirmwarePlugin::guidedModeROI(Vehicle *vehicle, const QGeoCoordinate &roiCenterCoord, double relativeAltitudeMeters) const
183{
184 // MAVLink spec path: firmware honors the frame in the command
185 _sendROICommand(vehicle, roiCenterCoord, MAV_FRAME_GLOBAL_RELATIVE_ALT, static_cast<float>(relativeAltitudeMeters));
186 return true;
187}
188
189void FirmwarePlugin::_sendROICommand(Vehicle *vehicle, const QGeoCoordinate &coord, MAV_FRAME frame, float altitude) const
190{
191 qCDebug(FirmwarePluginLog) << "_sendROICommand: lat" << coord.latitude() << "lon" << coord.longitude()
192 << "frame" << frame << "altitude" << altitude;
193
194 if (vehicle->capabilityBits() & MAV_PROTOCOL_CAPABILITY_COMMAND_INT) {
195 vehicle->sendMavCommandInt(
196 vehicle->defaultComponentId(),
197 MAV_CMD_DO_SET_ROI_LOCATION,
198 frame,
199 true, // show error if fails
200 static_cast<float>(qQNaN()),
201 static_cast<float>(qQNaN()),
202 static_cast<float>(qQNaN()),
203 static_cast<float>(qQNaN()),
204 coord.latitude(),
205 coord.longitude(),
206 altitude);
207 } else {
208 vehicle->sendMavCommand(
209 vehicle->defaultComponentId(),
210 MAV_CMD_DO_SET_ROI_LOCATION,
211 true, // show error if fails
212 static_cast<float>(qQNaN()),
213 static_cast<float>(qQNaN()),
214 static_cast<float>(qQNaN()),
215 static_cast<float>(qQNaN()),
216 static_cast<float>(coord.latitude()),
217 static_cast<float>(coord.longitude()),
218 altitude);
219 }
220}
221
223{
224 // Not supported by generic vehicle
226}
227
232
239
240const QVariantList &FirmwarePlugin::toolIndicators(const Vehicle*)
241{
242 //-- Default list of indicators for all vehicles.
243 if (_toolIndicatorList.isEmpty()) {
244 _toolIndicatorList = QVariantList({
245 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/TelemetryRSSIIndicator.qml")),
246 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/RCRSSIIndicator.qml")),
247 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/BatteryIndicator.qml")),
248 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/RemoteIDIndicator.qml")),
249 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/GimbalIndicator.qml")),
250 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/EscIndicator.qml")),
251 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/JoystickIndicator.qml")),
252 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/MultiVehicleSelector.qml")),
253#ifdef QT_DEBUG
254 // ControlIndicator is only available in debug builds for the moment
255 QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Toolbar/GCSControlIndicator.qml")),
256#endif
257 });
258 }
259
260 return _toolIndicatorList;
261}
262
264{
265 if (vehicle->armed()) {
266 return true;
267 }
268
269 bool vehicleArmed = false;
270
271 // Only try arming the vehicle a single time. Doing retries on arming with a delay can lead to safety issues.
272 vehicle->setArmed(true, false /* showError */);
273
274 // Wait 1500 msecs for vehicle to arm (waiting for the next heartbeat)
275 for (int i = 0; i < 15; i++) {
276 if (vehicle->armed()) {
277 vehicleArmed = true;
278 break;
279 }
280 QThread::msleep(100);
281 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
282 }
283
284 return vehicleArmed;
285}
286
287bool FirmwarePlugin::_setFlightModeAndValidate(Vehicle *vehicle, const QString &flightMode) const
288{
289 if (vehicle->flightMode() == flightMode) {
290 return true;
291 }
292
293 bool flightModeChanged = false;
294
295 // We try 3 times
296 for (int retries = 0; retries < 3; retries++) {
297 vehicle->setFlightMode(flightMode);
298
299 // Wait for vehicle to return flight mode
300 for (int i = 0; i < 13; i++) {
301 if (vehicle->flightMode() == flightMode) {
302 flightModeChanged = true;
303 break;
304 }
305 QThread::msleep(100);
306 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
307 }
308
309 if (flightModeChanged) {
310 break;
311 }
312 }
313
314 return flightModeChanged;
315}
316
317
318void FirmwarePlugin::batteryConsumptionData(Vehicle *vehicle, int &mAhBattery, double &hoverAmps, double &cruiseAmps) const
319{
320 Q_UNUSED(vehicle);
321 mAhBattery = 0;
322 hoverAmps = 0;
323 cruiseAmps = 0;
324}
325
326bool FirmwarePlugin::hasGimbal(Vehicle *vehicle, bool &rollSupported, bool &pitchSupported, bool &yawSupported) const
327{
328 Q_UNUSED(vehicle);
329 rollSupported = false;
330 pitchSupported = false;
331 yawSupported = false;
332 return false;
333}
334
336{
337 return new QGCCameraManager(vehicle);
338}
339
341{
342 return new VehicleCameraControl(info, vehicle, compID, parent);
343}
344
346{
347 // This is required as mocklink uses a hardcoded firmware version
348 if (QGC::runningUnitTests()) {
349 qCDebug(FirmwarePluginLog) << "Skipping version check";
350 return;
351 }
352
353 const QString versionFile = _getLatestVersionFileUrl(vehicle);
354 qCDebug(FirmwarePluginLog) << "Downloading" << versionFile;
355 QGCFileDownload *const downloader = new QGCFileDownload(vehicle);
356 (void) connect(downloader, &QGCFileDownload::finished, this, [vehicle, this, versionFile](bool success, const QString &localFile, const QString &errorMsg) {
357 if (success) {
358 _versionFileDownloadFinished(versionFile, localFile, vehicle);
359 } else if (!errorMsg.isEmpty()) {
360 qCDebug(FirmwarePluginLog) << "Failed to download the latest fw version file. Error:" << errorMsg;
361 }
362 sender()->deleteLater();
363 });
364
365 if (!downloader->start(versionFile)) {
366 downloader->deleteLater();
367 }
368}
369
370void FirmwarePlugin::_versionFileDownloadFinished(const QString& remoteFile, const QString& localFile,
371 Vehicle* vehicle) const
372{
373 qCDebug(FirmwarePluginLog) << "Download complete" << remoteFile << localFile;
374 // Now read the version file and pull out the version string
375 QFile versionFile(localFile);
376 if (!versionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
377 qCWarning(FirmwarePluginLog) << "Error opening downloaded version file.";
378 return;
379 }
380
381 QTextStream stream(&versionFile);
382 const QString versionFileContents = stream.readAll();
383 QString version;
384 const QRegularExpressionMatch match = QRegularExpression(_versionRegex()).match(versionFileContents);
385
386 qCDebug(FirmwarePluginLog) << "Looking for version number...";
387
388 if (match.hasMatch()) {
389 version = match.captured(1);
390 } else {
391 qCWarning(FirmwarePluginLog) << "Unable to parse version info from file" << remoteFile;
392 return;
393 }
394
395 qCDebug(FirmwarePluginLog) << "Latest stable version = " << version;
396
397 const int currType = vehicle->firmwareVersionType();
398
399 // Check if lower version than stable or same version but different type
400 if ((currType == FIRMWARE_VERSION_TYPE_OFFICIAL) && (vehicle->versionCompare(version) < 0)) {
401 const QString currentVersionNumber = QStringLiteral("%1.%2.%3").arg(vehicle->firmwareMajorVersion())
402 .arg(vehicle->firmwareMinorVersion())
403 .arg(vehicle->firmwarePatchVersion());
404 vehicle->setNewStableFirmwareVersion(version);
405
406 QSettings settings;
407 settings.beginGroup(QStringLiteral("LastNotifiedStableFirmware"));
408 const QString settingsKey = stableFirmwareSettingsKey(vehicle);
409 if (!isStableFirmwareVersionUnseen(version, settings.value(settingsKey).toString())) {
410 return;
411 }
412 settings.setValue(settingsKey, version);
413
414 QGC::showAppMessage(tr("Vehicle is not running latest stable firmware! Running %1, latest stable is %2.").arg(currentVersionNumber, version));
415 }
416}
417
419{
420 return QStringLiteral("%1_%2").arg(QString::fromLatin1(QGCMAVLink::firmwareClassToCanonicalString(
424}
425
426bool FirmwarePlugin::isStableFirmwareVersionUnseen(const QString& latestVersion, const QString& seenVersion)
427{
428 // Firmware version strings lack the "v" prefix QGCVersionCheck parses
429 return QGCVersionCheck::shouldNotify(QStringLiteral("v") + latestVersion, QStringLiteral("v") + seenVersion);
430}
431
432int FirmwarePlugin::versionCompare(const Vehicle *vehicle, int major, int minor, int patch) const
433{
434 const int currMajor = vehicle->firmwareMajorVersion();
435 const int currMinor = vehicle->firmwareMinorVersion();
436 const int currPatch = vehicle->firmwarePatchVersion();
437
438 if ((currMajor == major) && (currMinor == minor) && (currPatch == patch)) {
439 return 0;
440 }
441
442 if ((currMajor > major)
443 || ((currMajor == major) && (currMinor > minor))
444 || ((currMajor == major) && (currMinor == minor) && (currPatch > patch)))
445 {
446 return 1;
447 }
448
449 return -1;
450}
451
452int FirmwarePlugin::versionCompare(const Vehicle *vehicle, const QString &compare) const
453{
454 const QStringList versionNumbers = compare.split(".");
455 if (versionNumbers.size() != 3) {
456 qCWarning(FirmwarePluginLog) << "Error parsing version number: wrong format";
457 return -1;
458 }
459
460 const int major = versionNumbers[0].toInt();
461 const int minor = versionNumbers[1].toInt();
462 const int patch = versionNumbers[2].toInt();
463
464 return versionCompare(vehicle, major, minor, patch);
465}
466
467void FirmwarePlugin::sendGCSMotionReport(Vehicle *vehicle, const FollowMe::GCSMotionReport &motionReport, uint8_t estimationCapabilities) const
468{
469 const float altitude = static_cast<float>(motionReport.altMetersAMSL);
470 if (!vehicle || !qIsFinite(altitude)) {
471 qCDebug(FirmwarePluginLog) << "Follow target requires a vehicle and finite altitude";
472 return;
473 }
474 SharedLinkInterfacePtr sharedLink = vehicle->vehicleLinkManager()->primaryLink().lock();
475 if (!sharedLink) {
476 return;
477 }
478
479 mavlink_follow_target_t follow_target{};
480
481 follow_target.timestamp = qgcApp()->msecsSinceBoot();
482 follow_target.est_capabilities = estimationCapabilities;
483 follow_target.position_cov[0] = static_cast<float>(motionReport.pos_std_dev[0]);
484 follow_target.position_cov[2] = static_cast<float>(motionReport.pos_std_dev[2]);
485 follow_target.alt = altitude;
486 follow_target.lat = motionReport.lat_int;
487 follow_target.lon = motionReport.lon_int;
488 follow_target.vel[0] = static_cast<float>(motionReport.vxMetersPerSec);
489 follow_target.vel[1] = static_cast<float>(motionReport.vyMetersPerSec);
490
491 mavlink_message_t message{};
492 mavlink_msg_follow_target_encode_chan(
493 static_cast<uint8_t>(MAVLinkProtocol::instance()->getSystemId()),
494 static_cast<uint8_t>(MAVLinkProtocol::getComponentId()),
495 sharedLink->mavlinkChannel(),
496 &message,
497 &follow_target
498 );
499
500 (void) vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), message);
501}
502
504{
505 return new Autotune(vehicle);
506}
507
509{
510 _flightModeList.clear();
511 _modeEnumToString.clear();
512
513 for (FirmwareFlightMode &flightMode : flightModeList) {
514 _modeEnumToString[flightMode.custom_mode] = flightMode.mode_name;
516 }
517
519 qCDebug(FirmwarePluginLog) << "Flight Mode:" << flightMode.mode_name << " Custom Mode:" << flightMode.custom_mode;
520 }
521}
522
524{
525 for (const FirmwareFlightMode &existingFlightMode : _flightModeList) {
526 if (existingFlightMode.custom_mode == newFlightMode.custom_mode) {
527 qCDebug(FirmwarePluginLog) << "Flight Mode:" << newFlightMode.mode_name << " Custom Mode:" << newFlightMode.custom_mode
528 << " already exists, not adding again.";
529 return;
530 }
531 }
532 _flightModeList += newFlightMode;
533}
534
535/*===========================================================================*/
536
537static constexpr const char *kCachedMetaDataFilePrefix = "ParameterFactMetaData";
538
539static QDir _parameterMetaDataCacheDir(bool ensureExists = false)
540{
541 const QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
542 + QStringLiteral("/ParameterMetaData");
543 if (ensureExists) {
545 }
546 return QDir(path);
547}
548
550{
552 if (!metaData) {
553 if (_autopilotType() == MAV_AUTOPILOT_GENERIC) {
554 qCDebug(FirmwarePluginLog) << "No parameter metadata parser for firmware plugin" << this << "(expected for generic firmware)";
555 } else {
556 qCWarning(FirmwarePluginLog) << "No parameter metadata parser for firmware plugin" << this;
557 }
558 return nullptr;
559 }
560
561 const QString metaDataFile = _cachedParameterMetaDataFile(vehicle);
562 if (!metaDataFile.isEmpty()) {
563 metaData->loadParameterFactMetaDataFile(metaDataFile);
564 }
565 return metaData;
566}
567
569{
570 const MAV_AUTOPILOT autopilot = _autopilotType();
571 if (autopilot == MAV_AUTOPILOT_GENERIC) {
572 return _internalParameterMetaDataFile(vehicle);
573 }
574
575 const QString internalFile = _internalParameterMetaDataFile(vehicle);
576 QVersionNumber internalVersion = ParameterMetaData::versionFromFileName(internalFile);
577 if (internalVersion.isNull()) {
578 internalVersion = ParameterMetaData::versionFromMetaDataFile(internalFile);
579 }
580
581 // Without a known internal version we can't safely compare against
582 // cache — use the bundled file to avoid stale overrides.
583 if (internalVersion.isNull() || QGC::runningUnitTests()) {
584 qCDebug(FirmwarePluginLog) << "Using internal parameter metadata:" << internalFile;
585 return internalFile;
586 }
587
588 const int wantedMajorVersion = internalVersion.majorVersion();
589
590 const QDir cacheDir = _parameterMetaDataCacheDir();
591 const QString wildcard = QStringLiteral("%1_%2.*.json").arg(kCachedMetaDataFilePrefix).arg(autopilot);
592 const QStringList entries = cacheDir.entryList(QStringList(wildcard), QDir::Files);
593
594 QString bestFile;
595 QVersionNumber bestVersion;
596 for (const QString &entry : entries) {
597 const QVersionNumber ver = ParameterMetaData::versionFromFileName(entry);
598 if (ver.isNull() || ver.majorVersion() != wantedMajorVersion) {
599 continue;
600 }
601 if (bestVersion.isNull() || ver > bestVersion) {
602 bestVersion = ver;
603 bestFile = cacheDir.filePath(entry);
604 }
605 }
606
607 if (bestFile.isEmpty()) {
608 qCDebug(FirmwarePluginLog) << "No cached parameter metadata found, using internal:" << internalFile;
609 return internalFile;
610 }
611
612 if (internalVersion.majorVersion() == wantedMajorVersion && bestVersion <= internalVersion) {
613 qCDebug(FirmwarePluginLog) << "Internal metadata" << internalVersion.toString() << ">= cache" << bestVersion.toString()
614 << "— using internal:" << internalFile;
615 return internalFile;
616 }
617 qCDebug(FirmwarePluginLog) << "Using cached parameter metadata" << bestVersion.toString() << ":" << bestFile;
618 return bestFile;
619}
620
621void FirmwarePlugin::cacheParameterMetaDataFile(const QString &metaDataFile)
622{
623 const MAV_AUTOPILOT autopilot = _autopilotType();
624 if (autopilot == MAV_AUTOPILOT_GENERIC) {
625 return;
626 }
627
628 QString readError;
629 const QByteArray data = QGCCompression::readFile(metaDataFile, &readError);
630 if (data.isEmpty()) {
631 qCWarning(FirmwarePluginLog) << "Cannot cache parameter metadata: failed to read" << metaDataFile << readError;
632 return;
633 }
634
635 // Reject non-JSON content (e.g. XML from older PX4 firmware images)
636 // and extract the catalog version in a single parse pass.
637 bool validJson = false;
638 QVersionNumber newVersion = ParameterMetaData::versionFromJsonData(data, &validJson);
639 if (!validJson) {
640 qCDebug(FirmwarePluginLog) << "Skipping cache of non-JSON parameter metadata:" << metaDataFile;
641 return;
642 }
643 if (newVersion.isNull()) {
644 // Valid JSON but no version stamps — use fallback so unversioned
645 // files still get cached with a major version that matches the
646 // default wantedMajorVersion in _cachedParameterMetaDataFile.
647 newVersion = QVersionNumber(1, 0);
648 }
649
650 const int majorVersion = newVersion.majorVersion();
651 const QDir cacheDir = _parameterMetaDataCacheDir(true);
652
653 const QString wildcard = QStringLiteral("%1_%2.%3.*.json").arg(kCachedMetaDataFilePrefix).arg(autopilot).arg(majorVersion);
654 const QStringList existing = cacheDir.entryList(QStringList(wildcard), QDir::Files);
655
656 for (const QString &file : existing) {
657 const QVersionNumber existingVersion = ParameterMetaData::versionFromFileName(file);
658 // Strict less-than: equal versions are replaced so that
659 // re-flashing with corrected metadata (same version stamp)
660 // updates the cache.
661 if (!existingVersion.isNull() && newVersion < existingVersion) {
662 return;
663 }
664 }
665
666 const QString cachePath = cacheDir.filePath(
667 QStringLiteral("%1_%2.%3.%4.json").arg(kCachedMetaDataFilePrefix).arg(autopilot).arg(majorVersion).arg(newVersion.minorVersion()));
668 if (!QGCFileHelper::atomicWrite(cachePath, data)) {
669 qCWarning(FirmwarePluginLog) << "Failed to cache parameter metadata to" << cachePath;
670 return;
671 }
672
673 for (const QString &file : existing) {
674 const QString fullPath = cacheDir.filePath(file);
675 if (fullPath != cachePath && !QFile::remove(fullPath)) {
676 qCWarning(FirmwarePluginLog) << "Failed to remove old cache file:" << file;
677 }
678 }
679}
680
681/*===========================================================================*/
682
static constexpr const char * kCachedMetaDataFilePrefix
static const QString guided_mode_not_supported_by_vehicle
static QDir _parameterMetaDataCacheDir(bool ensureExists=false)
QList< FirmwareFlightMode > FlightModeList
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
#define qgcApp()
struct __mavlink_message mavlink_message_t
Unified file download utility with decompression, verification, and QML support.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_camera_information_t mavlink_camera_information_t
The AutoPilotPlugin class is an abstract base class which represents the methods and objects which ar...
virtual CommandSupportedResult anyVersionSupportsCommand(MAV_CMD) const
CommandSupportedResult getCommandSupported(MAV_CMD cmd) const
The FirmwarePlugin class represents the methods and objects which are specific to a certain Firmware ...
virtual void guidedModeChangeEquivalentAirspeedMetersSecond(Vehicle *vehicle, double airspeed_equiv) const
virtual void guidedModeChangeAltitude(Vehicle *vehicle, double altitudeChange, bool pauseVehicle)
virtual void startMission(Vehicle *vehicle) const
Command the vehicle to start the mission.
virtual void checkIfIsLatestStable(Vehicle *vehicle) const
Used to check if running firmware is latest stable version.
FlightModeList _flightModeList
virtual const QVariantList & toolIndicators(const Vehicle *vehicle)
virtual void guidedModeChangeGroundSpeedMetersSecond(Vehicle *vehicle, double groundspeed) const
virtual bool setFlightMode(const QString &flightMode, uint8_t *base_mode, uint32_t *custom_mode) const
virtual ~FirmwarePlugin()
virtual void _versionFileDownloadFinished(const QString &remoteFile, const QString &localFile, Vehicle *vehicle) const
Callback to process file with latest release information.
virtual void guidedModeTakeoff(Vehicle *vehicle, double takeoffAltRel) const
Command vehicle to takeoff from current location to the specified height.
void _sendROICommand(Vehicle *vehicle, const QGeoCoordinate &coord, MAV_FRAME frame, float altitude) const
Build + send MAV_CMD_DO_SET_ROI_LOCATION (COMMAND_INT when the vehicle supports it).
void cacheParameterMetaDataFile(const QString &metaDataFile)
virtual QString missionCommandOverrides(QGCMAVLinkTypes::VehicleClass_t vehicleClass) const
bool _setFlightModeAndValidate(Vehicle *vehicle, const QString &flightMode) const
virtual QString _internalParameterMetaDataFile(const Vehicle *) const
virtual QString _getLatestVersionFileUrl(Vehicle *) const
returns url with latest firmware release information.
void _updateFlightModeList(FlightModeList &flightModeList)
virtual void guidedModeChangeHeading(Vehicle *vehicle, const QGeoCoordinate &headingCoord) const
Command vehicle to rotate towards specified location.
virtual bool guidedModeGotoLocation(Vehicle *vehicle, const QGeoCoordinate &gotoCoord, double forwardFlightLoiterRadius=0.0) const
static QString stableFirmwareSettingsKey(const Vehicle *vehicle)
Settings key identifying the stable firmware stream (firmware + vehicle class) for this vehicle.
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode) const
virtual void startTakeoff(Vehicle *vehicle) const
Command the vehicle to start a takeoff.
void _addNewFlightMode(FirmwareFlightMode &flightMode)
virtual void pauseVehicle(Vehicle *vehicle) const
virtual MAV_AUTOPILOT _autopilotType() const
int versionCompare(const Vehicle *vehicle, const QString &compare) const
virtual Autotune * createAutotune(Vehicle *vehicle) const
Creates Autotune object.
static bool isStableFirmwareVersionUnseen(const QString &latestVersion, const QString &seenVersion)
ParameterMetaData * loadParameterMetaData(const Vehicle *vehicle)
virtual AutoPilotPlugin * autopilotPlugin(Vehicle *vehicle) const
virtual void guidedModeRTL(Vehicle *vehicle, bool smartRTL) const
Command vehicle to return to launch.
virtual ParameterMetaData * _createParameterMetaData()
virtual QString _versionRegex() const
Returns regex QString to extract version information from text.
bool _armVehicleAndValidate(Vehicle *vehicle) const
QVariantList _toolIndicatorList
QString _cachedParameterMetaDataFile(const Vehicle *vehicle) const
virtual void setGuidedMode(Vehicle *vehicle, bool guidedMode) const
Set guided flight mode.
FlightModeCustomModeMap _modeEnumToString
virtual bool guidedModeROI(Vehicle *vehicle, const QGeoCoordinate &roiCenterCoord, double relativeAltitudeMeters) const
virtual void batteryConsumptionData(Vehicle *vehicle, int &mAhBattery, double &hoverAmps, double &cruiseAmps) const
virtual QGCCameraManager * createCameraManager(Vehicle *vehicle) const
Creates vehicle camera manager.
virtual void sendGCSMotionReport(Vehicle *vehicle, const FollowMe::GCSMotionReport &motionReport, uint8_t estimationCapabilities) const
Sends the appropriate mavlink message for follow me support.
QMap< int, remapParamNameMinorVersionRemapMap_t > remapParamNameMajorVersionMap_t
virtual const remapParamNameMajorVersionMap_t & paramNameRemapMajorVersionMap() const
virtual void guidedModeLand(Vehicle *vehicle) const
Command vehicle to land at current location.
virtual MavlinkCameraControlInterface * createCameraControl(const mavlink_camera_information_t *info, Vehicle *vehicle, int compID, QObject *parent=nullptr) const
Camera control.
virtual bool hasGimbal(Vehicle *vehicle, bool &rollSupported, bool &pitchSupported, bool &yawSupported) const
This is the generic implementation of the AutoPilotPlugin class for mavs we do not have a specific Au...
static int getComponentId()
static MAVLinkProtocol * instance()
Abstract base class for all camera controls: real and simulated.
static QVersionNumber versionFromMetaDataFile(const QString &metaDataFile)
static QVersionNumber versionFromJsonData(const QByteArray &jsonData)
void loadParameterFactMetaDataFile(const QString &metaDataFile)
static QVersionNumber versionFromFileName(const QString &fileName)
Camera Manager.
File download with progress, decompression, and hash verification.
void finished(bool success, const QString &localPath, const QString &errorMessage)
bool start(const QString &remoteUrl)
static bool shouldNotify(const QString &latestVersion, const QString &lastNotifiedVersion)
MAVLink Camera API controller - connected to a real mavlink v2 camera.
WeakLinkInterfacePtr primaryLink() const
void sendMavCommand(int compId, MAV_CMD command, bool showError, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
Definition Vehicle.cc:2173
QString flightMode() const
Definition Vehicle.cc:1485
void setNewStableFirmwareVersion(const QString &version)
Definition Vehicle.cc:2365
uint64_t capabilityBits() const
Definition Vehicle.h:727
MAV_TYPE vehicleType() const
Definition Vehicle.h:446
VehicleLinkManager * vehicleLinkManager()
Definition Vehicle.h:597
void sendMavCommandInt(int compId, MAV_CMD command, MAV_FRAME frame, bool showError, float param1, float param2, float param3, float param4, double param5, double param6, float param7)
Definition Vehicle.cc:2202
int firmwareMinorVersion() const
Definition Vehicle.h:680
MAV_AUTOPILOT firmwareType() const
Definition Vehicle.h:445
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)
Definition Vehicle.cc:1401
void setFlightMode(const QString &flightMode)
Definition Vehicle.cc:1495
int firmwareVersionType() const
Definition Vehicle.h:682
int defaultComponentId() const
Definition Vehicle.h:700
int firmwarePatchVersion() const
Definition Vehicle.h:681
bool armed() const
Definition Vehicle.h:467
Q_INVOKABLE int versionCompare(const QString &compare) const
Used to check if running current version is equal or higher than the one being compared.
Definition Vehicle.cc:2810
int firmwareMajorVersion() const
Definition Vehicle.h:679
void setArmed(bool armed, bool showError)
Definition Vehicle.cc:1456
QByteArray readFile(const QString &filePath, QString *errorString, qint64 maxBytes)
Read file contents, transparently decompressing .gz/.xz/.zst/.bz2/.lz4 files.
bool atomicWrite(const QString &filePath, const QByteArray &data)
bool ensureDirectoryExists(const QString &path)
bool runningUnitTests()
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9
static constexpr VehicleClass_t VehicleClassGeneric