FirmwareUpgrade.qml 14.9 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 50
    readonly property string qgcUnplugText1:    "All QGroundControl connections to vehicles must be " + highlightPrefix + " disconnected " + highlightSuffix + "prior to firmware upgrade."
    readonly property string qgcUnplugText2:    highlightPrefix + "<big>Please unplug your Pixhawk and/or Radio from USB.</big>" + highlightSuffix
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
        property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

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

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

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

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

101 102 103
        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
104 105
                statusTextArea.append(qgcUnplugText1)
                statusTextArea.append(qgcUnplugText2)
106 107 108
            } 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)
109
                if (controller.boardType == "Pixhawk" || controller.boardType == "AeroCore" || controller.boardType == "PX4 Flow" || controller.boardType == "PX4 FMU V1") {
110
                    showDialog(pixhawkFirmwareSelectDialog, title, qgcView.showDialogDefaultWidth, StandardButton.Ok | StandardButton.Cancel)
111 112 113 114 115 116
                 }
             }
         }

        onError: {
            hideDialog()
117
            statusTextArea.append(flashFailText)
118 119
            flashCompleteWaitTimer.running = true
        }
120
    }
Don Gagne's avatar
Don Gagne committed
121

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

129 130
    Component {
        id: pixhawkFirmwareSelectDialog
131

132
        QGCViewDialog {
133
            anchors.fill: parent
dogmaphobic's avatar
dogmaphobic committed
134

Pritam Ghanghas's avatar
Pritam Ghanghas committed
135
            property bool showFirmwareTypeSelection: advancedMode.checked
136
            property bool px4Flow:              controller.boardType == "PX4 Flow"
137

138 139
            function accept() {
                hideDialog()
140
                var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
141 142 143 144
                if (px4Flow) {
                    stack = FirmwareUpgradeController.PX4Flow
                }

145 146 147
                var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
                var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
                if (apmFlightStack.checked) {
148
                    vehicleType = controller.vehicleTypeFromVersionIndex(vehicleTypeSelectionCombo.currentIndex)
149 150
                }
                controller.flash(stack, firmwareType, vehicleType)
151
            }
dogmaphobic's avatar
dogmaphobic committed
152

153 154 155 156
            function reject() {
                cancelFlash()
                hideDialog()
            }
dogmaphobic's avatar
dogmaphobic committed
157

158 159 160
            ExclusiveGroup {
                id: firmwareGroup
            }
dogmaphobic's avatar
dogmaphobic committed
161

162
            ListModel {
163
                id: firmwareTypeList
164 165

                ListElement {
166
                    text:           "Standard Version (stable)";
167
                    firmwareType:   FirmwareUpgradeController.StableFirmware
168 169
                }
                ListElement {
170
                    text:           "Beta Testing (beta)";
171
                    firmwareType:   FirmwareUpgradeController.BetaFirmware
172 173
                }
                ListElement {
174
                    text:           "Developer Build (master)";
175
                    firmwareType:   FirmwareUpgradeController.DeveloperFirmware
176 177
                }
                ListElement {
178
                    text:           "Custom firmware file...";
179
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
180
                 }
181
            }
dogmaphobic's avatar
dogmaphobic committed
182

183 184 185 186 187
            ListModel {
                id: px4FlowTypeList

                ListElement {
                    text:           "Standard Version (stable)";
188
                    firmwareType:   FirmwareUpgradeController.StableFirmware
189 190 191
                }
                ListElement {
                    text:           "Custom firmware file...";
192
                    firmwareType:   FirmwareUpgradeController.CustomFirmware
193 194
                 }
            }
dogmaphobic's avatar
dogmaphobic committed
195

196 197 198 199 200 201 202
            Column {
                anchors.fill:   parent
                spacing:        defaultTextHeight

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

206 207 208 209 210 211 212 213 214 215
                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
                }
216

217 218 219 220
                QGCRadioButton {
                    id:             px4FlightStack
                    checked:        true
                    exclusiveGroup: firmwareGroup
Don Gagne's avatar
Don Gagne committed
221
                    text:           "PX4 Flight Stack"
222
                    visible:        !px4Flow
223

224
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
225 226 227 228 229
                }

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
Don Gagne's avatar
Don Gagne committed
230
                    text:           "APM Flight Stack"
231
                    visible:        !px4Flow
232

233
                    onClicked: parent.firmwareVersionChanged(firmwareTypeList)
234
                }
235

236 237 238
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
239
                    visible:    showFirmwareTypeSelection
240
                    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:"
241
                }
242

243 244 245
                Row {
                    spacing: 10
                    QGCComboBox {
246 247 248 249 250
                        id:             firmwareVersionCombo
                        width:          200
                        visible:        showFirmwareTypeSelection
                        model:          px4Flow ? px4FlowTypeList : firmwareTypeList
                        currentIndex:   controller.selectedFirmwareType
251 252

                        onActivated: {
253 254
                            controller.selectedFirmwareType = index
                            if (model.get(index).firmwareType == FirmwareUpgradeController.BetaFirmware) {
255 256 257 258 259
                                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."
260
                            } else if (model.get(index).firmwareType == FirmwareUpgradeController.DeveloperFirmware) {
261 262 263 264 265
                                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. " +
nopeppermint's avatar
nopeppermint committed
266
                                        "Do NOT fly this without additonal safety precautions. " +
267 268 269 270
                                        "Follow the mailing list actively when using it."
                            } else {
                                firmwareVersionWarningLabel.visible = false
                            }
271
                        }
272 273 274 275 276 277
                    }

                    QGCComboBox {
                        id:         vehicleTypeSelectionCombo
                        width:      200
                        visible:    apmFlightStack.checked
278
                        model:      controller.apmAvailableVersions
279 280
                    }
                }
281 282 283 284 285 286 287

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
288 289
            }

290 291 292 293
            QGCCheckBox {
                id:             advancedMode
                anchors.bottom: parent.bottom
                text:           "Advanced mode"
294 295
                checked:        px4Flow ? true : false
                visible:        !px4Flow
296 297 298 299

                onClicked: {
                    firmwareVersionCombo.currentIndex = 0
                    firmwareVersionWarningLabel.visible = false
300
                }
301
            }
302

303 304 305 306 307 308
            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")
309
                visible:            !px4Flow
310
            }
311 312 313 314 315 316 317 318 319
        } // QGCViewDialog
    } // Component - pixhawkFirmwareSelectDialog


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
320

321 322 323
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
324
            }
325 326 327 328 329 330
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
331

332 333 334
        QGCLabel {
            id:             titleLabel
            text:           title
Don Gagne's avatar
Don Gagne committed
335
            font.pixelSize: ScreenTools.mediumFontPixelSize
336
        }
337

338 339 340 341 342 343
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
344

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
        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
360
            }
361 362
        }
    } // QGCViewPabel
363
} // QGCView