FirmwareUpgrade.qml 17.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*=====================================================================

 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/>.

 ======================================================================*/

Don Gagne's avatar
Don Gagne committed
24
import QtQuick 2.3
25 26
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
27
import QtQuick.Dialogs 1.2
28

Don Gagne's avatar
Don Gagne committed
29 30 31 32 33 34 35
import QGroundControl               1.0
import QGroundControl.Controls      1.0
import QGroundControl.FactSystem    1.0
import QGroundControl.FactControls  1.0
import QGroundControl.Palette       1.0
import QGroundControl.Controllers   1.0
import QGroundControl.ScreenTools   1.0
36

37
QGCView {
38 39 40 41
    id:         qgcView
    viewPanel:  panel

    // User visible strings
Don Gagne's avatar
Don Gagne committed
42
    readonly property string title:             "FIRMWARE"
dogmaphobic's avatar
dogmaphobic committed
43
    readonly property string highlightPrefix:   "<font color=\"" + qgcPal.warningText + "\">"
44 45 46 47 48 49 50
    readonly property string highlightSuffix:   "</font>"
    readonly property string welcomeText:       "QGroundControl can upgrade the firmware on Pixhawk devices, 3DR Radios and PX4 Flow Smart Cameras."
    readonly property string plugInText:        highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade"
    readonly property string qgcDisconnectText: "All QGroundControl connections to vehicles must be disconnected prior to firmware upgrade. " +
                                                    "Click " + highlightPrefix + "Disconnect" + highlightSuffix + " in the toolbar above."
    property string usbUnplugText:              "Device must be disconnected from USB to start firmware upgrade. " +
                                                    highlightPrefix + "Disconnect {0}" + highlightSuffix + " from usb."
51 52

    property string firmwareWarningMessage
53 54 55 56 57 58 59 60 61 62
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

    function cancelFlash() {
        statusTextArea.append(highlightPrefix + "Upgrade cancelled" + highlightSuffix)
        statusTextArea.append("------------------------------------------")
        controller.cancel()
        flashCompleteWaitTimer.running = true
    }
63

64
    QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled }
65

66 67 68 69
    FirmwareUpgradeController {
        id:             controller
        progressBar:    progressBar
        statusLog:      statusTextArea
70

71 72 73 74 75 76 77 78 79 80 81
        Component.onCompleted: {
            controllerCompleted = true
            if (qgcView.completedSignalled) {
                // We can only start the board search when the Qml and Controller are completely done loading
                controller.startBoardSearch()
            }
        }

        onNoBoardFound: {
            initialBoardSearch = false
            statusTextArea.append(plugInText)
82
        }
dogmaphobic's avatar
dogmaphobic committed
83

84 85 86 87
        onBoardGone: {
            initialBoardSearch = false
            statusTextArea.append(plugInText)
        }
dogmaphobic's avatar
dogmaphobic committed
88

89 90 91
        onBoardFound: {
            if (initialBoardSearch) {
                // Board was found right away, so something is already plugged in before we've started upgrade
Don Gagne's avatar
Don Gagne committed
92
                if (QGroundControl.linkManager.anyActiveLinks) {
93 94 95 96 97 98 99
                    statusTextArea.append(qgcDisconnectText)
                } else {
                    statusTextArea.append(usbUnplugText.replace('{0}', controller.boardType))
                }
            } else {
                // We end up here when we detect a board plugged in after we've started upgrade
                statusTextArea.append(highlightPrefix + "Found device" + highlightSuffix + ": " + controller.boardType)
100
                if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow") {
101 102 103 104 105 106 107 108 109 110 111
                    showDialog(pixhawkFirmwareSelectDialog, title, 50, StandardButton.Ok | StandardButton.Cancel)
                 }
             }
         }

        onError: {
            hideDialog()
            flashCompleteWaitTimer.running = true
        }

        onFlashComplete: flashCompleteWaitTimer.running = true
112
    }
Don Gagne's avatar
Don Gagne committed
113

114 115 116 117 118 119
    onCompleted: {
        if (controllerCompleted) {
            // We can only start the board search when the Qml and Controller are completely done loading
            controller.startBoardSearch()
        }
    }
120

121 122 123
    // After a flash completes we start this timer to trigger resetting the ui back to it's initial state of being ready to
    // flash another board. We do this only after the timer triggers to leave the results of the previous flash on the screen
    // for a small amount amount of time.
124

125 126 127
    Timer {
        id:         flashCompleteWaitTimer
        interval:   15000
128

129 130 131 132 133
        onTriggered: {
            initialBoardSearch = true
            progressBar.value = 0
            statusTextArea.append(welcomeText)
            controller.startBoardSearch()
134
        }
135 136 137 138
    }

    Component {
        id: pixhawkFirmwareSelectDialog
139

140
        QGCViewDialog {
141
            anchors.fill: parent
dogmaphobic's avatar
dogmaphobic committed
142

Pritam Ghanghas's avatar
Pritam Ghanghas committed
143
            property bool showFirmwareTypeSelection: advancedMode.checked
144
            property bool px4Flow:              controller.boardType == "PX4 Flow"
145

146 147
            function accept() {
                hideDialog()
148
                var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
149 150 151 152
                if (px4Flow) {
                    stack = FirmwareUpgradeController.PX4Flow
                }

153 154 155 156 157 158
                var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
                var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
                if (apmFlightStack.checked) {
                    vehicleType = vehicleTypeSelectionCombo.model.get(vehicleTypeSelectionCombo.currentIndex).vehicleType
                }
                controller.flash(stack, firmwareType, vehicleType)
159
            }
dogmaphobic's avatar
dogmaphobic committed
160

161 162 163 164
            function reject() {
                cancelFlash()
                hideDialog()
            }
dogmaphobic's avatar
dogmaphobic committed
165

166 167 168
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
169

170
            ListModel {
171
                id: firmwareTypeList
172 173

                ListElement {
174
                    text:           "Standard Version (stable)";
175
                    firmwareType:   FirmwareUpgradeController.StableFirmware
176 177
                }
                ListElement {
178
                    text:           "Beta Testing (beta)";
179
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
180 181
                }
                ListElement {
182
                    text:           "Developer Build (master)";
183
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
184 185
                }
                ListElement {
186
                    text:           "Custom firmware file...";
187
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
188
                 }
189
            }
dogmaphobic's avatar
dogmaphobic committed
190

191
            ListModel {
192
                id: vehicleTypeList
193

194 195 196
                ListElement {
                    text: "Quad"
                    vehicleType: FirmwareUpgradeController.QuadFirmware
197 198
                }
                ListElement {
199 200
                    text: "X8"
                    vehicleType: FirmwareUpgradeController.X8Firmware
201 202
                }
                ListElement {
203 204
                    text: "Hexa"
                    vehicleType: FirmwareUpgradeController.HexaFirmware
205 206
                }
                ListElement {
207 208
                    text: "Octo"
                    vehicleType: FirmwareUpgradeController.OctoFirmware
209 210
                }
                ListElement {
211 212
                    text: "Y"
                    vehicleType: FirmwareUpgradeController.YFirmware
213 214
                }
                ListElement {
215 216
                    text: "Y6"
                    vehicleType: FirmwareUpgradeController.Y6Firmware
217 218
                }
                ListElement {
219 220
                    text: "Heli"
                    vehicleType: FirmwareUpgradeController.HeliFirmware
221 222
                }
                ListElement {
223 224
                    text: "Plane"
                    vehicleType: FirmwareUpgradeController.PlaneFirmware
225 226 227
                }
                ListElement {
                    text: "Rover"
228
                    vehicleType: FirmwareUpgradeController.RoverFirmware
229
                }
230 231
            }

232 233 234 235 236
            ListModel {
                id: px4FlowTypeList

                ListElement {
                    text:           "Standard Version (stable)";
237
                    firmwareType:   FirmwareUpgradeController.StableFirmware
238 239 240
                }
                ListElement {
                    text:           "Custom firmware file...";
241
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
242 243
                 }
            }
dogmaphobic's avatar
dogmaphobic committed
244

245 246 247 248 249 250 251
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
252
                    text:       px4Flow ? "Detected PX4 Flow board. You can select from the following firmware:" : "Detected Pixhawk board. You can select from the following flight stacks:"
253
                }
254

255 256 257 258 259 260 261 262 263 264
                function firmwareVersionChanged(model) {
                    firmwareVersionWarningLabel.visible = false
                    // All of this bizarre, setting model to null and index to 1 and then to 0 is to work around
                    // strangeness in the combo box implementation. This sequence of steps correctly changes the combo model
                    // without generating any warnings and correctly updates the combo text with the new selection.
                    firmwareVersionCombo.model = null
                    firmwareVersionCombo.model = model
                    firmwareVersionCombo.currentIndex = 1
                    firmwareVersionCombo.currentIndex = 0
                }
265

266 267 268 269 270 271 272 273 274 275 276
                function vehicleTypeChanged(model) {
                    vehicleTypeSelectionCombo.model = null
                    // All of this bizarre, setting model to null and index to 1 and then to 0 is to work around
                    // strangeness in the combo box implementation. This sequence of steps correctly changes the combo model
                    // without generating any warnings and correctly updates the combo text with the new selection.
                    vehicleTypeSelectionCombo.model = null
                    vehicleTypeSelectionCombo.model = model
                    vehicleTypeSelectionCombo.currentIndex = 1
                    vehicleTypeSelectionCombo.currentIndex = 0
                }

277 278 279 280 281
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
                    text:           "PX4 Flight Stack (full QGC support)"
282
                    visible:        !px4Flow
283

284
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
285 286 287 288 289 290
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
                    text:           "APM Flight Stack (partial QGC support)"
291
                    visible:        !px4Flow
292

293 294 295 296
                    onClicked: {
                        parent.firmwareVersionChanged(firmwareTypeList)
                        parent.vehicleTypeChanged(vehicleTypeList)
                    }
297
                }
298

299 300 301
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
302
                    visible:    showFirmwareTypeSelection
303
                    text:       px4Flow ? "Select which version of the firmware you would like to install:" : "Select which version of the above flight stack you would like to install:"
304
                }
305

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
                Row {
                    spacing: 10
                    QGCComboBox {
                        id:         firmwareVersionCombo
                        width:      200
                        visible:    showFirmwareTypeSelection
                        model:      px4Flow ? px4FlowTypeList : firmwareTypeList

                        onActivated: {
                            if (model.get(index).firmwareType == FirmwareUpgradeController.PX4BetaFirmware || FirmwareUpgradeController.APMBetaFirmware ) {
                                firmwareVersionWarningLabel.visible = true
                                firmwareVersionWarningLabel.text = "WARNING: BETA FIRMWARE. " +
                                        "This firmware version is ONLY intended for beta testers. " +
                                        "Although it has received FLIGHT TESTING, it represents actively changed code. " +
                                        "Do NOT use for normal operation."
                            } else if (model.get(index).firmwareType == FirmwareUpgradeController.PX4DeveloperFirmware || FirmwareUpgradeController.APMDeveloperFirmware) {
                                firmwareVersionWarningLabel.visible = true
                                firmwareVersionWarningLabel.text = "WARNING: CONTINUOUS BUILD FIRMWARE. " +
                                        "This firmware has NOT BEEN FLIGHT TESTED. " +
                                        "It is only intended for DEVELOPERS. " +
                                        "Run bench tests without props first. " +
                                        "Do NOT fly this without addional safety precautions. " +
                                        "Follow the mailing list actively when using it."
                            } else {
                                firmwareVersionWarningLabel.visible = false
                            }
332
                        }
333 334 335 336 337 338 339 340 341
                    }

                    QGCComboBox {
                        id:         vehicleTypeSelectionCombo
                        width:      200
                        visible:    apmFlightStack.checked
                        model:      vehicleTypeList
                    }
                }
342 343 344 345 346 347 348

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
349 350
            }

351 352 353 354
            QGCCheckBox {
                id:             advancedMode
                anchors.bottom: parent.bottom
                text:           "Advanced mode"
355 356
                checked:        px4Flow ? true : false
                visible:        !px4Flow
357 358 359 360

                onClicked: {
                    firmwareVersionCombo.currentIndex = 0
                    firmwareVersionWarningLabel.visible = false
361
                }
362
            }
363

364 365 366 367 368 369
            QGCButton {
                anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
                anchors.left:       advancedMode.right
                anchors.bottom:     parent.bottom
                text:               "Help me pick a flight stack"
                onClicked:          Qt.openUrlExternally("http://pixhawk.org/choice")
370
                visible:            !px4Flow
371
            }
372 373 374 375 376 377 378 379 380
        } // QGCViewDialog
    } // Component - pixhawkFirmwareSelectDialog


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
381

382 383 384
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
385
            }
386 387 388 389 390 391
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
392

393 394 395
        QGCLabel {
            id:             titleLabel
            text:           title
Don Gagne's avatar
Don Gagne committed
396
            font.pixelSize: ScreenTools.mediumFontPixelSize
397
        }
398

399 400 401 402 403 404
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
405

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
        TextArea {
            id:                 statusTextArea
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        progressBar.bottom
            anchors.bottom:     parent.bottom
            width:              parent.width
            readOnly:           true
            frameVisible:       false
            font.pixelSize:     ScreenTools.defaultFontPixelSize
            textFormat:         TextEdit.RichText
            text:               welcomeText

            style: TextAreaStyle {
                textColor:          qgcPal.text
                backgroundColor:    qgcPal.windowShade
421
            }
422 423
        }
    } // QGCViewPabel
424
} // QGCView