FirmwareUpgrade.qml 15.1 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
    readonly property string highlightSuffix:   "</font>"
45
    readonly property string welcomeText:       "QGroundControl can upgrade the firmware on Pixhawk devices, SiK Radios and PX4 Flow Smart Cameras."
46
    readonly property string plugInText:        "<big>" + highlightPrefix + "Plug in your device" + highlightSuffix + " via USB to " + highlightPrefix + "start" + highlightSuffix + " firmware upgrade.</big>"
47 48
    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
    property bool   controllerCompleted:      false
    property bool   initialBoardSearch:       true
    property string firmwareName

    function cancelFlash() {
        statusTextArea.append(highlightPrefix + "Upgrade cancelled" + highlightSuffix)
        statusTextArea.append("------------------------------------------")
        controller.cancel()
    }
62

Don Gagne's avatar
Don Gagne committed
63
    QGCPalette { id: qgcPal; colorGroupEnabled: true }
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
Don Gagne's avatar
Don Gagne committed
103 104
                statusTextArea.append(qgcUnplugText1)
                statusTextArea.append(qgcUnplugText2)
105
                QGroundControl.multiVehicleManager.activeVehicle.autoDisconnect = true
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
    }
Don Gagne's avatar
Don Gagne committed
120

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

128 129
    Component {
        id: pixhawkFirmwareSelectDialog
130

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

134
            property bool showFirmwareTypeSelection: _advanced.checked
135
            property bool px4Flow:              controller.boardType == "PX4 Flow"
136

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

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

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

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

161
            ListModel {
162
                id: firmwareTypeList
163 164

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

182 183 184 185 186
            ListModel {
                id: px4FlowTypeList

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

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

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

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

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

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

                QGCRadioButton {
                    id:             apmFlightStack
                    exclusiveGroup: firmwareGroup
229
                    text:           "ArduPilot Flight Stack"
230
                    visible:        !px4Flow
231

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

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
                QGCComboBox {
                    id:         vehicleTypeSelectionCombo
                    width:      200
                    visible:    apmFlightStack.checked
                    model:      controller.apmAvailableVersions
                }

                Row {
                    width:      parent.width
                    spacing:    ScreenTools.defaultFontPixelWidth / 2
                    visible:    !px4Flow

                    Rectangle {
                        height: 1
                        width:      ScreenTools.defaultFontPixelWidth * 5
                        color:      qgcPal.text
                        anchors.verticalCenter: _advanced.verticalCenter
                    }

                    QGCCheckBox {
                        id:         _advanced
                        text:       "Advanced settings"
                        checked:    px4Flow ? true : false

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

                    Rectangle {
                        height:     1
                        width:      ScreenTools.defaultFontPixelWidth * 5
                        color:      qgcPal.text
                        anchors.verticalCenter: _advanced.verticalCenter
                    }
                }

273 274 275
                QGCLabel {
                    width:      parent.width
                    wrapMode:   Text.WordWrap
276
                    visible:    showFirmwareTypeSelection
277
                    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:"
278
                }
279

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
                QGCComboBox {
                    id:             firmwareVersionCombo
                    width:          200
                    visible:        showFirmwareTypeSelection
                    model:          px4Flow ? px4FlowTypeList : firmwareTypeList
                    currentIndex:   controller.selectedFirmwareType

                    onActivated: {
                        controller.selectedFirmwareType = index
                        if (model.get(index).firmwareType == FirmwareUpgradeController.BetaFirmware) {
                            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.DeveloperFirmware) {
                            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 additonal safety precautions. " +
                                    "Follow the mailing list actively when using it."
                        } else {
                            firmwareVersionWarningLabel.visible = false
305
                        }
306 307
                    }
                }
308 309 310 311 312 313 314

                QGCLabel {
                    id:         firmwareVersionWarningLabel
                    width:      parent.width
                    wrapMode:   Text.WordWrap
                    visible:    false
                }
315
            } // Column
316 317 318 319 320 321 322 323 324
        } // QGCViewDialog
    } // Component - pixhawkFirmwareSelectDialog


    Component {
        id: firmwareWarningDialog

        QGCViewMessage {
            message: firmwareWarningMessage
325

326 327 328
            function accept() {
                hideDialog()
                controller.doFirmwareUpgrade();
329
            }
330 331 332 333 334 335
        }
    }

    QGCViewPanel {
        id:             panel
        anchors.fill:   parent
336

337 338 339
        QGCLabel {
            id:             titleLabel
            text:           title
Don Gagne's avatar
Don Gagne committed
340
            font.pixelSize: ScreenTools.mediumFontPixelSize
341
        }
342

343 344 345 346 347 348
        ProgressBar {
            id:                 progressBar
            anchors.topMargin:  ScreenTools.defaultFontPixelHeight
            anchors.top:        titleLabel.bottom
            width:              parent.width
        }
349

350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
        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
365
            }
366 367
        }
    } // QGCViewPabel
368
} // QGCView