FirmwareUpgradeController.h 15.2 KB
Newer Older
1
/****************************************************************************
2
 *
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10
#pragma once
11

12
#include "PX4FirmwareUpgradeThread.h"
13
#include "FirmwareImage.h"
14
#include "Fact.h"
15 16

#include <QObject>
17 18 19 20
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
21 22
#include <QPixmap>
#include <QQuickItem>
23
#include <QSerialPort>
24

25 26
#include <stdint.h>

27 28
/// Supported firmware types. If you modify these you will need to update the qml file as well.

29 30
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
31 32
{
    Q_OBJECT
33
    
34
public:
35
        typedef enum {
36
            AutoPilotStackPX4 = 0,
37
            AutoPilotStackAPM,
38 39
            PX4FlowPX4,
            PX4FlowAPM,
40 41
            ThreeDRRadio,
            SingleFirmwareMode
42 43 44
        } AutoPilotStackType_t;

        typedef enum {
45
            StableFirmware = 0,
46 47 48
            BetaFirmware,
            DeveloperFirmware,
            CustomFirmware
49
        } FirmwareBuildType_t;
50 51

        typedef enum {
52
            CopterFirmware = 0,
Don Gagne's avatar
Don Gagne committed
53
            HeliFirmware,
54 55
            PlaneFirmware,
            RoverFirmware,
56
            SubFirmware,
57
            DefaultVehicleFirmware
58 59
        } FirmwareVehicleType_t;

60
        Q_ENUM(AutoPilotStackType_t)
61
        Q_ENUM(FirmwareBuildType_t)
62
        Q_ENUM(FirmwareVehicleType_t)
63 64 65 66 67

    class FirmwareIdentifier
    {
    public:
        FirmwareIdentifier(AutoPilotStackType_t stack = AutoPilotStackPX4,
68
                           FirmwareBuildType_t firmware = StableFirmware,
69 70 71
                           FirmwareVehicleType_t vehicle = DefaultVehicleFirmware)
            : autopilotStackType(stack), firmwareType(firmware), firmwareVehicleType(vehicle) {}

72
        bool operator==(const FirmwareIdentifier& firmwareId) const
73
        {
74 75 76
            return (firmwareId.autopilotStackType == autopilotStackType &&
                    firmwareId.firmwareType == firmwareType &&
                    firmwareId.firmwareVehicleType == firmwareVehicleType);
77 78 79 80
        }

        // members
        AutoPilotStackType_t    autopilotStackType;
81
        FirmwareBuildType_t          firmwareType;
82 83 84
        FirmwareVehicleType_t   firmwareVehicleType;
    };

85
    FirmwareUpgradeController(void);
Don Gagne's avatar
Don Gagne committed
86 87
    ~FirmwareUpgradeController();

88 89 90 91 92 93 94 95 96 97 98 99
    Q_PROPERTY(bool                 downloadingFirmwareList     MEMBER _downloadingFirmwareList                                     NOTIFY downloadingFirmwareListChanged)
    Q_PROPERTY(QString              boardPort                   READ boardPort                                                      NOTIFY boardFound)
    Q_PROPERTY(QString              boardDescription            READ boardDescription                                               NOTIFY boardFound)
    Q_PROPERTY(QString              boardType                   MEMBER _boardTypeName                                               NOTIFY boardFound)
    Q_PROPERTY(bool                 pixhawkBoard                READ pixhawkBoard                                                   NOTIFY boardFound)
    Q_PROPERTY(bool                 px4FlowBoard                READ px4FlowBoard                                                   NOTIFY boardFound)
    Q_PROPERTY(FirmwareBuildType_t  selectedFirmwareBuildType   READ selectedFirmwareBuildType  WRITE setSelectedFirmwareBuildType  NOTIFY selectedFirmwareBuildTypeChanged)
    Q_PROPERTY(QStringList          apmFirmwareNames            MEMBER _apmFirmwareNames                                            NOTIFY apmFirmwareNamesChanged)
    Q_PROPERTY(int                  apmFirmwareNamesBestIndex   MEMBER _apmFirmwareNamesBestIndex                                   NOTIFY apmFirmwareNamesChanged)
    Q_PROPERTY(QStringList          apmFirmwareUrls             MEMBER _apmFirmwareUrls                                             NOTIFY apmFirmwareNamesChanged)
    Q_PROPERTY(QString              px4StableVersion            READ px4StableVersion                                               NOTIFY px4StableVersionChanged)
    Q_PROPERTY(QString              px4BetaVersion              READ px4BetaVersion                                                 NOTIFY px4BetaVersionChanged)
100

101 102 103
    /// TextArea for log output
    Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
    
104 105
    /// Progress bar for you know what
    Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
106 107 108

    /// Starts searching for boards on the background thread
    Q_INVOKABLE void startBoardSearch(void);
109
    
110 111
    /// Cancels whatever state the upgrade worker thread is in
    Q_INVOKABLE void cancel(void);
112
    
113
    /// Called when the firmware type has been selected by the user to continue the flash process.
114
    Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
115
                           FirmwareBuildType_t firmwareType = StableFirmware,
116
                           FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
117

118 119
    Q_INVOKABLE void flashFirmwareUrl(QString firmwareUrl);

120
    /// Called to flash when upgrade is running in singleFirmwareMode
121
    Q_INVOKABLE void flashSingleFirmwareMode(FirmwareBuildType_t firmwareType);
122

123
    Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromFirmwareSelectionIndex(int index);
124
    
125 126 127
    // overload, not exposed to qml side
    void flash(const FirmwareIdentifier& firmwareId);

128
    // Property accessors
129
    
130 131 132
    QQuickItem* progressBar(void) { return _progressBar; }
    void setProgressBar(QQuickItem* progressBar) { _progressBar = progressBar; }
    
133 134 135
    QQuickItem* statusLog(void) { return _statusLog; }
    void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
    
136 137 138 139 140 141
    QString boardPort(void) { return _boardInfo.portName(); }
    QString boardDescription(void) { return _boardInfo.description(); }

    FirmwareBuildType_t selectedFirmwareBuildType(void) { return _selectedFirmwareBuildType; }
    void setSelectedFirmwareBuildType(FirmwareBuildType_t firmwareType);
    QString firmwareTypeAsString(FirmwareBuildType_t type) const;
142

143 144
    QString     px4StableVersion    (void) { return _px4StableVersion; }
    QString     px4BetaVersion  (void) { return _px4BetaVersion; }
145

146 147
    bool pixhawkBoard(void) const { return _boardType == QGCSerialPortInfo::BoardTypePixhawk; }
    bool px4FlowBoard(void) const { return _boardType == QGCSerialPortInfo::BoardTypePX4Flow; }
148

149 150 151 152 153 154
    /**
     * @brief Return a human friendly string of available boards
     *
     * @return availableBoardNames
     */
    Q_INVOKABLE QStringList availableBoardsName(void);
155

156
signals:
157 158 159 160 161 162 163 164 165 166 167 168
    void boardFound                     (void);
    void bootloaderFound                (void);
    void noBoardFound                   (void);
    void boardGone                      (void);
    void flashComplete                  (void);
    void flashCancelled                 (void);
    void error                          (void);
    void selectedFirmwareBuildTypeChanged(FirmwareBuildType_t firmwareType);
    void apmFirmwareNamesChanged        (void);
    void px4StableVersionChanged        (const QString& px4StableVersion);
    void px4BetaVersionChanged          (const QString& px4BetaVersion);
    void downloadingFirmwareListChanged (bool downloadingFirmwareList);
169

170
private slots:
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    void _firmwareDownloadProgress          (qint64 curr, qint64 total);
    void _firmwareDownloadComplete          (QString remoteFile, QString localFile, QString errorMsg);
    void _foundBoard                        (bool firstAttempt, const QSerialPortInfo& portInfo, int boardType, QString boardName);
    void _noBoardFound                      (void);
    void _boardGone                         (void);
    void _foundBoardInfo                    (int bootloaderVersion, int boardID, int flashSize);
    void _error                             (const QString& errorString);
    void _status                            (const QString& statusString);
    void _bootloaderSyncFailed              (void);
    void _flashComplete                     (void);
    void _updateProgress                    (int curr, int total);
    void _eraseStarted                      (void);
    void _eraseComplete                     (void);
    void _eraseProgressTick                 (void);
    void _px4ReleasesGithubDownloadComplete (QString remoteFile, QString localFile, QString errorMsg);
    void _ardupilotManifestDownloadComplete (QString remoteFile, QString localFile, QString errorMsg);
    void _buildAPMFirmwareNames             (void);
188 189

private:
190
    QHash<FirmwareIdentifier, QString>* _firmwareHashForBoardId(int boardId);
191 192 193 194 195 196 197
    void _getFirmwareFile           (FirmwareIdentifier firmwareId);
    void _initFirmwareHash          (void);
    void _downloadFirmware          (void);
    void _appendStatusLog           (const QString& text, bool critical = false);
    void _errorCancel               (const QString& msg);
    void _determinePX4StableVersion (void);
    void _downloadArduPilotManifest (void);
198

199 200
    QString _singleFirmwareURL;
    bool    _singleFirmwareMode;
201
    bool    _downloadingFirmwareList;
202 203 204
    QString _portName;
    QString _portDescription;

205 206 207 208 209
    // Firmware hashes
    QHash<FirmwareIdentifier, QString> _rgFMUV5Firmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV4PROFirmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV4Firmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV3Firmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
210 211
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
    QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
212
    QHash<FirmwareIdentifier, QString> _rgAUAVX2_1Firmware;
Henry Zhang's avatar
Henry Zhang committed
213
    QHash<FirmwareIdentifier, QString> _rgMindPXFMUV2Firmware;
214 215
    QHash<FirmwareIdentifier, QString> _rgTAPV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgASCV1Firmware;
216
    QHash<FirmwareIdentifier, QString> _rgCrazyflie2Firmware;
217
    QHash<FirmwareIdentifier, QString> _rgOmnibusF4SDFirmware;
218 219 220 221 222 223
    QHash<FirmwareIdentifier, QString> _rgKakuteF7Firmware;
    QHash<FirmwareIdentifier, QString> _rgDurandalV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgFMUK66V3Firmware;
    QHash<FirmwareIdentifier, QString> _rgModalFCV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgmRoCtrlZeroF7Firmware;
    QHash<FirmwareIdentifier, QString> _rgUVifyCoreFirmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
224 225
    QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
    QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;
226 227 228
    QHash<FirmwareIdentifier, QString> _rgPX4CUAVX7Fireware;
    QHash<FirmwareIdentifier, QString> _rgCUAVNoraFireware;

Pritam Ghanghas's avatar
Pritam Ghanghas committed
229

230 231 232 233
    // Hash map for ArduPilot ChibiOS lookup by board name
    QHash<FirmwareIdentifier, QString> _rgAPMChibiosReplaceNamedBoardFirmware;
    QHash<FirmwareIdentifier, QString> _rgFirmwareDynamic;

234
    QMap<FirmwareBuildType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
235 236
    QList<FirmwareVehicleType_t>                                _apmVehicleTypeFromCurrentVersionList;

237 238 239 240 241 242
    /// Information which comes back from the bootloader
    bool        _bootloaderFound;           ///< true: we have received the foundBootloader signals
    uint32_t    _bootloaderVersion;         ///< Bootloader version
    uint32_t    _bootloaderBoardID;         ///< Board ID
    uint32_t    _bootloaderBoardFlashSize;  ///< Flash size in bytes of board
    
243 244
    bool                 _startFlashWhenBootloaderFound;
    FirmwareIdentifier   _startFlashWhenBootloaderFoundFirmwareIdentity;
245 246 247 248 249 250 251 252

    QPixmap _boardIcon;             ///< Icon used to display image of board
    
    QString _firmwareFilename;      ///< Image which we are going to flash to the board
    
    QNetworkAccessManager*  _downloadManager;       ///< Used for firmware file downloading across the internet
    QNetworkReply*          _downloadNetworkReply;  ///< Used for firmware file downloading across the internet
    
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
253
    /// @brief Thread controller which is used to run bootloader commands on separate thread
254 255 256 257 258 259 260 261 262 263
    PX4FirmwareUpgradeThreadController* _threadController;
    
    static const int    _eraseTickMsec = 500;       ///< Progress bar update tick time for erase
    static const int    _eraseTotalMsec = 15000;    ///< Estimated amount of time erase takes
    int                 _eraseTickCount;            ///< Number of ticks for erase progress update
    QTimer              _eraseTimer;                ///< Timer used to update progress bar for erase

    static const int    _findBoardTimeoutMsec = 30000;      ///< Amount of time for user to plug in USB
    static const int    _findBootloaderTimeoutMsec = 5000;  ///< Amount time to look for bootloader
    
264
    QQuickItem*     _statusLog;         ///< Status log TextArea Qml control
265
    QQuickItem*     _progressBar;
266 267
    
    bool _searchingForBoard;    ///< true: searching for board, false: search for bootloader
268
    
269 270 271
    QSerialPortInfo                 _boardInfo;
    QGCSerialPortInfo::BoardType_t  _boardType;
    QString                         _boardTypeName;
272

273
    FirmwareBuildType_t             _selectedFirmwareBuildType;
274

275
    FirmwareImage*                  _image;
Don Gagne's avatar
Don Gagne committed
276 277

    QString _px4StableVersion;  // Version strange for latest PX4 stable
278
    QString _px4BetaVersion;    // Version strange for latest PX4 beta
279 280

    const QString _apmBoardDescriptionReplaceText;
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

    static const char* _manifestFirmwareJsonKey;
    static const char* _manifestBoardIdJsonKey;
    static const char* _manifestMavTypeJsonKey;
    static const char* _manifestFormatJsonKey;
    static const char* _manifestUrlJsonKey;
    static const char* _manifestMavFirmwareVersionTypeJsonKey;
    static const char* _manifestUSBIDJsonKey;
    static const char* _manifestMavFirmwareVersionJsonKey;
    static const char* _manifestBootloaderStrJsonKey;
    static const char* _manifestLatestKey;
    static const char* _manifestPlatformKey;
    static const char* _manifestBrandNameKey;

    typedef struct {
        uint32_t                boardId;
        FirmwareBuildType_t     firmwareBuildType;
        FirmwareVehicleType_t   vehicleType;
        QString                 url;
        QString                 version;
        QStringList             rgBootloaderPortString;
        QList<int>              rgVID;
        QList<int>              rgPID;
        QString                 friendlyName;
        bool                    chibios;
        bool                    fmuv2;
    } ManifestFirmwareInfo_t;


    QList<ManifestFirmwareInfo_t>           _rgManifestFirmwareInfo;
    QMap<QString, FirmwareBuildType_t>      _manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap;
    QMap<QString, FirmwareVehicleType_t>    _manifestMavTypeToFirmwareVehicleTypeMap;
    QStringList                             _apmFirmwareNames;
    int                                     _apmFirmwareNamesBestIndex = 0;
    QStringList                             _apmFirmwareUrls;
    Fact*                                   _apmChibiOSSetting;
    Fact*                                   _apmVehicleTypeSetting;

    FirmwareBuildType_t     _manifestMavFirmwareVersionTypeToFirmwareBuildType  (const QString& manifestMavFirmwareVersionType);
    FirmwareVehicleType_t   _manifestMavTypeToFirmwareVehicleType               (const QString& manifestMavType);
321 322
};

323
// global hashing function
324
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);