FirmwareUpgrade.qml 15.3 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
    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"
Don Gagne's avatar
Don Gagne committed
47
    readonly property string qgcDisconnectText: "All QGroundControl connections to vehicles must be disconnected prior to firmware upgrade."
48 49
    property string usbUnplugText:              "Device must be disconnected from USB to start firmware upgrade. " +
                                                    highlightPrefix + "Disconnect {0}" + highlightSuffix + " from usb."
50 51

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

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

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

70 71
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

72 73 74 75 76 77 78 79
        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()
            }
        }

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

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

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

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

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

        onFlashComplete: flashCompleteWaitTimer.running = true
123
    }
Don Gagne's avatar
Don Gagne committed
124

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

132 133 134
    // 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.
135

136 137 138
    Timer {
        id:         flashCompleteWaitTimer
        interval:   15000
139

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

    Component {
        id: pixhawkFirmwareSelectDialog
150

151
        QGCViewDialog {
152
            anchors.fill: parent
dogmaphobic's avatar
dogmaphobic committed
153

Pritam Ghanghas's avatar
Pritam Ghanghas committed
154
            property bool showFirmwareTypeSelection: advancedMode.checked
155
            property bool px4Flow:              controller.boardType == "PX4 Flow"
156

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

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

172 173 174 175
            function reject() {
                cancelFlash()
                hideDialog()
            }
dogmaphobic's avatar
dogmaphobic committed
176

177 178 179
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
180

181
            ListModel {
182
                id: firmwareTypeList
183 184

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

202 203 204 205 206
            ListModel {
                id: px4FlowTypeList

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

215 216 217 218 219 220 221
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

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

225 226 227 228 229 230 231 232 233 234
                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
                }
235

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

243
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
244 245 246 247 248
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
Don Gagne's avatar
Don Gagne committed
249
                    text:           "APM Flight Stack"
250
                    visible:        !px4Flow
251

252
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
253
                }
254

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

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

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

                    QGCComboBox {
                        id:         vehicleTypeSelectionCombo
                        width:      200
                        visible:    apmFlightStack.checked
297
                        model:      controller.apmAvailableVersions
298 299
                    }
                }
300 301 302 303 304 305 306

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
307 308
            }

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

                onClicked: {
                    firmwareVersionCombo.currentIndex = 0
                    firmwareVersionWarningLabel.visible = false
319
                }
320
            }
321

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


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
339

340 341 342
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
343
            }
344 345 346 347 348 349
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
350

351 352 353
        QGCLabel {
            id:             titleLabel
            text:           title
Don Gagne's avatar
Don Gagne committed
354
            font.pixelSize: ScreenTools.mediumFontPixelSize
355
        }
356

357 358 359 360 361 362
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
363

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