You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
809 lines
41 KiB
809 lines
41 KiB
/*===================================================================== |
|
|
|
QGroundControl Open Source Ground Control Station |
|
|
|
(c) 2009, 2015 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/>. |
|
|
|
======================================================================*/ |
|
|
|
/// @file |
|
/// @brief PX4 Firmware Upgrade UI |
|
/// @author Don Gagne <don@thegagnes.com> |
|
|
|
#include "FirmwareUpgradeController.h" |
|
#include "Bootloader.h" |
|
#include "QGCFileDialog.h" |
|
#include "QGCApplication.h" |
|
#include "QGCFileDownload.h" |
|
|
|
#include <QStandardPaths> |
|
#include <QRegularExpression> |
|
|
|
struct FirmwareToUrlElement_t { |
|
FirmwareUpgradeController::AutoPilotStackType_t stackType; |
|
FirmwareUpgradeController::FirmwareType_t firmwareType; |
|
FirmwareUpgradeController::FirmwareVehicleType_t vehicleType; |
|
QString url; |
|
}; |
|
|
|
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId) |
|
{ |
|
return ( firmwareId.autopilotStackType | |
|
(firmwareId.firmwareType << 8) | |
|
(firmwareId.firmwareVehicleType << 16) ); |
|
} |
|
|
|
/// @Brief Constructs a new FirmwareUpgradeController Widget. This widget is used within the PX4VehicleConfig set of screens. |
|
FirmwareUpgradeController::FirmwareUpgradeController(void) |
|
: _downloadManager(NULL) |
|
, _downloadNetworkReply(NULL) |
|
, _statusLog(NULL) |
|
, _selectedFirmwareType(StableFirmware) |
|
, _image(NULL) |
|
{ |
|
_threadController = new PX4FirmwareUpgradeThreadController(this); |
|
Q_CHECK_PTR(_threadController); |
|
|
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::foundBoard, this, &FirmwareUpgradeController::_foundBoard); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::noBoardFound, this, &FirmwareUpgradeController::_noBoardFound); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::boardGone, this, &FirmwareUpgradeController::_boardGone); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::foundBootloader, this, &FirmwareUpgradeController::_foundBootloader); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::bootloaderSyncFailed, this, &FirmwareUpgradeController::_bootloaderSyncFailed); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::error, this, &FirmwareUpgradeController::_error); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::updateProgress, this, &FirmwareUpgradeController::_updateProgress); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::status, this, &FirmwareUpgradeController::_status); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::eraseStarted, this, &FirmwareUpgradeController::_eraseStarted); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::eraseComplete, this, &FirmwareUpgradeController::_eraseComplete); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::flashComplete, this, &FirmwareUpgradeController::_flashComplete); |
|
connect(_threadController, &PX4FirmwareUpgradeThreadController::updateProgress, this, &FirmwareUpgradeController::_updateProgress); |
|
|
|
connect(&_eraseTimer, &QTimer::timeout, this, &FirmwareUpgradeController::_eraseProgressTick); |
|
|
|
_initFirmwareHash(); |
|
} |
|
|
|
FirmwareUpgradeController::~FirmwareUpgradeController() |
|
{ |
|
qgcApp()->toolbox()->linkManager()->setConnectionsAllowed(); |
|
} |
|
|
|
void FirmwareUpgradeController::startBoardSearch(void) |
|
{ |
|
LinkManager* linkMgr = qgcApp()->toolbox()->linkManager(); |
|
|
|
linkMgr->setConnectionsSuspended(tr("Connect not allowed during Firmware Upgrade.")); |
|
|
|
// FIXME: Why did we get here with active vehicle? |
|
if (!qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()) { |
|
// We have to disconnect any inactive links |
|
linkMgr->disconnectAll(); |
|
} |
|
|
|
_bootloaderFound = false; |
|
_startFlashWhenBootloaderFound = false; |
|
_threadController->startFindBoardLoop(); |
|
} |
|
|
|
void FirmwareUpgradeController::flash(AutoPilotStackType_t stackType, |
|
FirmwareType_t firmwareType, |
|
FirmwareVehicleType_t vehicleType) |
|
{ |
|
FirmwareIdentifier firmwareId = FirmwareIdentifier(stackType, firmwareType, vehicleType); |
|
if (_bootloaderFound) { |
|
_getFirmwareFile(firmwareId); |
|
} else { |
|
// We haven't found the bootloader yet. Need to wait until then to flash |
|
_startFlashWhenBootloaderFound = true; |
|
_startFlashWhenBootloaderFoundFirmwareIdentity = firmwareId; |
|
} |
|
} |
|
|
|
void FirmwareUpgradeController::flash(const FirmwareIdentifier& firmwareId) |
|
{ |
|
flash(firmwareId.autopilotStackType, firmwareId.firmwareType, firmwareId.firmwareVehicleType); |
|
} |
|
|
|
void FirmwareUpgradeController::cancel(void) |
|
{ |
|
_eraseTimer.stop(); |
|
_threadController->cancel(); |
|
} |
|
|
|
void FirmwareUpgradeController::_foundBoard(bool firstAttempt, const QSerialPortInfo& info, int boardType) |
|
{ |
|
_foundBoardInfo = info; |
|
_foundBoardType = (QGCSerialPortInfo::BoardType_t)boardType; |
|
|
|
switch (boardType) { |
|
case QGCSerialPortInfo::BoardTypePX4FMUV1: |
|
_foundBoardTypeName = "PX4 FMU V1"; |
|
_startFlashWhenBootloaderFound = false; |
|
break; |
|
case QGCSerialPortInfo::BoardTypePX4FMUV2: |
|
case QGCSerialPortInfo::BoardTypePX4FMUV4: |
|
_foundBoardTypeName = "Pixhawk"; |
|
_startFlashWhenBootloaderFound = false; |
|
break; |
|
case QGCSerialPortInfo::BoardTypeAeroCore: |
|
_foundBoardTypeName = "AeroCore"; |
|
_startFlashWhenBootloaderFound = false; |
|
break; |
|
case QGCSerialPortInfo::BoardTypePX4Flow: |
|
_foundBoardTypeName = "PX4 Flow"; |
|
_startFlashWhenBootloaderFound = false; |
|
break; |
|
case QGCSerialPortInfo::BoardTypeSikRadio: |
|
_foundBoardTypeName = "SiK Radio"; |
|
if (!firstAttempt) { |
|
// Radio always flashes latest firmware, so we can start right away without |
|
// any further user input. |
|
_startFlashWhenBootloaderFound = true; |
|
_startFlashWhenBootloaderFoundFirmwareIdentity = FirmwareIdentifier(ThreeDRRadio, |
|
StableFirmware, |
|
DefaultVehicleFirmware); |
|
} |
|
break; |
|
} |
|
|
|
qCDebug(FirmwareUpgradeLog) << _foundBoardType; |
|
emit boardFound(); |
|
_loadAPMVersions(_foundBoardType); |
|
} |
|
|
|
|
|
void FirmwareUpgradeController::_noBoardFound(void) |
|
{ |
|
emit noBoardFound(); |
|
} |
|
|
|
void FirmwareUpgradeController::_boardGone(void) |
|
{ |
|
emit boardGone(); |
|
} |
|
|
|
/// @brief Called when the bootloader is connected to by the findBootloader process. Moves the state machine |
|
/// to the next step. |
|
void FirmwareUpgradeController::_foundBootloader(int bootloaderVersion, int boardID, int flashSize) |
|
{ |
|
_bootloaderFound = true; |
|
_bootloaderVersion = bootloaderVersion; |
|
_bootloaderBoardID = boardID; |
|
_bootloaderBoardFlashSize = flashSize; |
|
|
|
_appendStatusLog("Connected to bootloader:"); |
|
_appendStatusLog(QString(" Version: %1").arg(_bootloaderVersion)); |
|
_appendStatusLog(QString(" Board ID: %1").arg(_bootloaderBoardID)); |
|
_appendStatusLog(QString(" Flash size: %1").arg(_bootloaderBoardFlashSize)); |
|
|
|
if (_startFlashWhenBootloaderFound) { |
|
flash(_startFlashWhenBootloaderFoundFirmwareIdentity); |
|
} |
|
} |
|
|
|
|
|
/// @brief intializes the firmware hashes with proper urls. |
|
/// This happens only once for a class instance first time when it is needed. |
|
void FirmwareUpgradeController::_initFirmwareHash() |
|
{ |
|
// indirect check whether this function has been called before or not |
|
// may have to be modified if _rgPX4FMUV2Firmware disappears |
|
if (!_rgPX4FMUV2Firmware.isEmpty()) { |
|
return; |
|
} |
|
|
|
//////////////////////////////////// PX4FMUV4 firmwares ////////////////////////////////////////////////// |
|
FirmwareToUrlElement_t rgPX4FMV4FirmwareArray[] = { |
|
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v4_default.px4"}, |
|
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v4_default.px4"}, |
|
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v4_default.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v4.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v4.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v4.px4"} |
|
}; |
|
|
|
//////////////////////////////////// PX4FMUV2 firmwares ////////////////////////////////////////////////// |
|
FirmwareToUrlElement_t rgPX4FMV2FirmwareArray[] = { |
|
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v2_default.px4"}, |
|
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v2_default.px4"}, |
|
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v2_default.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v2.px4"} |
|
}; |
|
|
|
//////////////////////////////////// PX4FMU aerocore firmwares ////////////////////////////////////////////////// |
|
FirmwareToUrlElement_t rgAeroCoreFirmwareArray[] = { |
|
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/stable/aerocore_default.px4"}, |
|
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/beta/aerocore_default.px4"}, |
|
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/master/aerocore_default.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://gumstix-aerocore.s3.amazonaws.com/APM/Copter/stable/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/stable/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/stable/PX4/APMrover2-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, YFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/beta/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/beta/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/beta/PX4/APMrover2-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-octa-quad/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-hexa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-octa/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-tri/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-y6/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-heli/ArduCopter-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/latest/PX4/ArduPlane-v2.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/latest/PX4/APMrover2-v2.px4"} |
|
}; |
|
|
|
/////////////////////////////// FMUV1 firmwares /////////////////////////////////////////// |
|
FirmwareToUrlElement_t rgPX4FMUV1FirmwareArray[] = { |
|
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v1_default.px4"}, |
|
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/px4fmu-v1_default.px4"}, |
|
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/px4fmu-v1_default.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-hexa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-octa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-tri/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/stable/PX4-y6/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v1.px4"}, |
|
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-hexa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-octa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-tri/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/beta/PX4-y6/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v1.px4"}, |
|
{ AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, QuadFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, X8Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa-quad/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HexaFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-hexa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, OctoFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-octa/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, YFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-tri/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, Y6Firmware, "http://firmware.ardupilot.org/Copter/latest/PX4-y6/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v1.px4"}, |
|
{ AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v1.px4"} |
|
}; |
|
|
|
/////////////////////////////// px4flow firmwares /////////////////////////////////////// |
|
FirmwareToUrlElement_t rgPX4FLowFirmwareArray[] = { |
|
{ PX4Flow, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Flow/master/px4flow.px4" }, |
|
}; |
|
|
|
/////////////////////////////// 3dr radio firmwares /////////////////////////////////////// |
|
FirmwareToUrlElement_t rg3DRRadioFirmwareArray[] = { |
|
{ ThreeDRRadio, StableFirmware, DefaultVehicleFirmware, "http://firmware.ardupilot.org/SiK/stable/radio~hm_trp.ihx"} |
|
}; |
|
|
|
// populate hashes now |
|
int size = sizeof(rgPX4FMV4FirmwareArray)/sizeof(rgPX4FMV4FirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rgPX4FMV4FirmwareArray[i]; |
|
_rgPX4FMUV4Firmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
|
|
size = sizeof(rgPX4FMV2FirmwareArray)/sizeof(rgPX4FMV2FirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rgPX4FMV2FirmwareArray[i]; |
|
_rgPX4FMUV2Firmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
|
|
size = sizeof(rgAeroCoreFirmwareArray)/sizeof(rgAeroCoreFirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rgAeroCoreFirmwareArray[i]; |
|
_rgAeroCoreFirmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
|
|
size = sizeof(rgPX4FMUV1FirmwareArray)/sizeof(rgPX4FMUV1FirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rgPX4FMUV1FirmwareArray[i]; |
|
_rgPX4FMUV1Firmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
|
|
size = sizeof(rgPX4FLowFirmwareArray)/sizeof(rgPX4FLowFirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rgPX4FLowFirmwareArray[i]; |
|
_rgPX4FLowFirmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
|
|
size = sizeof(rg3DRRadioFirmwareArray)/sizeof(rg3DRRadioFirmwareArray[0]); |
|
for (int i = 0; i < size; i++) { |
|
const FirmwareToUrlElement_t& element = rg3DRRadioFirmwareArray[i]; |
|
_rg3DRRadioFirmware.insert(FirmwareIdentifier(element.stackType, element.firmwareType, element.vehicleType), element.url); |
|
} |
|
} |
|
|
|
/// @brief Called when the findBootloader process is unable to sync to the bootloader. Moves the state |
|
/// machine to the appropriate error state. |
|
void FirmwareUpgradeController::_bootloaderSyncFailed(void) |
|
{ |
|
_errorCancel("Unable to sync with bootloader."); |
|
} |
|
|
|
QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* FirmwareUpgradeController::_firmwareHashForBoardId(int boardId) |
|
{ |
|
switch (boardId) { |
|
case Bootloader::boardIDPX4FMUV1: |
|
return &_rgPX4FMUV1Firmware; |
|
case Bootloader::boardIDPX4Flow: |
|
return &_rgPX4FLowFirmware; |
|
case Bootloader::boardIDPX4FMUV2: |
|
return &_rgPX4FMUV2Firmware; |
|
case Bootloader::boardIDPX4FMUV4: |
|
return &_rgPX4FMUV4Firmware; |
|
case Bootloader::boardIDAeroCore: |
|
return &_rgAeroCoreFirmware; |
|
case Bootloader::boardID3DRRadio: |
|
return &_rg3DRRadioFirmware; |
|
default: |
|
return NULL; |
|
} |
|
} |
|
|
|
QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* FirmwareUpgradeController::_firmwareHashForBoardType(QGCSerialPortInfo::BoardType_t boardType) |
|
{ |
|
int boardId = Bootloader::boardIDPX4FMUV2; |
|
|
|
switch (boardType) { |
|
case QGCSerialPortInfo::BoardTypePX4FMUV1: |
|
boardId = Bootloader::boardIDPX4FMUV1; |
|
break; |
|
case QGCSerialPortInfo::BoardTypePX4FMUV2: |
|
boardId = Bootloader::boardIDPX4FMUV2; |
|
break; |
|
case QGCSerialPortInfo::BoardTypePX4FMUV4: |
|
boardId = Bootloader::boardIDPX4FMUV4; |
|
break; |
|
case QGCSerialPortInfo::BoardTypeAeroCore: |
|
boardId = Bootloader::boardIDAeroCore; |
|
break; |
|
case QGCSerialPortInfo::BoardTypePX4Flow: |
|
boardId = Bootloader::boardIDPX4Flow; |
|
break; |
|
case QGCSerialPortInfo::BoardTypeSikRadio: |
|
boardId = Bootloader::boardID3DRRadio; |
|
break; |
|
default: |
|
qWarning() << "Internal error: invalid board type for flashing" << boardType; |
|
boardId = Bootloader::boardIDPX4FMUV2; |
|
break; |
|
} |
|
|
|
return _firmwareHashForBoardId(boardId); |
|
} |
|
|
|
|
|
/// @brief Prompts the user to select a firmware file if needed and moves the state machine to the next state. |
|
void FirmwareUpgradeController::_getFirmwareFile(FirmwareIdentifier firmwareId) |
|
{ |
|
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardId(_bootloaderBoardID); |
|
|
|
if (!prgFirmware && firmwareId.firmwareType != CustomFirmware) { |
|
_errorCancel("Attempting to flash an unknown board type, you must select 'Custom firmware file'"); |
|
return; |
|
} |
|
|
|
if (firmwareId.firmwareType == CustomFirmware) { |
|
_firmwareFilename = QGCFileDialog::getOpenFileName(NULL, // Parent to main window |
|
"Select Firmware File", // Dialog Caption |
|
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory |
|
"Firmware Files (*.px4 *.bin *.ihx)"); // File filter |
|
} else { |
|
|
|
if (prgFirmware->contains(firmwareId)) { |
|
_firmwareFilename = prgFirmware->value(firmwareId); |
|
} else { |
|
_errorCancel("Unable to find specified firmware download location"); |
|
return; |
|
} |
|
} |
|
|
|
if (_firmwareFilename.isEmpty()) { |
|
_errorCancel("No firmware file selected"); |
|
} else { |
|
_downloadFirmware(); |
|
} |
|
} |
|
|
|
/// @brief Begins the process of downloading the selected firmware file. |
|
void FirmwareUpgradeController::_downloadFirmware(void) |
|
{ |
|
Q_ASSERT(!_firmwareFilename.isEmpty()); |
|
|
|
_appendStatusLog("Downloading firmware..."); |
|
_appendStatusLog(QString(" From: %1").arg(_firmwareFilename)); |
|
|
|
// Split out filename from path |
|
QString firmwareFilename = QFileInfo(_firmwareFilename).fileName(); |
|
Q_ASSERT(!firmwareFilename.isEmpty()); |
|
|
|
// Determine location to download file to |
|
QString downloadFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation); |
|
if (downloadFile.isEmpty()) { |
|
downloadFile = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); |
|
if (downloadFile.isEmpty()) { |
|
_errorCancel("Unabled to find writable download location. Tried downloads and temp directory."); |
|
return; |
|
} |
|
} |
|
Q_ASSERT(!downloadFile.isEmpty()); |
|
downloadFile += "/" + firmwareFilename; |
|
|
|
QUrl firmwareUrl; |
|
if (_firmwareFilename.startsWith("http:")) { |
|
firmwareUrl.setUrl(_firmwareFilename); |
|
} else { |
|
firmwareUrl = QUrl::fromLocalFile(_firmwareFilename); |
|
} |
|
Q_ASSERT(firmwareUrl.isValid()); |
|
|
|
QNetworkRequest networkRequest(firmwareUrl); |
|
|
|
// Store download file location in user attribute so we can retrieve when the download finishes |
|
networkRequest.setAttribute(QNetworkRequest::User, downloadFile); |
|
|
|
_downloadManager = new QNetworkAccessManager(this); |
|
Q_CHECK_PTR(_downloadManager); |
|
_downloadNetworkReply = _downloadManager->get(networkRequest); |
|
Q_ASSERT(_downloadNetworkReply); |
|
connect(_downloadNetworkReply, &QNetworkReply::downloadProgress, this, &FirmwareUpgradeController::_downloadProgress); |
|
connect(_downloadNetworkReply, &QNetworkReply::finished, this, &FirmwareUpgradeController::_downloadFinished); |
|
|
|
connect(_downloadNetworkReply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), |
|
this, &FirmwareUpgradeController::_downloadError); |
|
} |
|
|
|
/// @brief Updates the progress indicator while downloading |
|
void FirmwareUpgradeController::_downloadProgress(qint64 curr, qint64 total) |
|
{ |
|
// Take care of cases where 0 / 0 is emitted as error return value |
|
if (total > 0) { |
|
_progressBar->setProperty("value", (float)curr / (float)total); |
|
} |
|
} |
|
|
|
/// @brief Called when the firmware download completes. |
|
void FirmwareUpgradeController::_downloadFinished(void) |
|
{ |
|
_appendStatusLog("Download complete"); |
|
|
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(QObject::sender()); |
|
Q_ASSERT(reply); |
|
|
|
Q_ASSERT(_downloadNetworkReply == reply); |
|
|
|
_downloadManager->deleteLater(); |
|
_downloadManager = NULL; |
|
|
|
// When an error occurs or the user cancels the download, we still end up here. So bail out in |
|
// those cases. |
|
if (reply->error() != QNetworkReply::NoError) { |
|
return; |
|
} |
|
|
|
// Download file location is in user attribute |
|
QString downloadFilename = reply->request().attribute(QNetworkRequest::User).toString(); |
|
Q_ASSERT(!downloadFilename.isEmpty()); |
|
|
|
// Store downloaded file in download location |
|
QFile file(downloadFilename); |
|
if (!file.open(QIODevice::WriteOnly)) { |
|
_errorCancel(QString("Could not save downloaded file to %1. Error: %2").arg(downloadFilename).arg(file.errorString())); |
|
return; |
|
} |
|
|
|
file.write(reply->readAll()); |
|
file.close(); |
|
FirmwareImage* image = new FirmwareImage(this); |
|
|
|
connect(image, &FirmwareImage::statusMessage, this, &FirmwareUpgradeController::_status); |
|
connect(image, &FirmwareImage::errorMessage, this, &FirmwareUpgradeController::_error); |
|
|
|
if (!image->load(downloadFilename, _bootloaderBoardID)) { |
|
_errorCancel("Image load failed"); |
|
return; |
|
} |
|
|
|
// We can't proceed unless we have the bootloader |
|
if (!_bootloaderFound) { |
|
_errorCancel("Bootloader not found"); |
|
return; |
|
} |
|
|
|
if (_bootloaderBoardFlashSize != 0 && image->imageSize() > _bootloaderBoardFlashSize) { |
|
_errorCancel(QString("Image size of %1 is too large for board flash size %2").arg(image->imageSize()).arg(_bootloaderBoardFlashSize)); |
|
return; |
|
} |
|
|
|
_threadController->flash(image); |
|
} |
|
|
|
/// @brief Called when an error occurs during download |
|
void FirmwareUpgradeController::_downloadError(QNetworkReply::NetworkError code) |
|
{ |
|
QString errorMsg; |
|
|
|
if (code == QNetworkReply::OperationCanceledError) { |
|
errorMsg = "Download cancelled"; |
|
|
|
} else if (code == QNetworkReply::ContentNotFoundError) { |
|
errorMsg = QString("Error: File Not Found. Please check %1 firmware version is available.") |
|
.arg(firmwareTypeAsString(_selectedFirmwareType)); |
|
|
|
} else { |
|
errorMsg = QString("Error during download. Error: %1").arg(code); |
|
} |
|
_errorCancel(errorMsg); |
|
} |
|
|
|
/// @brief returns firmware type as a string |
|
QString FirmwareUpgradeController::firmwareTypeAsString(FirmwareType_t type) const |
|
{ |
|
switch (type) { |
|
case StableFirmware: |
|
return "stable"; |
|
case DeveloperFirmware: |
|
return "developer"; |
|
case BetaFirmware: |
|
return "beta"; |
|
default: |
|
return "custom"; |
|
} |
|
} |
|
|
|
/// @brief Signals completion of one of the specified bootloader commands. Moves the state machine to the |
|
/// appropriate next step. |
|
void FirmwareUpgradeController::_flashComplete(void) |
|
{ |
|
delete _image; |
|
_image = NULL; |
|
|
|
_appendStatusLog("Upgrade complete", true); |
|
_appendStatusLog("------------------------------------------", false); |
|
emit flashComplete(); |
|
qgcApp()->toolbox()->linkManager()->setConnectionsAllowed(); |
|
} |
|
|
|
void FirmwareUpgradeController::_error(const QString& errorString) |
|
{ |
|
delete _image; |
|
_image = NULL; |
|
|
|
_errorCancel(QString("Error: %1").arg(errorString)); |
|
} |
|
|
|
void FirmwareUpgradeController::_status(const QString& statusString) |
|
{ |
|
_appendStatusLog(statusString); |
|
} |
|
|
|
/// @brief Updates the progress bar from long running bootloader commands |
|
void FirmwareUpgradeController::_updateProgress(int curr, int total) |
|
{ |
|
// Take care of cases where 0 / 0 is emitted as error return value |
|
if (total > 0) { |
|
_progressBar->setProperty("value", (float)curr / (float)total); |
|
} |
|
} |
|
|
|
/// @brief Moves the progress bar ahead on tick while erasing the board |
|
void FirmwareUpgradeController::_eraseProgressTick(void) |
|
{ |
|
_eraseTickCount++; |
|
_progressBar->setProperty("value", (float)(_eraseTickCount*_eraseTickMsec) / (float)_eraseTotalMsec); |
|
} |
|
|
|
/// Appends the specified text to the status log area in the ui |
|
void FirmwareUpgradeController::_appendStatusLog(const QString& text, bool critical) |
|
{ |
|
Q_ASSERT(_statusLog); |
|
|
|
QVariant returnedValue; |
|
QVariant varText; |
|
|
|
if (critical) { |
|
varText = QString("<font color=\"yellow\">%1</font>").arg(text); |
|
} else { |
|
varText = text; |
|
} |
|
|
|
QMetaObject::invokeMethod(_statusLog, |
|
"append", |
|
Q_RETURN_ARG(QVariant, returnedValue), |
|
Q_ARG(QVariant, varText)); |
|
} |
|
|
|
void FirmwareUpgradeController::_errorCancel(const QString& msg) |
|
{ |
|
_appendStatusLog(msg, false); |
|
_appendStatusLog("Upgrade cancelled", true); |
|
_appendStatusLog("------------------------------------------", false); |
|
emit error(); |
|
cancel(); |
|
qgcApp()->toolbox()->linkManager()->setConnectionsAllowed(); |
|
} |
|
|
|
void FirmwareUpgradeController::_eraseStarted(void) |
|
{ |
|
// We set up our own progress bar for erase since the erase command does not provide one |
|
_eraseTickCount = 0; |
|
_eraseTimer.start(_eraseTickMsec); |
|
} |
|
|
|
void FirmwareUpgradeController::_eraseComplete(void) |
|
{ |
|
_eraseTimer.stop(); |
|
} |
|
|
|
void FirmwareUpgradeController::_loadAPMVersions(QGCSerialPortInfo::BoardType_t boardType) |
|
{ |
|
_apmVersionMap.clear(); |
|
|
|
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardType(boardType); |
|
|
|
foreach (FirmwareIdentifier firmwareId, prgFirmware->keys()) { |
|
if (firmwareId.autopilotStackType == AutoPilotStackAPM) { |
|
QString versionFile = QFileInfo(prgFirmware->value(firmwareId)).path() + "/git-version.txt"; |
|
|
|
qCDebug(FirmwareUpgradeLog) << "Downloading" << versionFile; |
|
QGCFileDownload* downloader = new QGCFileDownload(this); |
|
connect(downloader, &QGCFileDownload::downloadFinished, this, &FirmwareUpgradeController::_apmVersionDownloadFinished); |
|
downloader->download(versionFile); |
|
} |
|
} |
|
} |
|
|
|
|
|
void FirmwareUpgradeController::_apmVersionDownloadFinished(QString remoteFile, QString localFile) |
|
{ |
|
qCDebug(FirmwareUpgradeLog) << "Download complete" << remoteFile << localFile; |
|
|
|
// Now read the version file and pull out the version string |
|
|
|
QFile versionFile(localFile); |
|
versionFile.open(QIODevice::ReadOnly | QIODevice::Text); |
|
QTextStream stream(&versionFile); |
|
QString versionContents = stream.readAll(); |
|
|
|
QString version; |
|
QRegularExpression re("APMVERSION: (.*)$"); |
|
QRegularExpressionMatch match = re.match(versionContents); |
|
if (match.hasMatch()) { |
|
version = match.captured(1); |
|
} |
|
|
|
if (version.isEmpty()) { |
|
qWarning() << "Unable to parse version info from file" << remoteFile; |
|
return; |
|
} |
|
|
|
// In order to determine the firmware and vehicle type for this file we find the matching entry in the firmware list |
|
|
|
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardType(_foundBoardType); |
|
|
|
QString remotePath = QFileInfo(remoteFile).path(); |
|
foreach (FirmwareIdentifier firmwareId, prgFirmware->keys()) { |
|
if (remotePath == QFileInfo((*prgFirmware)[firmwareId]).path()) { |
|
qCDebug(FirmwareUpgradeLog) << "Adding version to map, version:firwmareType:vehicleType" << version << firmwareId.firmwareType << firmwareId.firmwareVehicleType; |
|
_apmVersionMap[firmwareId.firmwareType][firmwareId.firmwareVehicleType] = version; |
|
} |
|
} |
|
|
|
emit apmAvailableVersionsChanged(); |
|
} |
|
|
|
void FirmwareUpgradeController::setSelectedFirmwareType(FirmwareType_t firmwareType) |
|
{ |
|
_selectedFirmwareType = firmwareType; |
|
emit selectedFirmwareTypeChanged(_selectedFirmwareType); |
|
emit apmAvailableVersionsChanged(); |
|
} |
|
|
|
QStringList FirmwareUpgradeController::apmAvailableVersions(void) |
|
{ |
|
QStringList list; |
|
|
|
_apmVehicleTypeFromCurrentVersionList.clear(); |
|
|
|
foreach (FirmwareVehicleType_t vehicleType, _apmVersionMap[_selectedFirmwareType].keys()) { |
|
QString version; |
|
|
|
switch (vehicleType) { |
|
case QuadFirmware: |
|
version = "Quad - "; |
|
break; |
|
case X8Firmware: |
|
version = "X8 - "; |
|
break; |
|
case HexaFirmware: |
|
version = "Hexa - "; |
|
break; |
|
case OctoFirmware: |
|
version = "Octo - "; |
|
break; |
|
case YFirmware: |
|
version = "Y - "; |
|
break; |
|
case Y6Firmware: |
|
version = "Y6 - "; |
|
break; |
|
case HeliFirmware: |
|
version = "Heli - "; |
|
break; |
|
case PlaneFirmware: |
|
case RoverFirmware: |
|
case DefaultVehicleFirmware: |
|
break; |
|
} |
|
|
|
version += _apmVersionMap[_selectedFirmwareType][vehicleType]; |
|
_apmVehicleTypeFromCurrentVersionList.append(vehicleType); |
|
|
|
list << version; |
|
} |
|
|
|
return list; |
|
} |
|
|
|
FirmwareUpgradeController::FirmwareVehicleType_t FirmwareUpgradeController::vehicleTypeFromVersionIndex(int index) |
|
{ |
|
if (index < 0 || index >= _apmVehicleTypeFromCurrentVersionList.count()) { |
|
qWarning() << "Invalid index, index:count" << index << _apmVehicleTypeFromCurrentVersionList.count(); |
|
return QuadFirmware; |
|
} |
|
|
|
return _apmVehicleTypeFromCurrentVersionList[index]; |
|
}
|
|
|