FirmwareUpgrade.qml 15.8 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
    readonly property string highlightSuffix:   "</font>"
    readonly property string welcomeText:       "QGroundControl can upgrade the firmware on Pixhawk devices, 3DR Radios and PX4 Flow Smart Cameras."
46 47 48
    readonly property string plugInText:        highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade. "
    readonly property string flashFailText:     "If upgrade failed, make sure to connect " + highlightPrefix + "directly" + highlightSuffix + " to a powered USB port on your computer, not through a USB hub. " +
                                                "Also make sure you are only powered via USB " + highlightPrefix + "not battery" + highlightSuffix + "."
Don Gagne's avatar
Don Gagne committed
49
    readonly property string qgcDisconnectText: "All QGroundControl connections to vehicles must be disconnected prior to firmware upgrade."
50 51
    property string usbUnplugText:              "Device must be disconnected from USB to start firmware upgrade. " +
                                                    highlightPrefix + "Disconnect {0}" + highlightSuffix + " from usb."
52 53

    property string firmwareWarningMessage
54 55 56 57 58 59 60 61 62 63
    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
    }
64

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

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

72 73
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

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()
            }
        }

82 83 84 85 86 87
        onActiveVehicleChanged: {
            if (!activeVehicle) {
                statusTextArea.append(plugInText)
            }
        }

88 89
        onNoBoardFound: {
            initialBoardSearch = false
90 91 92
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
93
        }
dogmaphobic's avatar
dogmaphobic committed
94

95 96
        onBoardGone: {
            initialBoardSearch = false
97 98 99
            if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
                statusTextArea.append(plugInText)
            }
100
        }
dogmaphobic's avatar
dogmaphobic committed
101

102 103 104
        onBoardFound: {
            if (initialBoardSearch) {
                // Board was found right away, so something is already plugged in before we've started upgrade
105
                if (QGroundControl.multiVehicleManager.activeVehicleAvailable) {
106 107 108 109 110 111 112
                    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)
113
                if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow" || controller.boardType == "PX4 FMU V1") {
114
                    showDialog(pixhawkFirmwareSelectDialog, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
115 116 117 118 119 120
                 }
             }
         }

        onError: {
            hideDialog()
121
            statusTextArea.append(flashFailText)
122 123 124 125
            flashCompleteWaitTimer.running = true
        }

        onFlashComplete: flashCompleteWaitTimer.running = true
126
    }
Don Gagne's avatar
Don Gagne committed
127

128 129 130 131 132 133
    onCompleted: {
        if (controllerCompleted) {
            // We can only start the board search when the Qml and Controller are completely done loading
            controller.startBoardSearch()
        }
    }
134

135 136 137
    // 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.
138

139 140 141
    Timer {
        id:         flashCompleteWaitTimer
        interval:   15000
142

143 144 145 146 147
        onTriggered: {
            initialBoardSearch = true
            progressBar.value = 0
            statusTextArea.append(welcomeText)
            controller.startBoardSearch()
148
        }
149 150 151 152
    }

    Component {
        id: pixhawkFirmwareSelectDialog
153

154
        QGCViewDialog {
155
            anchors.fill: parent
dogmaphobic's avatar
dogmaphobic committed
156

Pritam Ghanghas's avatar
Pritam Ghanghas committed
157
            property bool showFirmwareTypeSelection: advancedMode.checked
158
            property bool px4Flow:              controller.boardType == "PX4 Flow"
159

160 161
            function accept() {
                hideDialog()
162
                var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
163 164 165 166
                if (px4Flow) {
                    stack = FirmwareUpgradeController.PX4Flow
                }

167 168 169
                var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
                var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
                if (apmFlightStack.checked) {
170
                    vehicleType = controller.vehicleTypeFromVersionIndex(vehicleTypeSelectionCombo.currentIndex)
171 172
                }
                controller.flash(stack, firmwareType, vehicleType)
173
            }
dogmaphobic's avatar
dogmaphobic committed
174

175 176 177 178
            function reject() {
                cancelFlash()
                hideDialog()
            }
dogmaphobic's avatar
dogmaphobic committed
179

180 181 182
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
183

184
            ListModel {
185
                id: firmwareTypeList
186 187

                ListElement {
188
                    text:           "Standard Version (stable)";
189
                    firmwareType:   FirmwareUpgradeController.StableFirmware
190 191
                }
                ListElement {
192
                    text:           "Beta Testing (beta)";
193
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
194 195
                }
                ListElement {
196
                    text:           "Developer Build (master)";
197
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
198 199
                }
                ListElement {
200
                    text:           "Custom firmware file...";
201
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
202
                 }
203
            }
dogmaphobic's avatar
dogmaphobic committed
204

205 206 207 208 209
            ListModel {
                id: px4FlowTypeList

                ListElement {
                    text:           "Standard Version (stable)";
210
                    firmwareType:   FirmwareUpgradeController.StableFirmware
211 212 213
                }
                ListElement {
                    text:           "Custom firmware file...";
214
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
215 216
                 }
            }
dogmaphobic's avatar
dogmaphobic committed
217

218 219 220 221 222 223 224
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

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

228 229 230 231 232 233 234 235 236 237
                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
                }
238

239 240 241 242
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
Don Gagne's avatar
Don Gagne committed
243
                    text:           "PX4 Flight Stack"
244
                    visible:        !px4Flow
245

246
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
247 248 249 250 251
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
Don Gagne's avatar
Don Gagne committed
252
                    text:           "APM Flight Stack"
253
                    visible:        !px4Flow
254

255
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
256
                }
257

258 259 260
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
261
                    visible:    showFirmwareTypeSelection
262
                    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:"
263
                }
264

265 266 267
                Row {
                    spacing: 10
                    QGCComboBox {
268 269 270 271 272
                        id:             firmwareVersionCombo
                        width:          200
                        visible:        showFirmwareTypeSelection
                        model:          px4Flow ? px4FlowTypeList : firmwareTypeList
                        currentIndex:   controller.selectedFirmwareType
273 274

                        onActivated: {
275 276
                            controller.selectedFirmwareType = index
                            if (model.get(index).firmwareType == FirmwareUpgradeController.BetaFirmware) {
277 278 279 280 281
                                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."
282
                            } else if (model.get(index).firmwareType == FirmwareUpgradeController.DeveloperFirmware) {
283 284 285 286 287 288 289 290 291 292
                                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
                            }
293
                        }
294 295 296 297 298 299
                    }

                    QGCComboBox {
                        id:         vehicleTypeSelectionCombo
                        width:      200
                        visible:    apmFlightStack.checked
300
                        model:      controller.apmAvailableVersions
301 302
                    }
                }
303 304 305 306 307 308 309

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
310 311
            }

312 313 314 315
            QGCCheckBox {
                id:             advancedMode
                anchors.bottom: parent.bottom
                text:           "Advanced mode"
316 317
                checked:        px4Flow ? true : false
                visible:        !px4Flow
318 319 320 321

                onClicked: {
                    firmwareVersionCombo.currentIndex = 0
                    firmwareVersionWarningLabel.visible = false
322
                }
323
            }
324

325 326 327 328 329 330
            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")
331
                visible:            !px4Flow
332
            }
333 334 335 336 337 338 339 340 341
        } // QGCViewDialog
    } // Component - pixhawkFirmwareSelectDialog


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
342

343 344 345
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
346
            }
347 348 349 350 351 352
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
353

354 355 356
        QGCLabel {
            id:             titleLabel
            text:           title
Don Gagne's avatar
Don Gagne committed
357
            font.pixelSize: ScreenTools.mediumFontPixelSize
358
        }
359

360 361 362 363 364 365
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
366

367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
        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
382
            }
383 384
        }
    } // QGCViewPabel
385
} // QGCView