7import QGroundControl.Controls
8import QGroundControl.FactControls
12 pageComponent: firmwarePageComponent
13 pageName: qsTr("Firmware")
14 showAdvanced: globals.activeVehicle && globals.activeVehicle.apmFirmware
17 id: firmwarePageComponent
21 height: availableHeight
22 spacing: ScreenTools.defaultFontPixelHeight
24 // Those user visible strings are hard to translate because we can't send the
25 // HTML strings to translation as this can create a security risk. we need to find
26 // a better way to highlight them, or use less highlights.
28 // User visible strings
29 readonly property string title: qsTr("Firmware Setup") // Popup dialog title
30 readonly property string highlightPrefix: "<font color=\"" + qgcPal.warningText + "\">"
31 readonly property string highlightSuffix: "</font>"
32 readonly property string welcomeText: qsTr("%1 can upgrade the firmware on Pixhawk devices and SiK Radios.").arg(QGroundControl.appName)
33 readonly property string welcomeTextSingle: qsTr("Update the autopilot firmware to the latest version")
34 readonly property string plugInText: "<big>" + highlightPrefix + qsTr("Plug in your device") + highlightSuffix + qsTr(" via USB to ") + highlightPrefix + qsTr("start") + highlightSuffix + qsTr(" firmware upgrade.") + "</big>"
35 readonly property string flashFailText: qsTr("If upgrade failed, make sure to connect ") + highlightPrefix + qsTr("directly") + highlightSuffix + qsTr(" to a powered USB port on your computer, not through a USB hub. ") +
36 qsTr("Also make sure you are only powered via USB ") + highlightPrefix + qsTr("not battery") + highlightSuffix + "."
37 readonly property string qgcUnplugText1: qsTr("All %1 connections to vehicles must be ").arg(QGroundControl.appName) + highlightPrefix + qsTr(" disconnected ") + highlightSuffix + qsTr("prior to firmware upgrade.")
38 readonly property string qgcUnplugText2: highlightPrefix + "<big>" + qsTr("Please unplug your Pixhawk and/or Radio from USB.") + "</big>" + highlightSuffix
40 readonly property int _defaultFimwareTypePX4: 12
41 readonly property int _defaultFimwareTypeAPM: 3
43 property var _firmwareUpgradeSettings: QGroundControl.settingsManager.firmwareUpgradeSettings
44 property var _defaultFirmwareFact: _firmwareUpgradeSettings.defaultFirmwareType
45 property bool _defaultFirmwareIsPX4: true
47 property string firmwareWarningMessage
48 property bool firmwareWarningMessageVisible: false
49 property bool initialBoardSearch: true
50 property string firmwareName
52 property bool _singleFirmwareMode: QGroundControl.corePlugin.options.firmwareUpgradeSingleURL.length != 0 ///< true: running in special single firmware download mode
54 function setupPageCompleted() {
55 controller.startBoardSearch()
56 _defaultFirmwareIsPX4 = _defaultFirmwareFact.rawValue === _defaultFimwareTypePX4 // we don't want this to be bound and change as radios are selected
60 id: customFirmwareDialog
61 title: qsTr("Select Firmware File")
62 nameFilters: [qsTr("Firmware Files (*.px4 *.apj *.bin *.ihx)"), qsTr("All Files (*)")]
63 folder: QGroundControl.settingsManager.appSettings.logSavePath
64 onAcceptedForLoad: (file) => {
65 controller.flashFirmwareUrl(file)
70 FirmwareUpgradeController {
72 progressBar: progressBar
73 statusLog: statusTextArea
75 property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
77 onActiveVehicleChanged: {
78 if (!globals.activeVehicle) {
79 statusTextArea.append(plugInText)
84 initialBoardSearch = false
85 if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
86 statusTextArea.append(plugInText)
91 initialBoardSearch = false
92 if (!QGroundControl.multiVehicleManager.activeVehicleAvailable) {
93 statusTextArea.append(plugInText)
98 if (initialBoardSearch) {
99 // Board was found right away, so something is already plugged in before we've started upgrade
100 statusTextArea.append(qgcUnplugText1)
101 statusTextArea.append(qgcUnplugText2)
103 var availableDevices = controller.availableBoardsName()
104 if (availableDevices.length > 1) {
105 statusTextArea.append(highlightPrefix + qsTr("Multiple devices detected! Remove all detected devices to perform the firmware upgrade."))
106 statusTextArea.append(qsTr("Detected [%1]: ").arg(availableDevices.length) + availableDevices.join(", "))
108 if (QGroundControl.multiVehicleManager.activeVehicle) {
109 QGroundControl.multiVehicleManager.activeVehicle.vehicleLinkManager.autoDisconnect = true
112 // We end up here when we detect a board plugged in after we've started upgrade
113 statusTextArea.append(highlightPrefix + qsTr("Found device") + highlightSuffix + ": " + controller.boardType)
117 onShowFirmwareSelectDlg: firmwareSelectDialogFactory.open()
118 onError: statusTextArea.append(flashFailText)
121 QGCPopupDialogFactory {
122 id: firmwareSelectDialogFactory
124 dialogComponent: firmwareSelectDialogComponent
128 id: firmwareSelectDialogComponent
131 id: firmwareSelectDialog
132 title: qsTr("Firmware Setup")
133 buttons: Dialog.Ok | Dialog.Cancel
135 property bool showFirmwareTypeSelection: _advanced.checked
137 function firmwareVersionChanged(model) {
138 firmwareWarningMessageVisible = false
139 // All of this bizarre, setting model to null and index to 1 and then to 0 is to work around
140 // strangeness in the combo box implementation. This sequence of steps correctly changes the combo model
141 // without generating any warnings and correctly updates the combo text with the new selection.
142 firmwareBuildTypeCombo.model = null
143 firmwareBuildTypeCombo.model = model
144 firmwareBuildTypeCombo.currentIndex = 1
145 firmwareBuildTypeCombo.currentIndex = 0
148 function updatePX4VersionDisplay() {
149 var versionString = ""
150 if (_advanced.checked) {
151 switch (controller.selectedFirmwareBuildType) {
152 case FirmwareUpgradeController.StableFirmware:
153 versionString = controller.px4StableVersion
155 case FirmwareUpgradeController.BetaFirmware:
156 versionString = controller.px4BetaVersion
160 versionString = controller.px4StableVersion
162 px4FlightStackRadio.text = qsTr("PX4 Pro ") + versionString
163 //px4FlightStackRadio2.text = qsTr("PX4 Pro ") + versionString
166 Component.onCompleted: {
167 firmwarePage.advanced = false
168 firmwarePage.showAdvanced = false
169 updatePX4VersionDisplay()
178 if (_singleFirmwareMode) {
179 controller.flashSingleFirmwareMode(controller.selectedFirmwareBuildType)
181 var firmwareBuildType = firmwareBuildTypeCombo.model.get(firmwareBuildTypeCombo.currentIndex).firmwareType
182 var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
184 var stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
185 if (apmFlightStack.checked) {
186 if (firmwareBuildType === FirmwareUpgradeController.CustomFirmware) {
187 vehicleType = apmVehicleTypeCombo.currentIndex
189 if (controller.apmFirmwareNames.length === 0) {
190 // Not ready yet, or no firmware available
191 QGroundControl.showMessageDialog(firmwarePage, firmwareSelectDialog.title, qsTr("Either firmware list is still downloading, or no firmware is available for current selection."))
192 firmwareSelectDialog.preventClose = true
195 if (ardupilotFirmwareSelectionCombo.currentIndex == -1) {
196 QGroundControl.showMessageDialog(firmwarePage, firmwareSelectDialog.title, qsTr("You must choose a board type."))
197 firmwareSelectDialog.preventClose = true
201 var firmwareUrl = controller.apmFirmwareUrls[ardupilotFirmwareSelectionCombo.currentIndex]
202 if (firmwareUrl == "") {
203 QGroundControl.showMessageDialog(firmwarePage, firmwareSelectDialog.title, qsTr("No firmware was found for the current selection."))
204 firmwareSelectDialog.preventClose = true
207 controller.flashFirmwareUrl(controller.apmFirmwareUrls[ardupilotFirmwareSelectionCombo.currentIndex])
211 //-- If custom, get file path
212 if (firmwareBuildType === FirmwareUpgradeController.CustomFirmware) {
213 customFirmwareDialog.openForLoad()
215 controller.flash(stack, firmwareBuildType, vehicleType)
221 statusTextArea.append(highlightPrefix + qsTr("Upgrade cancelled") + highlightSuffix)
222 statusTextArea.append("------------------------------------------")
228 id: firmwareBuildTypeList
231 text: qsTr("Standard Version (stable)")
232 firmwareType: FirmwareUpgradeController.StableFirmware
235 text: qsTr("Beta Testing (beta)")
236 firmwareType: FirmwareUpgradeController.BetaFirmware
239 text: qsTr("Developer Build (master)")
240 firmwareType: FirmwareUpgradeController.DeveloperFirmware
243 text: qsTr("Custom firmware file...")
244 firmwareType: FirmwareUpgradeController.CustomFirmware
249 id: singleFirmwareModeTypeList
252 text: qsTr("Standard Version")
253 firmwareType: FirmwareUpgradeController.StableFirmware
256 text: qsTr("Custom firmware file...")
257 firmwareType: FirmwareUpgradeController.CustomFirmware
262 width: Math.max(ScreenTools.defaultFontPixelWidth * 40, firmwareRadiosColumn.width)
263 spacing: globals.defaultTextHeight / 2
266 Layout.fillWidth: true
267 wrapMode: Text.WordWrap
268 text: (_singleFirmwareMode || !QGroundControl.apmFirmwareSupported) ? _singleFirmwareLabel : _pixhawkLabel
270 readonly property string _pixhawkLabel: qsTr("Detected Pixhawk board. You can select from the following flight stacks:")
271 readonly property string _singleFirmwareLabel: qsTr("Press Ok to upgrade your vehicle.")
275 id: firmwareRadiosColumn
278 visible: !_singleFirmwareMode && QGroundControl.apmFirmwareSupported
280 Component.onCompleted: {
281 if(!QGroundControl.apmFirmwareSupported) {
282 _defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
283 firmwareVersionChanged(firmwareBuildTypeList)
288 id: px4FlightStackRadio
289 text: qsTr("PX4 Pro ")
290 font.bold: _defaultFirmwareIsPX4
291 checked: _defaultFirmwareIsPX4
294 _defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
295 firmwareVersionChanged(firmwareBuildTypeList)
301 text: qsTr("ArduPilot")
302 font.bold: !_defaultFirmwareIsPX4
303 checked: !_defaultFirmwareIsPX4
306 _defaultFirmwareFact.rawValue = _defaultFimwareTypeAPM
307 firmwareVersionChanged(firmwareBuildTypeList)
313 Layout.fillWidth: true
314 visible: apmFlightStack.checked
315 fact: _firmwareUpgradeSettings.apmChibiOS
320 id: apmVehicleTypeCombo
321 Layout.fillWidth: true
322 visible: apmFlightStack.checked
323 fact: _firmwareUpgradeSettings.apmVehicleType
328 id: ardupilotFirmwareSelectionCombo
329 Layout.fillWidth: true
330 visible: apmFlightStack.checked && !controller.downloadingFirmwareList && controller.apmFirmwareNames.length !== 0
331 model: controller.apmFirmwareNames
332 onModelChanged: currentIndex = controller.apmFirmwareNamesBestIndex
336 Layout.fillWidth: true
337 wrapMode: Text.WordWrap
338 text: qsTr("Downloading list of available firmwares...")
339 visible: controller.downloadingFirmwareList
343 Layout.fillWidth: true
344 wrapMode: Text.WordWrap
345 text: qsTr("No Firmware Available")
346 visible: !controller.downloadingFirmwareList && (QGroundControl.apmFirmwareSupported && controller.apmFirmwareNames.length === 0)
351 text: qsTr("Advanced settings")
355 firmwareBuildTypeCombo.currentIndex = 0
356 firmwareWarningMessageVisible = false
357 updatePX4VersionDisplay()
362 Layout.fillWidth: true
363 wrapMode: Text.WordWrap
364 visible: showFirmwareTypeSelection
365 text: _singleFirmwareMode ? qsTr("Select the standard version or one from the file system (previously downloaded):") :
366 qsTr("Select which version of the above flight stack you would like to install:")
370 id: firmwareBuildTypeCombo
371 Layout.fillWidth: true
372 visible: showFirmwareTypeSelection
374 model: _singleFirmwareMode ? singleFirmwareModeTypeList : firmwareBuildTypeList
376 onActivated: (index) => {
377 controller.selectedFirmwareBuildType = model.get(index).firmwareType
378 if (model.get(index).firmwareType === FirmwareUpgradeController.BetaFirmware) {
379 firmwareWarningMessageVisible = true
380 firmwareVersionWarningLabel.text = qsTr("WARNING: BETA FIRMWARE. ") +
381 qsTr("This firmware version is ONLY intended for beta testers. ") +
382 qsTr("Although it has received FLIGHT TESTING, it represents actively changed code. ") +
383 qsTr("Do NOT use for normal operation.")
384 } else if (model.get(index).firmwareType === FirmwareUpgradeController.DeveloperFirmware) {
385 firmwareWarningMessageVisible = true
386 firmwareVersionWarningLabel.text = qsTr("WARNING: CONTINUOUS BUILD FIRMWARE. ") +
387 qsTr("This firmware has NOT BEEN FLIGHT TESTED. ") +
388 qsTr("It is only intended for DEVELOPERS. ") +
389 qsTr("Run bench tests without props first. ") +
390 qsTr("Do NOT fly this without additional safety precautions. ") +
391 qsTr("Follow the forums actively when using it.")
393 firmwareWarningMessageVisible = false
395 updatePX4VersionDisplay()
400 id: firmwareVersionWarningLabel
401 Layout.fillWidth: true
402 wrapMode: Text.WordWrap
403 visible: firmwareWarningMessageVisible
407 } // Component - firmwareSelectDialogComponent
411 Layout.preferredWidth: parent.width
412 visible: !flashBootloaderButton.visible
416 id: flashBootloaderButton
417 text: qsTr("Flash ChibiOS Bootloader")
418 visible: firmwarePage.advanced
419 onClicked: globals.activeVehicle.flashBootloader()
424 Layout.preferredWidth: parent.width
425 Layout.fillHeight: true
427 font.pointSize: ScreenTools.defaultFontPointSize
428 textFormat: TextEdit.RichText
429 text: _singleFirmwareMode ? welcomeTextSingle : welcomeText
432 background: Rectangle {
433 color: qgcPal.windowShade