Commit 7eb9fbc6 authored by Gus Grubba's avatar Gus Grubba

Merge branch 'master' of https://github.com/mavlink/qgroundcontrol into qgc4

# Conflicts:
#	qgroundcontrol.qrc
#	src/Microhard/MicrohardSettings.qml
#	src/VehicleSetup/FirmwareUpgrade.qml
parents 745bec25 ef731572
Subproject commit 171c83700c6318af9ffb4a7ee733567b55a14543
Subproject commit 600bbff722a13cfa61fe053de1da07069bab1d10
......@@ -482,6 +482,7 @@ HEADERS += \
src/Settings/AppSettings.h \
src/Settings/AutoConnectSettings.h \
src/Settings/BrandImageSettings.h \
src/Settings/FirmwareUpgradeSettings.h \
src/Settings/FlightMapSettings.h \
src/Settings/FlyViewSettings.h \
src/Settings/OfflineMapsSettings.h \
......@@ -659,6 +660,7 @@ SOURCES += \
src/Settings/AppSettings.cc \
src/Settings/AutoConnectSettings.cc \
src/Settings/BrandImageSettings.cc \
src/Settings/FirmwareUpgradeSettings.cc \
src/Settings/FlightMapSettings.cc \
src/Settings/FlyViewSettings.cc \
src/Settings/OfflineMapsSettings.cc \
......
......@@ -213,8 +213,6 @@
<qresource prefix="/json">
<file alias="APMMavlinkStreamRate.SettingsGroup.json">src/Settings/APMMavlinkStreamRate.SettingsGroup.json</file>
<file alias="BreachReturn.FactMetaData.json">src/MissionManager/BreachReturn.FactMetaData.json</file>
<file alias="OfflineMaps.SettingsGroup.json">src/Settings/OfflineMaps.SettingsGroup.json</file>
<file alias="PlanView.SettingsGroup.json">src/Settings/PlanView.SettingsGroup.json</file>
<file alias="App.SettingsGroup.json">src/Settings/App.SettingsGroup.json</file>
<file alias="AutoConnect.SettingsGroup.json">src/Settings/AutoConnect.SettingsGroup.json</file>
<file alias="BrandImage.SettingsGroup.json">src/Settings/BrandImage.SettingsGroup.json</file>
......@@ -223,6 +221,7 @@
<file alias="CameraSpec.FactMetaData.json">src/MissionManager/CameraSpec.FactMetaData.json</file>
<file alias="CorridorScan.SettingsGroup.json">src/MissionManager/CorridorScan.SettingsGroup.json</file>
<file alias="EditPositionDialog.FactMetaData.json">src/QmlControls/EditPositionDialog.FactMetaData.json</file>
<file alias="FirmwareUpgrade.SettingsGroup.json">src/Settings/FirmwareUpgrade.SettingsGroup.json</file>
<file alias="FlightMap.SettingsGroup.json">src/Settings/FlightMap.SettingsGroup.json</file>
<file alias="FlyView.SettingsGroup.json">src/Settings/FlyView.SettingsGroup.json</file>
<file alias="FWLandingPattern.FactMetaData.json">src/MissionManager/FWLandingPattern.FactMetaData.json</file>
......@@ -233,6 +232,8 @@
<file alias="MavCmdInfoSub.json">src/MissionManager/MavCmdInfoSub.json</file>
<file alias="MavCmdInfoVTOL.json">src/MissionManager/MavCmdInfoVTOL.json</file>
<file alias="MissionSettings.FactMetaData.json">src/MissionManager/MissionSettings.FactMetaData.json</file>
<file alias="OfflineMaps.SettingsGroup.json">src/Settings/OfflineMaps.SettingsGroup.json</file>
<file alias="PlanView.SettingsGroup.json">src/Settings/PlanView.SettingsGroup.json</file>
<file alias="QGCMapCircle.Facts.json">src/MissionManager/QGCMapCircle.Facts.json</file>
<file alias="RallyPoint.FactMetaData.json">src/MissionManager/RallyPoint.FactMetaData.json</file>
<file alias="RTK.SettingsGroup.json">src/Settings/RTK.SettingsGroup.json</file>
......
add_library(AutoPilotPlugins
APM/APMAirframeComponent.cc
APM/APMAirframeComponentAirframes.cc
APM/APMAirframeComponentController.cc
APM/APMAirframeLoader.cc
APM/APMAutoPilotPlugin.cc
APM/APMCameraComponent.cc
APM/APMCompassCal.cc
......
......@@ -107,8 +107,8 @@ QGCCameraManager::_handleHeartbeat(const mavlink_message_t &message)
{
mavlink_heartbeat_t heartbeat;
mavlink_msg_heartbeat_decode(&message, &heartbeat);
//-- If this heartbeat is from a different component within the vehicle
if(_vehicleReadyState && _vehicle->id() == message.sysid && _vehicle->defaultComponentId() != message.compid) {
//-- Only pay attention to "camera" component IDs
if(_vehicleReadyState && _vehicle->id() == message.sysid && message.compid >= MAV_COMP_ID_CAMERA && message.compid <= MAV_COMP_ID_CAMERA6) {
//-- First time hearing from this one?
QString sCompID = QString::number(message.compid);
if(!_cameraInfoRequest.contains(sCompID)) {
......@@ -135,8 +135,7 @@ QGCCameraManager::_handleHeartbeat(const mavlink_message_t &message)
}
} else {
pInfo->tryCount++;
//-- Request camera info. Again. It could be something other than a camera, in which
// case, we won't ever receive it.
//-- Request camera info again.
_requestCameraInfo(message.compid);
}
}
......
......@@ -15,13 +15,12 @@
#include <QSettings>
#define LONG_TIMEOUT 5000
#define SHORT_TIMEOUT 2500
#define LONG_TIMEOUT 5000
static const char *kMICROHARD_GROUP = "Microhard";
static const char *kLOCAL_IP = "LocalIP";
static const char *kREMOTE_IP = "RemoteIP";
static const char *kGROUND_IP = "GroundIP";
static const char *kAIR_IP = "AirIP";
static const char *kNET_MASK = "NetMask";
static const char *kCFG_PASSWORD = "ConfigPassword";
static const char *kENC_KEY = "EncryptionKey";
......@@ -38,8 +37,6 @@ MicrohardManager::MicrohardManager(QGCApplication* app, QGCToolbox* toolbox)
settings.beginGroup(kMICROHARD_GROUP);
_localIPAddr = settings.value(kLOCAL_IP, QString("192.168.168.1")).toString();
_remoteIPAddr = settings.value(kREMOTE_IP, QString("192.168.168.2")).toString();
_groundIPAddr = settings.value(kGROUND_IP, QString("192.168.168.101")).toString();
_airIPAddr = settings.value(kAIR_IP, QString("192.168.168.213")).toString();
_netMask = settings.value(kNET_MASK, QString("255.255.255.0")).toString();
_configPassword = settings.value(kCFG_PASSWORD, QString("admin")).toString();
_encryptionKey = settings.value(kENC_KEY, QString("1234567890")).toString();
......@@ -117,10 +114,10 @@ MicrohardManager::setToolbox(QGCToolbox* toolbox)
//-----------------------------------------------------------------------------
bool
MicrohardManager::setIPSettings(QString localIP_, QString remoteIP_, QString groundIP_, QString airIP_, QString netMask_, QString cfgPassword_, QString encryptionKey_)
MicrohardManager::setIPSettings(QString localIP_, QString remoteIP_, QString netMask_, QString cfgPassword_, QString encryptionKey_)
{
if (_localIPAddr != localIP_ || _remoteIPAddr != remoteIP_ || _netMask != netMask_ ||
_configPassword != cfgPassword_ || _encryptionKey != encryptionKey_ || _groundIPAddr != groundIP_ || _airIPAddr != airIP_)
_configPassword != cfgPassword_ || _encryptionKey != encryptionKey_)
{
if (_mhSettingsLoc && _encryptionKey != encryptionKey_) {
_mhSettingsLoc->setEncryptionKey(encryptionKey_);
......@@ -128,8 +125,6 @@ MicrohardManager::setIPSettings(QString localIP_, QString remoteIP_, QString gro
_localIPAddr = localIP_;
_remoteIPAddr = remoteIP_;
_groundIPAddr = groundIP_;
_airIPAddr = airIP_;
_netMask = netMask_;
_configPassword = cfgPassword_;
_encryptionKey = encryptionKey_;
......@@ -138,8 +133,6 @@ MicrohardManager::setIPSettings(QString localIP_, QString remoteIP_, QString gro
settings.beginGroup(kMICROHARD_GROUP);
settings.setValue(kLOCAL_IP, localIP_);
settings.setValue(kREMOTE_IP, remoteIP_);
settings.setValue(kGROUND_IP, groundIP_);
settings.setValue(kAIR_IP, airIP_);
settings.setValue(kNET_MASK, netMask_);
settings.setValue(kCFG_PASSWORD, cfgPassword_);
settings.setValue(kENC_KEY, encryptionKey_);
......@@ -169,7 +162,7 @@ MicrohardManager::_setEnabled()
connect(_mhSettingsRem, &MicrohardSettings::connected, this, &MicrohardManager::_connectedRem);
connect(_mhSettingsRem, &MicrohardSettings::rssiUpdated, this, &MicrohardManager::_rssiUpdatedRem);
}
_workTimer.start(1000);
_workTimer.start(SHORT_TIMEOUT);
} else {
//-- Stop everything
_close();
......@@ -268,5 +261,5 @@ MicrohardManager::_checkMicrohard()
_mhSettingsRem->getStatus();
}
}
_workTimer.start(_isConnected ? 1000 : LONG_TIMEOUT);
_workTimer.start(_isConnected ? SHORT_TIMEOUT : LONG_TIMEOUT);
}
......@@ -32,13 +32,11 @@ public:
Q_PROPERTY(int downlinkRSSI READ downlinkRSSI NOTIFY linkChanged)
Q_PROPERTY(QString localIPAddr READ localIPAddr NOTIFY localIPAddrChanged)
Q_PROPERTY(QString remoteIPAddr READ remoteIPAddr NOTIFY remoteIPAddrChanged)
Q_PROPERTY(QString groundIPAddr READ groundIPAddr NOTIFY groundIPAddrChanged)
Q_PROPERTY(QString airIPAddr READ airIPAddr NOTIFY airIPAddrChanged)
Q_PROPERTY(QString netMask READ netMask NOTIFY netMaskChanged)
Q_PROPERTY(QString configPassword READ configPassword NOTIFY configPasswordChanged)
Q_PROPERTY(QString encryptionKey READ encryptionKey NOTIFY encryptionKeyChanged)
Q_INVOKABLE bool setIPSettings (QString localIP, QString remoteIP, QString groundIP, QString airIP, QString netMask, QString cfgPassword, QString encyrptionKey);
Q_INVOKABLE bool setIPSettings (QString localIP, QString remoteIP, QString netMask, QString cfgPassword, QString encyrptionKey);
explicit MicrohardManager (QGCApplication* app, QGCToolbox* toolbox);
~MicrohardManager () override;
......@@ -51,8 +49,6 @@ public:
int downlinkRSSI () { return _uplinkRSSI; }
QString localIPAddr () { return _localIPAddr; }
QString remoteIPAddr () { return _remoteIPAddr; }
QString airIPAddr () { return _airIPAddr; }
QString groundIPAddr () { return _groundIPAddr; }
QString netMask () { return _netMask; }
QString configPassword () { return _configPassword; }
QString encryptionKey () { return _encryptionKey; }
......@@ -63,8 +59,6 @@ signals:
void connectedChanged ();
void localIPAddrChanged ();
void remoteIPAddrChanged ();
void airIPAddrChanged ();
void groundIPAddrChanged ();
void netMaskChanged ();
void configPasswordChanged ();
void encryptionKeyChanged ();
......@@ -98,8 +92,6 @@ private:
int _uplinkRSSI = 0;
QString _localIPAddr;
QString _remoteIPAddr;
QString _groundIPAddr;
QString _airIPAddr;
QString _netMask;
QString _configPassword;
QString _encryptionKey;
......
......@@ -41,252 +41,227 @@ Rectangle {
readonly property real _internalWidthRatio: 0.8
QGCFlickable {
clip: true
anchors.fill: parent
contentHeight: settingsColumn.height
contentWidth: settingsColumn.width
Column {
id: settingsColumn
QGCFlickable {
clip: true
anchors.fill: parent
contentHeight: settingsColumn.height
contentWidth: settingsColumn.width
Column {
id: settingsColumn
width: _root.width
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
//-----------------------------------------------------------------
//-- General
Item {
width: _panelWidth
height: generalLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
id: generalLabel
text: qsTr("General")
font.family: ScreenTools.demiboldFontFamily
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
//-----------------------------------------------------------------
//-- General
Item {
width: _panelWidth
height: generalLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
QGCLabel {
id: generalLabel
text: qsTr("General")
font.family: ScreenTools.demiboldFontFamily
}
}
}
Rectangle {
height: generalRow.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Row {
id: generalRow
spacing: ScreenTools.defaultFontPixelWidth * 4
anchors.centerIn: parent
Column {
spacing: ScreenTools.defaultFontPixelWidth
FactCheckBox {
text: qsTr("Enable Microhard")
fact: _microhardEnabledFact
enabled: true
visible: _microhardEnabledFact.visible
Rectangle {
height: generalRow.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Row {
id: generalRow
spacing: ScreenTools.defaultFontPixelWidth * 4
anchors.centerIn: parent
Column {
spacing: ScreenTools.defaultFontPixelWidth
FactCheckBox {
text: qsTr("Enable Microhard")
fact: _microhardEnabledFact
enabled: true
visible: _microhardEnabledFact.visible
}
}
}
}
}
//-----------------------------------------------------------------
//-- Connection Status
Item {
width: _panelWidth
height: statusLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _microhardEnabled
QGCLabel {
id: statusLabel
text: qsTr("Connection Status")
font.family: ScreenTools.demiboldFontFamily
//-----------------------------------------------------------------
//-- Connection Status
Item {
width: _panelWidth
height: statusLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _microhardEnabled
QGCLabel {
id: statusLabel
text: qsTr("Connection Status")
font.family: ScreenTools.demiboldFontFamily
}
}
}
Rectangle {
height: statusCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
visible: _microhardEnabled
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: statusCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: parent.width
anchors.centerIn: parent
GridLayout {
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth * 2
anchors.horizontalCenter: parent.horizontalCenter
columns: 2
QGCLabel {
text: qsTr("Ground Unit:")
Layout.minimumWidth: _labelWidth
}
QGCLabel {
text: QGroundControl.microhardManager.connected ? qsTr("Connected") : qsTr("Not Connected")
color: QGroundControl.microhardManager.connected ? qgcPal.colorGreen : qgcPal.colorRed
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Air Unit:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected ? qsTr("Connected") : qsTr("Not Connected")
color: QGroundControl.microhardManager.linkConnected ? qgcPal.colorGreen : qgcPal.colorRed
}
QGCLabel {
text: qsTr("Uplink RSSI:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected && QGroundControl.microhardManager.uplinkRSSI < 0 ? QGroundControl.microhardManager.uplinkRSSI : ""
}
QGCLabel {
text: qsTr("Downlink RSSI:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected && QGroundControl.microhardManager.downlinkRSSI < 0 ? QGroundControl.microhardManager.downlinkRSSI : ""
Rectangle {
height: statusCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
visible: _microhardEnabled
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: statusCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: parent.width
anchors.centerIn: parent
GridLayout {
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth * 2
anchors.horizontalCenter: parent.horizontalCenter
columns: 2
QGCLabel {
text: qsTr("Ground Unit:")
Layout.minimumWidth: _labelWidth
}
QGCLabel {
text: QGroundControl.microhardManager.connected ? qsTr("Connected") : qsTr("Not Connected")
color: QGroundControl.microhardManager.connected ? qgcPal.colorGreen : qgcPal.colorRed
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Air Unit:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected ? qsTr("Connected") : qsTr("Not Connected")
color: QGroundControl.microhardManager.linkConnected ? qgcPal.colorGreen : qgcPal.colorRed
}
QGCLabel {
text: qsTr("Uplink RSSI:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected && QGroundControl.microhardManager.uplinkRSSI < 0 ? QGroundControl.microhardManager.uplinkRSSI : ""
}
QGCLabel {
text: qsTr("Downlink RSSI:")
}
QGCLabel {
text: QGroundControl.microhardManager.linkConnected && QGroundControl.microhardManager.downlinkRSSI < 0 ? QGroundControl.microhardManager.downlinkRSSI : ""
}
}
}
}
}
//-----------------------------------------------------------------
//-- IP Settings
Item {
width: _panelWidth
height: ipSettingsLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _microhardEnabled
QGCLabel {
id: ipSettingsLabel
text: qsTr("Network Settings")
font.family: ScreenTools.demiboldFontFamily
//-----------------------------------------------------------------
//-- IP Settings
Item {
width: _panelWidth
height: ipSettingsLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: _microhardEnabled
QGCLabel {
id: ipSettingsLabel
text: qsTr("Network Settings")
font.family: ScreenTools.demiboldFontFamily
}
}
}
Rectangle {
height: ipSettingsCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
visible: _microhardEnabled
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: ipSettingsCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: parent.width
anchors.centerIn: parent
GridLayout {
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth * 2
anchors.horizontalCenter: parent.horizontalCenter
columns: 2
QGCLabel {
text: qsTr("Local IP Address:")
Layout.minimumWidth: _labelWidth
}
QGCTextField {
id: localIP
text: QGroundControl.microhardManager.localIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Remote IP Address:")
}
QGCTextField {
id: remoteIP
text: QGroundControl.microhardManager.remoteIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Ground Unit IP Address:")
Layout.minimumWidth: _labelWidth
}
QGCTextField {
id: groundIP
text: QGroundControl.microhardManager.groundIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Air Unit IP Address:")
}
QGCTextField {
id: airIP
text: QGroundControl.microhardManager.airIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Network Mask:")
}
QGCTextField {
id: netMask
text: QGroundControl.microhardManager.netMask
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Configuration password:")
}
QGCTextField {
id: configPassword
text: QGroundControl.microhardManager.configPassword
enabled: true
inputMethodHints: Qt.ImhHiddenText
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Encryption key:")
}
QGCTextField {
id: encryptionKey
text: QGroundControl.microhardManager.encryptionKey
enabled: true
inputMethodHints: Qt.ImhHiddenText
Layout.minimumWidth: _valueWidth
Rectangle {
height: ipSettingsCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
visible: _microhardEnabled
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: ipSettingsCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
width: parent.width
anchors.centerIn: parent
GridLayout {
anchors.margins: ScreenTools.defaultFontPixelHeight
columnSpacing: ScreenTools.defaultFontPixelWidth * 2
anchors.horizontalCenter: parent.horizontalCenter
columns: 2
QGCLabel {
text: qsTr("Local IP Address:")
Layout.minimumWidth: _labelWidth
}
QGCTextField {
id: localIP
text: QGroundControl.microhardManager.localIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Remote IP Address:")
}
QGCTextField {
id: remoteIP
text: QGroundControl.microhardManager.remoteIPAddr
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Network Mask:")
}
QGCTextField {
id: netMask
text: QGroundControl.microhardManager.netMask
enabled: true
inputMethodHints: Qt.ImhFormattedNumbersOnly
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Configuration password:")
}
QGCTextField {
id: configPassword
text: QGroundControl.microhardManager.configPassword
enabled: true
inputMethodHints: Qt.ImhHiddenText
Layout.minimumWidth: _valueWidth
}
QGCLabel {
text: qsTr("Encryption key:")
}
QGCTextField {
id: encryptionKey
text: QGroundControl.microhardManager.encryptionKey
enabled: true
inputMethodHints: Qt.ImhHiddenText
Layout.minimumWidth: _valueWidth
}
}
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
QGCButton {
function validateIPaddress(ipaddress) {
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress))
return true
return false
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
function testEnabled() {
if(localIP.text === QGroundControl.microhardManager.localIPAddr &&
remoteIP.text === QGroundControl.microhardManager.remoteIPAddr &&
groundIP.text === QGroundControl.microhardManager.groundIPAddr &&
airIP.text === QGroundControl.microhardManager.airIPAddr &&
netMask.text === QGroundControl.microhardManager.netMask &&
configPassword.text === QGroundControl.microhardManager.configPassword &&
encryptionKey.text === QGroundControl.microhardManager.encryptionKey)
QGCButton {
function validateIPaddress(ipaddress) {
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress))
return true
return false
if(!validateIPaddress(localIP.text)) return false
if(!validateIPaddress(remoteIP.text)) return false
if(!validateIPaddress(groundIP.text)) return false
if(!validateIPaddress(airIP.text)) return false
if(!validateIPaddress(netMask.text)) return false
return true
}
enabled: testEnabled()
text: qsTr("Apply")
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
QGroundControl.microhardManager.setIPSettings(localIP.text, remoteIP.text, groundIP.text, airIP.text, netMask.text, configPassword.text, encryptionKey.text)
}
}
function testEnabled() {
if(localIP.text === QGroundControl.microhardManager.localIPAddr &&
remoteIP.text === QGroundControl.microhardManager.remoteIPAddr &&
netMask.text === QGroundControl.microhardManager.netMask &&
configPassword.text === QGroundControl.microhardManager.configPassword &&
encryptionKey.text === QGroundControl.microhardManager.encryptionKey)
return false
if(!validateIPaddress(localIP.text)) return false
if(!validateIPaddress(remoteIP.text)) return false
if(!validateIPaddress(netMask.text)) return false
return true
}
enabled: testEnabled()
text: qsTr("Apply")
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
QGroundControl.microhardManager.setIPSettings(localIP.text, remoteIP.text, netMask.text, configPassword.text, encryptionKey.text)
}
}
}
}
}
}
}
}
[
{
"name": "defaultFirmwareType",
"shortDescription": "Default firmware type for flashing",
"type": "uint32",
"defaultValue": 12
},
{
"name": "apmChibiOS",
"type": "uint32",
"enumStrings": "ChibiOS,NuttX",
"enumValues": "0,1",
"defaultValue": 0
},
{
"name": "apmVehicleType",
"type": "uint32",
"enumStrings": "Multi-Rotor,Helicopter,Plane,Rover,Sub",
"enumValues": "0,1,2,3,4",
"defaultValue": 0
}
]
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "FirmwareUpgradeSettings.h"
#include <QQmlEngine>
#include <QtQml>
DECLARE_SETTINGGROUP(FirmwareUpgrade, "FirmwareUpgrade")
{
qmlRegisterUncreatableType<FirmwareUpgradeSettings>("QGroundControl.SettingsManager", 1, 0, "FirmwareUpgradeSettings", "Reference only");
}
DECLARE_SETTINGSFACT(FirmwareUpgradeSettings, defaultFirmwareType)
DECLARE_SETTINGSFACT(FirmwareUpgradeSettings, apmChibiOS)
DECLARE_SETTINGSFACT(FirmwareUpgradeSettings, apmVehicleType)
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "SettingsGroup.h"
#include "QGCMAVLink.h"
class FirmwareUpgradeSettings : public SettingsGroup
{
Q_OBJECT
public:
FirmwareUpgradeSettings(QObject* parent = nullptr);
DEFINE_SETTING_NAME_GROUP()
DEFINE_SETTINGFACT(defaultFirmwareType)
DEFINE_SETTINGFACT(apmChibiOS)
DEFINE_SETTINGFACT(apmVehicleType)
};
......@@ -27,6 +27,7 @@ SettingsManager::SettingsManager(QGCApplication* app, QGCToolbox* toolbox)
, _planViewSettings (nullptr)
, _brandImageSettings (nullptr)
, _offlineMapsSettings (nullptr)
, _firmwareUpgradeSettings (nullptr)
#if !defined(NO_ARDUPILOT_DIALECT)
, _apmMavlinkStreamRateSettings (nullptr)
#endif
......@@ -40,20 +41,21 @@ void SettingsManager::setToolbox(QGCToolbox *toolbox)
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
qmlRegisterUncreatableType<SettingsManager>("QGroundControl.SettingsManager", 1, 0, "SettingsManager", "Reference only");
_unitsSettings = new UnitsSettings (this); // Must be first since AppSettings references it
_appSettings = new AppSettings (this);
_autoConnectSettings = new AutoConnectSettings (this);
_videoSettings = new VideoSettings (this);
_flightMapSettings = new FlightMapSettings (this);
_rtkSettings = new RTKSettings (this);
_flyViewSettings = new FlyViewSettings (this);
_planViewSettings = new PlanViewSettings (this);
_brandImageSettings = new BrandImageSettings (this);
_offlineMapsSettings = new OfflineMapsSettings (this);
_unitsSettings = new UnitsSettings (this); // Must be first since AppSettings references it
_appSettings = new AppSettings (this);
_autoConnectSettings = new AutoConnectSettings (this);
_videoSettings = new VideoSettings (this);
_flightMapSettings = new FlightMapSettings (this);
_rtkSettings = new RTKSettings (this);
_flyViewSettings = new FlyViewSettings (this);
_planViewSettings = new PlanViewSettings (this);
_brandImageSettings = new BrandImageSettings (this);
_offlineMapsSettings = new OfflineMapsSettings (this);
_firmwareUpgradeSettings = new FirmwareUpgradeSettings (this);
#if !defined(NO_ARDUPILOT_DIALECT)
_apmMavlinkStreamRateSettings = new APMMavlinkStreamRateSettings (this);
_apmMavlinkStreamRateSettings = new APMMavlinkStreamRateSettings(this);
#endif
#if defined(QGC_AIRMAP_ENABLED)
_airMapSettings = new AirMapSettings (this);
_airMapSettings = new AirMapSettings (this);
#endif
}
......@@ -25,6 +25,7 @@
#include "BrandImageSettings.h"
#include "OfflineMapsSettings.h"
#include "APMMavlinkStreamRateSettings.h"
#include "FirmwareUpgradeSettings.h"
#if defined(QGC_AIRMAP_ENABLED)
#include "AirMapSettings.h"
#endif
......@@ -50,7 +51,8 @@ public:
Q_PROPERTY(QObject* flyViewSettings READ flyViewSettings CONSTANT)
Q_PROPERTY(QObject* planViewSettings READ planViewSettings CONSTANT)
Q_PROPERTY(QObject* brandImageSettings READ brandImageSettings CONSTANT)
Q_PROPERTY(QObject* offlineMapsSettings READ offlineMapsSettings CONSTANT)
Q_PROPERTY(QObject* offlineMapsSettings READ offlineMapsSettings CONSTANT)
Q_PROPERTY(QObject* firmwareUpgradeSettings READ firmwareUpgradeSettings CONSTANT)
#if !defined(NO_ARDUPILOT_DIALECT)
Q_PROPERTY(QObject* apmMavlinkStreamRateSettings READ apmMavlinkStreamRateSettings CONSTANT)
#endif
......@@ -70,6 +72,7 @@ public:
PlanViewSettings* planViewSettings (void) { return _planViewSettings; }
BrandImageSettings* brandImageSettings (void) { return _brandImageSettings; }
OfflineMapsSettings* offlineMapsSettings (void) { return _offlineMapsSettings; }
FirmwareUpgradeSettings* firmwareUpgradeSettings (void) { return _firmwareUpgradeSettings; }
#if !defined(NO_ARDUPILOT_DIALECT)
APMMavlinkStreamRateSettings* apmMavlinkStreamRateSettings(void) { return _apmMavlinkStreamRateSettings; }
#endif
......@@ -87,6 +90,7 @@ private:
PlanViewSettings* _planViewSettings;
BrandImageSettings* _brandImageSettings;
OfflineMapsSettings* _offlineMapsSettings;
FirmwareUpgradeSettings* _firmwareUpgradeSettings;
#if !defined(NO_ARDUPILOT_DIALECT)
APMMavlinkStreamRateSettings* _apmMavlinkStreamRateSettings;
#endif
......
......@@ -3333,6 +3333,10 @@ void Vehicle::_handleCommandAck(mavlink_message_t& message)
//_startPlanRequest();
}
if (ack.command == MAV_CMD_FLASH_BOOTLOADER && ack.result == MAV_RESULT_ACCEPTED) {
qgcApp()->showMessage(tr("Bootloader flash succeeded"));
}
if (_mavCommandQueue.count() && ack.command == _mavCommandQueue[0].command) {
_mavCommandAckTimer.stop();
showError = _mavCommandQueue[0].showError;
......
......@@ -58,8 +58,9 @@ SetupPage {
readonly property int _defaultFimwareTypePX4: 12
readonly property int _defaultFimwareTypeAPM: 3
property var _defaultFirmwareFact: QGroundControl.settingsManager.appSettings.defaultFirmwareType
property bool _defaultFirmwareIsPX4: true
property var _firmwareUpgradeSettings: QGroundControl.settingsManager.firmwareUpgradeSettings
property var _defaultFirmwareFact: _firmwareUpgradeSettings.defaultFirmwareType
property bool _defaultFirmwareIsPX4: true
property string firmwareWarningMessage
property bool initialBoardSearch: true
......@@ -77,6 +78,18 @@ SetupPage {
controller.startBoardSearch()
_defaultFirmwareIsPX4 = _defaultFirmwareFact.rawValue === _defaultFimwareTypePX4 // we don't want this to be bound and change as radios are selected
}
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.
firmwareBuildTypeCombo.model = null
firmwareBuildTypeCombo.model = model
firmwareBuildTypeCombo.currentIndex = 1
firmwareBuildTypeCombo.currentIndex = 0
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
FirmwareUpgradeController {
id: controller
......@@ -139,7 +152,7 @@ SetupPage {
function updatePX4VersionDisplay() {
var versionString = ""
if (_advanced.checked) {
switch (controller.selectedFirmwareType) {
switch (controller.selectedFirmwareBuildType) {
case FirmwareUpgradeController.StableFirmware:
versionString = controller.px4StableVersion
break
......@@ -150,8 +163,8 @@ SetupPage {
} else {
versionString = controller.px4StableVersion
}
px4FlightStackRadio1.text = qsTr("PX4 Flight Stack ") + versionString
px4FlightStackRadio2.text = qsTr("PX4 Flight Stack ") + versionString
px4FlightStackRadio.text = qsTr("PX4 Pro ") + versionString
//px4FlightStackRadio2.text = qsTr("PX4 Pro ") + versionString
}
Component.onCompleted: {
......@@ -161,12 +174,11 @@ SetupPage {
}
function accept() {
hideDialog()
if (_singleFirmwareMode) {
controller.flashSingleFirmwareMode(controller.selectedFirmwareType)
controller.flashSingleFirmwareMode(controller.selectedFirmwareBuildType)
} else {
var stack
var firmwareType = firmwareVersionCombo.model.get(firmwareVersionCombo.currentIndex).firmwareType
var firmwareBuildType = firmwareBuildTypeCombo.model.get(firmwareBuildTypeCombo.currentIndex).firmwareType
var vehicleType = FirmwareUpgradeController.DefaultVehicleFirmware
if (px4Flow) {
......@@ -175,11 +187,25 @@ SetupPage {
} else {
stack = apmFlightStack.checked ? FirmwareUpgradeController.AutoPilotStackAPM : FirmwareUpgradeController.AutoPilotStackPX4
if (apmFlightStack.checked) {
vehicleType = controller.vehicleTypeFromVersionIndex(vehicleTypeSelectionCombo.currentIndex)
if (firmwareBuildType === FirmwareUpgradeController.CustomFirmware) {
vehicleType = apmVehicleTypeCombo.currentIndex
} else {
if (controller.apmFirmwareNames.length === 0) {
// Not ready yet, or no firmware available
return
}
var firmwareUrl = controller.apmFirmwareUrls[ardupilotFirmwareSelectionCombo.currentIndex]
if (firmwareUrl == "") {
return
}
controller.flashFirmwareUrl(controller.apmFirmwareUrls[ardupilotFirmwareSelectionCombo.currentIndex])
hideDialog()
return
}
}
}
controller.flash(stack, firmwareType, vehicleType)
controller.flash(stack, firmwareBuildType, vehicleType)
hideDialog()
}
}
......@@ -195,7 +221,7 @@ SetupPage {
}
ListModel {
id: firmwareTypeList
id: firmwareBuildTypeList
ListElement {
text: qsTr("Standard Version (stable)")
......@@ -275,65 +301,86 @@ SetupPage {
readonly property string _singleFirmwareLabel: qsTr("Press Ok to upgrade your vehicle.")
}
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
}
QGCLabel { text: qsTr("Flight Stack") }
// The following craziness of three radio buttons to represent two radio buttons is so that the
// order can be changed such that the default firmware button is always on the top
RowLayout {
spacing: _margins
layoutDirection: px4FlightStackRadio.checked ? Qt.LeftToRight : Qt.RightToLeft
// The following craziness of three radio buttons to represent two radio buttons is so that the
// order can be changed such that the default firmware button is always on the top
//-- Visible only if you have an option. If it's the only option, it's already setup.
QGCRadioButton {
id: px4FlightStackRadio1
text: qsTr("PX4 Flight Stack ")
textBold: _defaultFirmwareIsPX4
checked: _defaultFirmwareIsPX4
visible: _defaultFirmwareIsPX4 && !_singleFirmwareMode && !px4Flow && QGroundControl.hasAPMSupport
onClicked: {
_defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
parent.firmwareVersionChanged(firmwareTypeList)
QGCRadioButton {
id: px4FlightStackRadio
exclusiveGroup: firmwareGroup
text: qsTr("PX4 Pro ")
textBold: _defaultFirmwareIsPX4
checked: _defaultFirmwareIsPX4
visible: !_singleFirmwareMode && !px4Flow
onClicked: {
_defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
firmwareVersionChanged(firmwareBuildTypeList)
}
}
}
QGCRadioButton {
id: apmFlightStack
text: qsTr("ArduPilot Flight Stack")
textBold: !_defaultFirmwareIsPX4
checked: !_defaultFirmwareIsPX4
QGCRadioButton {
id: apmFlightStack
exclusiveGroup: firmwareGroup
text: qsTr("ArduPilot")
textBold: !_defaultFirmwareIsPX4
checked: !_defaultFirmwareIsPX4
visible: !_singleFirmwareMode && !px4Flow && QGroundControl.hasAPMSupport
onClicked: {
_defaultFirmwareFact.rawValue = _defaultFimwareTypeAPM
parent.firmwareVersionChanged(firmwareTypeList)
onClicked: {
_defaultFirmwareFact.rawValue = _defaultFimwareTypeAPM
firmwareVersionChanged(firmwareBuildTypeList)
}
}
}
//-- Visible only if you have an option. If it's the only option, it's already setup.
QGCRadioButton {
id: px4FlightStackRadio2
text: qsTr("PX4 Flight Stack ")
visible: !_defaultFirmwareIsPX4 && !_singleFirmwareMode && !px4Flow && QGroundControl.hasAPMSupport
FactComboBox {
anchors.left: parent.left
anchors.right: parent.right
visible: !px4Flow && apmFlightStack.checked
fact: _firmwareUpgradeSettings.apmChibiOS
indexModel: false
}
onClicked: {
_defaultFirmwareFact.rawValue = _defaultFimwareTypePX4
parent.firmwareVersionChanged(firmwareTypeList)
}
FactComboBox {
id: apmVehicleTypeCombo
anchors.left: parent.left
anchors.right: parent.right
visible: !px4Flow && apmFlightStack.checked
fact: _firmwareUpgradeSettings.apmVehicleType
indexModel: false
}
QGCComboBox {
id: vehicleTypeSelectionCombo
id: ardupilotFirmwareSelectionCombo
anchors.left: parent.left
anchors.right: parent.right
visible: !px4Flow && apmFlightStack.checked
model: controller.apmAvailableVersions
visible: !px4Flow && apmFlightStack.checked && !controller.downloadingFirmwareList && controller.apmFirmwareNames.length !== 0
model: controller.apmFirmwareNames
onModelChanged: console.log("model", model)
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("Downloading list of available firmwares...")
visible: controller.downloadingFirmwareList
}
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("No Firmware Available")
visible: !controller.downloadingFirmwareList && controller.apmFirmwareNames.length === 0
}
QGCComboBox {
......@@ -363,7 +410,7 @@ SetupPage {
checked: px4Flow ? true : false
onClicked: {
firmwareVersionCombo.currentIndex = 0
firmwareBuildTypeCombo.currentIndex = 0
firmwareVersionWarningLabel.visible = false
updatePX4VersionDisplay()
}
......@@ -385,15 +432,15 @@ SetupPage {
}
QGCComboBox {
id: firmwareVersionCombo
id: firmwareBuildTypeCombo
anchors.left: parent.left
anchors.right: parent.right
visible: showFirmwareTypeSelection
model: _singleFirmwareMode ? singleFirmwareModeTypeList : (px4Flow ? px4FlowTypeList : firmwareTypeList)
currentIndex: controller.selectedFirmwareType
model: _singleFirmwareMode ? singleFirmwareModeTypeList : (px4Flow ? px4FlowTypeList : firmwareBuildTypeList)
currentIndex: controller.selectedFirmwareBuildType
onActivated: {
controller.selectedFirmwareType = model.get(index).firmwareType
controller.selectedFirmwareBuildType = model.get(index).firmwareType
if (model.get(index).firmwareType === FirmwareUpgradeController.BetaFirmware) {
firmwareVersionWarningLabel.visible = true
firmwareVersionWarningLabel.text = qsTr("WARNING: BETA FIRMWARE. ") +
......
......@@ -7,11 +7,6 @@
*
****************************************************************************/
/// @file
/// @brief PX4 Firmware Upgrade UI
/// @author Don Gagne <don@thegagnes.com>
#include "FirmwareUpgradeController.h"
#include "Bootloader.h"
//-- TODO: #include "QGCQFileDialog.h"
......@@ -19,6 +14,8 @@
#include "QGCFileDownload.h"
#include "QGCOptions.h"
#include "QGCCorePlugin.h"
#include "FirmwareUpgradeSettings.h"
#include "SettingsManager.h"
#include <QStandardPaths>
#include <QRegularExpression>
......@@ -27,31 +24,57 @@
#include <QJsonArray>
#include <QNetworkProxy>
const char* FirmwareUpgradeController::_manifestFirmwareJsonKey = "firmware";
const char* FirmwareUpgradeController::_manifestBoardIdJsonKey = "board_id";
const char* FirmwareUpgradeController::_manifestMavTypeJsonKey = "mav-type";
const char* FirmwareUpgradeController::_manifestFormatJsonKey = "format";
const char* FirmwareUpgradeController::_manifestUrlJsonKey = "url";
const char* FirmwareUpgradeController::_manifestMavFirmwareVersionTypeJsonKey = "mav-firmware-version-type";
const char* FirmwareUpgradeController::_manifestUSBIDJsonKey = "USBID";
const char* FirmwareUpgradeController::_manifestMavFirmwareVersionJsonKey = "mav-firmware-version";
const char* FirmwareUpgradeController::_manifestBootloaderStrJsonKey = "bootloader_str";
const char* FirmwareUpgradeController::_manifestLatestKey = "latest";
const char* FirmwareUpgradeController::_manifestPlatformKey = "platform";
const char* FirmwareUpgradeController::_manifestBrandNameKey = "brand_name";
struct FirmwareToUrlElement_t {
FirmwareUpgradeController::AutoPilotStackType_t stackType;
FirmwareUpgradeController::FirmwareType_t firmwareType;
FirmwareUpgradeController::FirmwareVehicleType_t vehicleType;
QString url;
FirmwareUpgradeController::AutoPilotStackType_t stackType;
FirmwareUpgradeController::FirmwareBuildType_t firmwareType;
FirmwareUpgradeController::FirmwareVehicleType_t vehicleType;
QString url;
};
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId)
{
return static_cast<uint>(( firmwareId.autopilotStackType |
(firmwareId.firmwareType << 8) |
(firmwareId.firmwareVehicleType << 16) ));
(firmwareId.firmwareType << 8) |
(firmwareId.firmwareVehicleType << 16) ));
}
/// @Brief Constructs a new FirmwareUpgradeController Widget. This widget is used within the PX4VehicleConfig set of screens.
FirmwareUpgradeController::FirmwareUpgradeController(void)
: _singleFirmwareURL (qgcApp()->toolbox()->corePlugin()->options()->firmwareUpgradeSingleURL())
, _singleFirmwareMode (!_singleFirmwareURL.isEmpty())
, _downloadingFirmwareList (false)
, _downloadManager (nullptr)
, _downloadNetworkReply (nullptr)
, _statusLog (nullptr)
, _selectedFirmwareType (StableFirmware)
, _selectedFirmwareBuildType (StableFirmware)
, _image (nullptr)
, _apmBoardDescriptionReplaceText ("<APMBoardDescription>")
, _apmChibiOSSetting (qgcApp()->toolbox()->settingsManager()->firmwareUpgradeSettings()->apmChibiOS())
, _apmVehicleTypeSetting (qgcApp()->toolbox()->settingsManager()->firmwareUpgradeSettings()->apmVehicleType())
{
_manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap["OFFICIAL"] = StableFirmware;
_manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap["BETA"] = BetaFirmware;
_manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap["DEV"] = DeveloperFirmware;
_manifestMavTypeToFirmwareVehicleTypeMap["Copter"] = CopterFirmware;
_manifestMavTypeToFirmwareVehicleTypeMap["HELICOPTER"] = HeliFirmware;
_manifestMavTypeToFirmwareVehicleTypeMap["FIXED_WING"] = PlaneFirmware;
_manifestMavTypeToFirmwareVehicleTypeMap["GROUND_ROVER"] = RoverFirmware;
_manifestMavTypeToFirmwareVehicleTypeMap["SUBMARINE"] = SubFirmware;
_threadController = new PX4FirmwareUpgradeThreadController(this);
Q_CHECK_PTR(_threadController);
......@@ -70,8 +93,12 @@ FirmwareUpgradeController::FirmwareUpgradeController(void)
connect(&_eraseTimer, &QTimer::timeout, this, &FirmwareUpgradeController::_eraseProgressTick);
connect(_apmChibiOSSetting, &Fact::rawValueChanged, this, &FirmwareUpgradeController::_buildAPMFirmwareNames);
connect(_apmVehicleTypeSetting, &Fact::rawValueChanged, this, &FirmwareUpgradeController::_buildAPMFirmwareNames);
_initFirmwareHash();
_determinePX4StableVersion();
_downloadArduPilotManifest();
}
FirmwareUpgradeController::~FirmwareUpgradeController()
......@@ -97,7 +124,7 @@ void FirmwareUpgradeController::startBoardSearch(void)
}
void FirmwareUpgradeController::flash(AutoPilotStackType_t stackType,
FirmwareType_t firmwareType,
FirmwareBuildType_t firmwareType,
FirmwareVehicleType_t vehicleType)
{
qCDebug(FirmwareUpgradeLog) << "_flash stackType:firmwareType:vehicleType" << stackType << firmwareType << vehicleType;
......@@ -108,6 +135,18 @@ void FirmwareUpgradeController::flash(AutoPilotStackType_t stackType,
// We haven't found the bootloader yet. Need to wait until then to flash
_startFlashWhenBootloaderFound = true;
_startFlashWhenBootloaderFoundFirmwareIdentity = firmwareId;
_firmwareFilename.clear();
}
}
void FirmwareUpgradeController::flashFirmwareUrl(QString firmwareFlashUrl)
{
_firmwareFilename = firmwareFlashUrl;
if (_bootloaderFound) {
_downloadFirmware();
} else {
// We haven't found the bootloader yet. Need to wait until then to flash
_startFlashWhenBootloaderFound = true;
}
}
......@@ -116,7 +155,7 @@ void FirmwareUpgradeController::flash(const FirmwareIdentifier& firmwareId)
flash(firmwareId.autopilotStackType, firmwareId.firmwareType, firmwareId.firmwareVehicleType);
}
void FirmwareUpgradeController::flashSingleFirmwareMode(FirmwareType_t firmwareType)
void FirmwareUpgradeController::flashSingleFirmwareMode(FirmwareBuildType_t firmwareType)
{
flash(SingleFirmwareMode, firmwareType, DefaultVehicleFirmware);
}
......@@ -129,9 +168,12 @@ void FirmwareUpgradeController::cancel(void)
void FirmwareUpgradeController::_foundBoard(bool firstAttempt, const QSerialPortInfo& info, int boardType, QString boardName)
{
_foundBoardInfo = info;
_foundBoardType = static_cast<QGCSerialPortInfo::BoardType_t>(boardType);
_foundBoardTypeName = boardName;
_foundBoardInfo = info;
_foundBoardType = static_cast<QGCSerialPortInfo::BoardType_t>(boardType);
_foundBoardTypeName = boardName;
qDebug() << info.manufacturer() << info.description();
_startFlashWhenBootloaderFound = false;
if (_foundBoardType == QGCSerialPortInfo::BoardTypeSiKRadio) {
......@@ -178,7 +220,9 @@ void FirmwareUpgradeController::_foundBootloader(int bootloaderVersion, int boar
flash(_startFlashWhenBootloaderFoundFirmwareIdentity);
}
_loadAPMVersions(_bootloaderBoardID);
if (_rgManifestFirmwareInfo.count()) {
_buildAPMFirmwareNames();
}
}
......@@ -197,19 +241,6 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/stable/aerocore_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/beta/aerocore_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://gumstix-aerocore.s3.amazonaws.com/PX4/master/aerocore_default.px4"},
#if !defined(NO_ARDUPILOT_DIALECT)
{ AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/stable/PX4-heli/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/stable/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/stable/PX4/APMrover2-v2.px4"},
{ AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v2.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, CopterFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Copter/latest/PX4-heli/ArduCopter-v2.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Plane/latest/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://gumstix-aerocore.s3.amazonaws.com/Rover/latest/PX4/APMrover2-v2.px4"}
#endif
};
//////////////////////////////////// AUAVX2_1 firmwares //////////////////////////////////////////////////
......@@ -217,23 +248,6 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/stable/auav-x21_default.px4"},
{ AutoPilotStackPX4, BetaFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/beta/auav-x21_default.px4"},
{ AutoPilotStackPX4, DeveloperFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/Firmware/master/auav-x21_default.px4"},
#if !defined(NO_ARDUPILOT_DIALECT)
{ AutoPilotStackAPM, StableFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, StableFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/stable/PX4-heli/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, StableFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/stable/PX4/ArduPlane-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/stable/PX4/APMrover2-v2.px4"},
{ AutoPilotStackAPM, StableFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/stable/PX4/ArduSub-v2.px4"},
{ AutoPilotStackAPM, BetaFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, BetaFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/beta/PX4-heli/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, BetaFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/beta/PX4/ArduPlane-v3.px4"},
{ AutoPilotStackAPM, BetaFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/beta/PX4/APMrover2-v3.px4"},
{ AutoPilotStackAPM, BetaFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/beta/PX4/ArduSub-v3.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, CopterFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, HeliFirmware, "http://firmware.ardupilot.org/Copter/latest/PX4-heli/ArduCopter-v3.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, PlaneFirmware, "http://firmware.ardupilot.org/Plane/latest/PX4/ArduPlane-v3.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, RoverFirmware, "http://firmware.ardupilot.org/Rover/latest/PX4/APMrover2-v3.px4"},
{ AutoPilotStackAPM, DeveloperFirmware, SubFirmware, "http://firmware.ardupilot.org/Sub/latest/PX4/ArduSub-v3.px4"}
#endif
};
//////////////////////////////////// MindPXFMUV2 firmwares //////////////////////////////////////////////////
FirmwareToUrlElement_t rgMindPXFMUV2FirmwareArray[] = {
......@@ -288,7 +302,7 @@ void FirmwareUpgradeController::_initFirmwareHash()
{ ThreeDRRadio, StableFirmware, DefaultVehicleFirmware, "http://px4-travis.s3.amazonaws.com/SiK/stable/radio~hm_trp.ihx"}
};
// We build the maps for PX4 and ArduPilot firmwares dynamically using the data below
// We build the maps for PX4 firmwares dynamically using the data below
#if 0
Example URLs for PX4 and ArduPilot
......@@ -298,77 +312,14 @@ void FirmwareUpgradeController::_initFirmwareHash()
#endif
QString px4Url ("http://px4-travis.s3.amazonaws.com/Firmware/%1/px4fmu-%2_default.px4");
QString apmUrl ("http://firmware.ardupilot.org/%1/%2/%3/%4-v%5.px4");
QString apmChibiOSUrl ("http://firmware.ardupilot.org/%1/%2/fmuv%3%4/%5.apj");
QMap<FirmwareType_t, QString> px4MapFirmwareTypeToDir;
QMap<FirmwareBuildType_t, QString> px4MapFirmwareTypeToDir;
px4MapFirmwareTypeToDir[StableFirmware] = QStringLiteral("stable");
px4MapFirmwareTypeToDir[BetaFirmware] = QStringLiteral("beta");
px4MapFirmwareTypeToDir[DeveloperFirmware] = QStringLiteral("master");
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmMapVehicleTypeToDir;
apmMapVehicleTypeToDir[CopterFirmware] = QStringLiteral("Copter");
apmMapVehicleTypeToDir[HeliFirmware] = QStringLiteral("Copter");
apmMapVehicleTypeToDir[PlaneFirmware] = QStringLiteral("Plane");
apmMapVehicleTypeToDir[RoverFirmware] = QStringLiteral("Rover");
apmMapVehicleTypeToDir[SubFirmware] = QStringLiteral("Sub");
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmChibiOSMapVehicleTypeToDir;
apmChibiOSMapVehicleTypeToDir[CopterChibiOSFirmware] = QStringLiteral("Copter");
apmChibiOSMapVehicleTypeToDir[HeliChibiOSFirmware] = QStringLiteral("Copter");
apmChibiOSMapVehicleTypeToDir[PlaneChibiOSFirmware] = QStringLiteral("Plane");
apmChibiOSMapVehicleTypeToDir[RoverChibiOSFirmware] = QStringLiteral("Rover");
apmChibiOSMapVehicleTypeToDir[SubChibiOSFirmware] = QStringLiteral("Sub");
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareType_t, QString> apmMapFirmwareTypeToDir;
apmMapFirmwareTypeToDir[StableFirmware] = QStringLiteral("stable");
apmMapFirmwareTypeToDir[BetaFirmware] = QStringLiteral("beta");
apmMapFirmwareTypeToDir[DeveloperFirmware] = QStringLiteral("latest");
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmMapVehicleTypeToPX4Dir;
apmMapVehicleTypeToPX4Dir[CopterFirmware] = QStringLiteral("PX4");
apmMapVehicleTypeToPX4Dir[HeliFirmware] = QStringLiteral("PX4-heli");
apmMapVehicleTypeToPX4Dir[PlaneFirmware] = QStringLiteral("PX4");
apmMapVehicleTypeToPX4Dir[RoverFirmware] = QStringLiteral("PX4");
apmMapVehicleTypeToPX4Dir[SubFirmware] = QStringLiteral("PX4");
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmMapVehicleTypeToFilename;
apmMapVehicleTypeToFilename[CopterFirmware] = QStringLiteral("ArduCopter");
apmMapVehicleTypeToFilename[HeliFirmware] = QStringLiteral("ArduCopter");
apmMapVehicleTypeToFilename[PlaneFirmware] = QStringLiteral("ArduPlane");
apmMapVehicleTypeToFilename[RoverFirmware] = QStringLiteral("APMrover2");
apmMapVehicleTypeToFilename[SubFirmware] = QStringLiteral("ArduSub");
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmChibiOSMapVehicleTypeToFmuDir;
apmChibiOSMapVehicleTypeToFmuDir[CopterChibiOSFirmware] = QString();
apmChibiOSMapVehicleTypeToFmuDir[HeliChibiOSFirmware] = QStringLiteral("-heli");
apmChibiOSMapVehicleTypeToFmuDir[PlaneChibiOSFirmware] = QString();
apmChibiOSMapVehicleTypeToFmuDir[RoverChibiOSFirmware] = QString();
apmChibiOSMapVehicleTypeToFmuDir[SubChibiOSFirmware] = QString();
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
QMap<FirmwareVehicleType_t, QString> apmChibiOSMapVehicleTypeToFilename;
apmChibiOSMapVehicleTypeToFilename[CopterChibiOSFirmware] = QStringLiteral("arducopter");
apmChibiOSMapVehicleTypeToFilename[HeliChibiOSFirmware] = QStringLiteral("arducopter-heli");
apmChibiOSMapVehicleTypeToFilename[PlaneChibiOSFirmware] = QStringLiteral("arduplane");
apmChibiOSMapVehicleTypeToFilename[RoverChibiOSFirmware] = QStringLiteral("ardurover");
apmChibiOSMapVehicleTypeToFilename[SubChibiOSFirmware] = QStringLiteral("ardusub");
#endif
// PX4 Firmwares
for (const FirmwareType_t& firmwareType: px4MapFirmwareTypeToDir.keys()) {
for (const FirmwareBuildType_t& firmwareType: px4MapFirmwareTypeToDir.keys()) {
QString dir = px4MapFirmwareTypeToDir[firmwareType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v5"));
_rgFMUV4PROFirmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v4pro"));
......@@ -377,49 +328,6 @@ void FirmwareUpgradeController::_initFirmwareHash()
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v2"));
}
#if !defined(NO_ARDUPILOT_DIALECT)
// ArduPilot non-ChibiOS Firmwares for direct board id to fmu mappings
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmMapVehicleTypeToDir.keys()) {
QString vehicleTypeDir = apmMapVehicleTypeToDir[vehicleType];
QString px4Dir = apmMapVehicleTypeToPX4Dir[vehicleType];
QString filename = apmMapVehicleTypeToFilename[vehicleType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("5"));
_rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("4"));
_rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("3"));
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("2"));
}
}
// ArduPilot ChibiOS Firmwares for direct board id to fmu mappings. Used when bootloader is not new ArduPilot bootloader.
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) {
QString vehicleTypeDir = apmChibiOSMapVehicleTypeToDir[vehicleType];
QString fmuDir = apmChibiOSMapVehicleTypeToFmuDir[vehicleType];
QString filename = apmChibiOSMapVehicleTypeToFilename[vehicleType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("5").arg(fmuDir).arg(filename));
_rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("4").arg(fmuDir).arg(filename));
_rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("3").arg(fmuDir).arg(filename));
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("2").arg(fmuDir).arg(filename));
}
}
// ArduPilot ChibiOS Firmwares when board id is an unknown type but follows ArduPilot port info naming conventions.
// This is only used if the board is using the new ArduPilot bootloader port naming scheme.
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) {
QString namedURL("http://firmware.ardupilot.org/%1/%2/%3%4/%5.apj");
QString vehicleTypeDir = apmChibiOSMapVehicleTypeToDir[vehicleType];
QString fmuDir = apmChibiOSMapVehicleTypeToFmuDir[vehicleType];
QString filename = apmChibiOSMapVehicleTypeToFilename[vehicleType];
_rgAPMChibiosReplaceNamedBoardFirmware.insert(FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), namedURL.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(_apmBoardDescriptionReplaceText).arg(fmuDir).arg(filename));
}
}
#endif
int size = sizeof(rgAeroCoreFirmwareArray)/sizeof(rgAeroCoreFirmwareArray[0]);
for (int i = 0; i < size; i++) {
const FirmwareToUrlElement_t& element = rgAeroCoreFirmwareArray[i];
......@@ -550,24 +458,6 @@ QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* FirmwareUpgradeCo
break;
}
// Check for ArduPilot ChibiOS bootloader
QStringList rgManufacturers = { QStringLiteral("ArduPilot"), QStringLiteral("Hex/ProfiCNC"), QStringLiteral("Holybro") };
QString apmDescriptionSuffix("-BL");
if (rgManufacturers.contains(_foundBoardInfo.manufacturer()) && _foundBoardInfo.description().endsWith(apmDescriptionSuffix)) {
// Board ios using a ChibiOS bootloader. Prefer naming scheme from that over board ids for ArduPilot entries.
// First remove the ChibiOS by board id entries from the list
for (const FirmwareIdentifier& firmwareId: _rgAPMChibiosReplaceNamedBoardFirmware.keys()) {
_rgFirmwareDynamic.remove(firmwareId);
}
// Now add the ChibiOS by board description entries to the list
for (const FirmwareIdentifier& firmwareId: _rgAPMChibiosReplaceNamedBoardFirmware.keys()) {
QString namedUrl = _rgAPMChibiosReplaceNamedBoardFirmware[firmwareId];
_rgFirmwareDynamic.insert(firmwareId, namedUrl.replace(_apmBoardDescriptionReplaceText, _foundBoardInfo.description().left(_foundBoardInfo.description().length() - apmDescriptionSuffix.length())));
}
}
return &_rgFirmwareDynamic;
}
......@@ -659,7 +549,7 @@ void FirmwareUpgradeController::_firmwareDownloadError(QString errorMsg)
}
/// @brief returns firmware type as a string
QString FirmwareUpgradeController::firmwareTypeAsString(FirmwareType_t type) const
QString FirmwareUpgradeController::firmwareTypeAsString(FirmwareBuildType_t type) const
{
switch (type) {
case StableFirmware:
......@@ -757,119 +647,62 @@ void FirmwareUpgradeController::_eraseComplete(void)
_eraseTimer.stop();
}
void FirmwareUpgradeController::_loadAPMVersions(uint32_t bootloaderBoardID)
void FirmwareUpgradeController::setSelectedFirmwareBuildType(FirmwareBuildType_t firmwareType)
{
_apmVersionMap.clear();
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardId(static_cast<int>(bootloaderBoardID));
for (FirmwareIdentifier firmwareId: prgFirmware->keys()) {
if (firmwareId.autopilotStackType == AutoPilotStackAPM) {
QString versionFile = QFileInfo(prgFirmware->value(firmwareId)).path() + "/git-version.txt";
qCDebug(FirmwareUpgradeLog) << "Downloading" << versionFile;
QGCFileDownload* downloader = new QGCFileDownload(this);
connect(downloader, &QGCFileDownload::downloadFinished, this, &FirmwareUpgradeController::_apmVersionDownloadFinished);
downloader->download(versionFile);
}
}
_selectedFirmwareBuildType = firmwareType;
emit selectedFirmwareBuildTypeChanged(_selectedFirmwareBuildType);
_buildAPMFirmwareNames();
}
void FirmwareUpgradeController::_apmVersionDownloadFinished(QString remoteFile, QString localFile)
void FirmwareUpgradeController::_buildAPMFirmwareNames(void)
{
qCDebug(FirmwareUpgradeLog) << "Download complete" << remoteFile << localFile;
// Now read the version file and pull out the version string
qCDebug(FirmwareUpgradeLog) << "_buildAPMFirmwareNames";
QFile versionFile(localFile);
versionFile.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream stream(&versionFile);
QString versionContents = stream.readAll();
bool chibios = _apmChibiOSSetting->rawValue().toInt() == 0;
FirmwareVehicleType_t vehicleType = static_cast<FirmwareVehicleType_t>(_apmVehicleTypeSetting->rawValue().toInt());
QString version;
QRegularExpression re("APMVERSION: (.*)$");
QRegularExpressionMatch match = re.match(versionContents);
if (match.hasMatch()) {
version = match.captured(1);
}
if (version.isEmpty()) {
qWarning() << "Unable to parse version info from file" << remoteFile;
sender()->deleteLater();
return;
}
_apmFirmwareNames.clear();
_apmFirmwareUrls.clear();
// In order to determine the firmware and vehicle type for this file we find the matching entry in the firmware list
QString apmDescriptionSuffix("-BL");
bool bootloaderMatch = _foundBoardInfo.description().endsWith(apmDescriptionSuffix);
for (const ManifestFirmwareInfo_t& firmwareInfo: _rgManifestFirmwareInfo) {
bool match = false;
if (firmwareInfo.firmwareBuildType == _selectedFirmwareBuildType && firmwareInfo.chibios == chibios && firmwareInfo.vehicleType == vehicleType) {
if (bootloaderMatch) {
if (firmwareInfo.rgBootloaderPortString.contains(_foundBoardInfo.description())) {
qCDebug(FirmwareUpgradeLog) << "Bootloader match:" << firmwareInfo.friendlyName << _foundBoardInfo.description() << firmwareInfo.rgBootloaderPortString << firmwareInfo.url << firmwareInfo.vehicleType;
match = true;
}
} else {
if (firmwareInfo.rgVID.contains(_foundBoardInfo.vendorIdentifier()) && firmwareInfo.rgPID.contains(_foundBoardInfo.productIdentifier())) {
qCDebug(FirmwareUpgradeLog) << "Fallback match:" << firmwareInfo.friendlyName << _foundBoardInfo.vendorIdentifier() << _foundBoardInfo.productIdentifier() << _bootloaderBoardID << firmwareInfo.url << firmwareInfo.vehicleType;
match = true;
}
}
}
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardId(static_cast<int>(_bootloaderBoardID));
// Do a final filter on fmuv2/fmuv3
if (match && _bootloaderBoardID == Bootloader::boardIDPX4FMUV3) {
match = !firmwareInfo.fmuv2;
}
QString remotePath = QFileInfo(remoteFile).path();
for (FirmwareIdentifier firmwareId: prgFirmware->keys()) {
if (remotePath == QFileInfo((*prgFirmware)[firmwareId]).path()) {
qCDebug(FirmwareUpgradeLog) << "Adding version to map, version:firwmareType:vehicleType" << version << firmwareId.firmwareType << firmwareId.firmwareVehicleType;
_apmVersionMap[firmwareId.firmwareType][firmwareId.firmwareVehicleType] = version;
if (match) {
_apmFirmwareNames.append(firmwareInfo.friendlyName);
_apmFirmwareUrls.append(firmwareInfo.url);
}
}
emit apmAvailableVersionsChanged();
sender()->deleteLater();
}
void FirmwareUpgradeController::setSelectedFirmwareType(FirmwareType_t firmwareType)
{
_selectedFirmwareType = firmwareType;
emit selectedFirmwareTypeChanged(_selectedFirmwareType);
emit apmAvailableVersionsChanged();
}
QStringList FirmwareUpgradeController::apmAvailableVersions(void)
{
QStringList list;
QList<FirmwareVehicleType_t> vehicleTypes;
// This allows us to force the order of the combo box display
vehicleTypes << CopterChibiOSFirmware << HeliChibiOSFirmware << PlaneChibiOSFirmware << RoverChibiOSFirmware << SubChibiOSFirmware << CopterFirmware << HeliFirmware << PlaneFirmware << RoverFirmware << SubFirmware;
_apmVehicleTypeFromCurrentVersionList.clear();
for (FirmwareVehicleType_t vehicleType: vehicleTypes) {
if (_apmVersionMap[_selectedFirmwareType].contains(vehicleType)) {
QString version;
switch (vehicleType) {
case CopterFirmware:
version = tr("NuttX - MultiRotor:");
break;
case HeliFirmware:
version = tr("NuttX - Heli:");
break;
case CopterChibiOSFirmware:
version = tr("ChibiOS- MultiRotor:");
break;
case HeliChibiOSFirmware:
version = tr("ChibiOS - Heli:");
break;
case PlaneChibiOSFirmware:
case RoverChibiOSFirmware:
case SubChibiOSFirmware:
version = tr("ChibiOS - ");
break;
default:
version = tr("NuttX - ");
break;
}
version += _apmVersionMap[_selectedFirmwareType][vehicleType];
_apmVehicleTypeFromCurrentVersionList.append(vehicleType);
list << version;
}
if (_apmFirmwareNames.count() > 1) {
_apmFirmwareNames.prepend(tr("Choose board type"));
_apmFirmwareUrls.prepend(QString());
}
return list;
emit apmFirmwareNamesChanged();
}
FirmwareUpgradeController::FirmwareVehicleType_t FirmwareUpgradeController::vehicleTypeFromVersionIndex(int index)
FirmwareUpgradeController::FirmwareVehicleType_t FirmwareUpgradeController::vehicleTypeFromFirmwareSelectionIndex(int index)
{
if (index < 0 || index >= _apmVehicleTypeFromCurrentVersionList.count()) {
qWarning() << "Invalid index, index:count" << index << _apmVehicleTypeFromCurrentVersionList.count();
......@@ -944,3 +777,147 @@ void FirmwareUpgradeController::_px4ReleasesGithubDownloadError(QString errorMsg
{
qCWarning(FirmwareUpgradeLog) << "PX4 releases github download failed" << errorMsg;
}
void FirmwareUpgradeController::_downloadArduPilotManifest(void)
{
_downloadingFirmwareList = true;
emit downloadingFirmwareListChanged(true);
QGCFileDownload* downloader = new QGCFileDownload(this);
connect(downloader, &QGCFileDownload::downloadFinished, this, &FirmwareUpgradeController::_ardupilotManifestDownloadFinished);
connect(downloader, &QGCFileDownload::error, this, &FirmwareUpgradeController::_ardupilotManifestDownloadError);
#if 0
downloader->download(QStringLiteral("http://firmware.ardupilot.org/manifest.json.gz"));
#else
downloader->download(QStringLiteral("http://firmware.ardupilot.org/manifest.json"));
#endif
}
void FirmwareUpgradeController::_ardupilotManifestDownloadFinished(QString remoteFile, QString localFile)
{
Q_UNUSED(remoteFile);
// Delete the QGCFileDownload object
sender()->deleteLater();
qDebug() << "_ardupilotManifestDownloadFinished" << remoteFile << localFile;
#if 0
QFile gzipFile(localFile);
if (!gzipFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCWarning(FirmwareUpgradeLog) << "Unable to open ArduPilot firmware manifest file" << localFile << gzipFile.errorString();
QFile::remove(localFile);
return;
}
// Store decompressed size as first four bytes. This is required by qUncompress routine.
QByteArray raw;
int decompressedSize = 3073444;
raw.append((unsigned char)((decompressedSize >> 24) & 0xFF));
raw.append((unsigned char)((decompressedSize >> 16) & 0xFF));
raw.append((unsigned char)((decompressedSize >> 8) & 0xFF));
raw.append((unsigned char)((decompressedSize >> 0) & 0xFF));
raw.append(gzipFile.readAll());
QByteArray bytes = qUncompress(raw);
#else
QFile jsonFile(localFile);
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qCWarning(FirmwareUpgradeLog) << "Unable to open ArduPilot firmware manifest file" << localFile << jsonFile.errorString();
QFile::remove(localFile);
return;
}
QByteArray bytes = jsonFile.readAll();
jsonFile.close();
#endif
QFile::remove(localFile);
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qCWarning(FirmwareUpgradeLog) << "Unable to open ArduPilot manifest json document" << localFile << jsonParseError.errorString();
}
QJsonObject json = doc.object();
QJsonArray rgFirmware = json[_manifestFirmwareJsonKey].toArray();
for (int i=0; i<rgFirmware.count(); i++) {
const QJsonObject& firmwareJson = rgFirmware[i].toObject();
FirmwareVehicleType_t firmwareVehicleType = _manifestMavTypeToFirmwareVehicleType(firmwareJson[_manifestMavTypeJsonKey].toString());
FirmwareBuildType_t firmwareBuildType = _manifestMavFirmwareVersionTypeToFirmwareBuildType(firmwareJson[_manifestMavFirmwareVersionTypeJsonKey].toString());
QString format = firmwareJson[_manifestFormatJsonKey].toString();
QString platform = firmwareJson[_manifestPlatformKey].toString();
if (firmwareVehicleType != DefaultVehicleFirmware && firmwareBuildType != CustomFirmware && (format == QStringLiteral("apj") || format == QStringLiteral("px4"))) {
if (platform.contains("-heli") && firmwareVehicleType != HeliFirmware) {
continue;
}
_rgManifestFirmwareInfo.append(ManifestFirmwareInfo_t());
ManifestFirmwareInfo_t& firmwareInfo = _rgManifestFirmwareInfo.last();
firmwareInfo.boardId = static_cast<uint32_t>(firmwareJson[_manifestBoardIdJsonKey].toInt());
firmwareInfo.firmwareBuildType = firmwareBuildType;
firmwareInfo.vehicleType = firmwareVehicleType;
firmwareInfo.url = firmwareJson[_manifestUrlJsonKey].toString();
firmwareInfo.version = firmwareJson[_manifestMavFirmwareVersionJsonKey].toString();
firmwareInfo.chibios = format == QStringLiteral("apj");
firmwareInfo.fmuv2 = platform.contains(QStringLiteral("fmuv2"));
QJsonArray bootloaderArray = firmwareJson[_manifestBootloaderStrJsonKey].toArray();
for (int j=0; j<bootloaderArray.count(); j++) {
firmwareInfo.rgBootloaderPortString.append(bootloaderArray[j].toString());
}
QJsonArray usbidArray = firmwareJson[_manifestUSBIDJsonKey].toArray();
for (int j=0; j<usbidArray.count(); j++) {
QStringList vidpid = usbidArray[j].toString().split('/');
QString vid = vidpid[0];
QString pid = vidpid[1];
bool ok;
firmwareInfo.rgVID.append(vid.right(vid.count() - 2).toInt(&ok, 16));
firmwareInfo.rgPID.append(pid.right(pid.count() - 2).toInt(&ok, 16));
}
QString brandName = firmwareJson[_manifestBrandNameKey].toString();
firmwareInfo.friendlyName = QStringLiteral("%1 - %2").arg(brandName.isEmpty() ? platform : brandName).arg(firmwareInfo.version);
}
}
if (_bootloaderFound) {
_buildAPMFirmwareNames();
}
_downloadingFirmwareList = false;
emit downloadingFirmwareListChanged(false);
}
void FirmwareUpgradeController::_ardupilotManifestDownloadError(QString errorMsg)
{
qCWarning(FirmwareUpgradeLog) << "ArduPilot Manifest download failed" << errorMsg;
}
FirmwareUpgradeController::FirmwareBuildType_t FirmwareUpgradeController::_manifestMavFirmwareVersionTypeToFirmwareBuildType(const QString& manifestMavFirmwareVersionType)
{
if (_manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap.contains(manifestMavFirmwareVersionType)) {
return _manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap[manifestMavFirmwareVersionType];
} else {
return CustomFirmware;
}
}
FirmwareUpgradeController::FirmwareVehicleType_t FirmwareUpgradeController::_manifestMavTypeToFirmwareVehicleType(const QString& manifestMavType)
{
if (_manifestMavTypeToFirmwareVehicleTypeMap.contains(manifestMavType)) {
return _manifestMavTypeToFirmwareVehicleTypeMap[manifestMavType];
} else {
return DefaultVehicleFirmware;
}
}
......@@ -7,16 +7,12 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef FirmwareUpgradeController_H
#define FirmwareUpgradeController_H
#pragma once
#include "PX4FirmwareUpgradeThread.h"
#include "LinkManager.h"
#include "FirmwareImage.h"
#include "Fact.h"
#include <QObject>
#include <QUrl>
......@@ -38,7 +34,7 @@ class FirmwareUpgradeController : public QObject
public:
typedef enum {
AutoPilotStackPX4,
AutoPilotStackPX4 = 0,
AutoPilotStackAPM,
PX4FlowPX4,
PX4FlowAPM,
......@@ -47,35 +43,30 @@ public:
} AutoPilotStackType_t;
typedef enum {
StableFirmware,
StableFirmware = 0,
BetaFirmware,
DeveloperFirmware,
CustomFirmware
} FirmwareType_t;
} FirmwareBuildType_t;
typedef enum {
CopterFirmware,
CopterFirmware = 0,
HeliFirmware,
PlaneFirmware,
RoverFirmware,
SubFirmware,
CopterChibiOSFirmware,
HeliChibiOSFirmware,
PlaneChibiOSFirmware,
RoverChibiOSFirmware,
SubChibiOSFirmware,
DefaultVehicleFirmware
} FirmwareVehicleType_t;
Q_ENUM(AutoPilotStackType_t)
Q_ENUM(FirmwareType_t)
Q_ENUM(FirmwareBuildType_t)
Q_ENUM(FirmwareVehicleType_t)
class FirmwareIdentifier
{
public:
FirmwareIdentifier(AutoPilotStackType_t stack = AutoPilotStackPX4,
FirmwareType_t firmware = StableFirmware,
FirmwareBuildType_t firmware = StableFirmware,
FirmwareVehicleType_t vehicle = DefaultVehicleFirmware)
: autopilotStackType(stack), firmwareType(firmware), firmwareVehicleType(vehicle) {}
......@@ -88,22 +79,24 @@ public:
// members
AutoPilotStackType_t autopilotStackType;
FirmwareType_t firmwareType;
FirmwareBuildType_t firmwareType;
FirmwareVehicleType_t firmwareVehicleType;
};
FirmwareUpgradeController(void);
~FirmwareUpgradeController();
Q_PROPERTY(QString boardPort READ boardPort NOTIFY boardFound)
Q_PROPERTY(QString boardDescription READ boardDescription NOTIFY boardFound)
Q_PROPERTY(QString boardType MEMBER _foundBoardTypeName NOTIFY boardFound)
Q_PROPERTY(bool pixhawkBoard READ pixhawkBoard NOTIFY boardFound)
Q_PROPERTY(bool px4FlowBoard READ px4FlowBoard NOTIFY boardFound)
Q_PROPERTY(FirmwareType_t selectedFirmwareType READ selectedFirmwareType WRITE setSelectedFirmwareType NOTIFY selectedFirmwareTypeChanged)
Q_PROPERTY(QStringList apmAvailableVersions READ apmAvailableVersions NOTIFY apmAvailableVersionsChanged)
Q_PROPERTY(QString px4StableVersion READ px4StableVersion NOTIFY px4StableVersionChanged)
Q_PROPERTY(QString px4BetaVersion READ px4BetaVersion NOTIFY px4BetaVersionChanged)
Q_PROPERTY(bool downloadingFirmwareList MEMBER _downloadingFirmwareList NOTIFY downloadingFirmwareListChanged)
Q_PROPERTY(QString boardPort READ boardPort NOTIFY boardFound)
Q_PROPERTY(QString boardDescription READ boardDescription NOTIFY boardFound)
Q_PROPERTY(QString boardType MEMBER _foundBoardTypeName NOTIFY boardFound)
Q_PROPERTY(bool pixhawkBoard READ pixhawkBoard NOTIFY boardFound)
Q_PROPERTY(bool px4FlowBoard READ px4FlowBoard NOTIFY boardFound)
Q_PROPERTY(FirmwareBuildType_t selectedFirmwareBuildType READ selectedFirmwareBuildType WRITE setSelectedFirmwareBuildType NOTIFY selectedFirmwareBuildTypeChanged)
Q_PROPERTY(QStringList apmFirmwareNames MEMBER _apmFirmwareNames NOTIFY apmFirmwareNamesChanged)
Q_PROPERTY(QStringList apmFirmwareUrls MEMBER _apmFirmwareUrls NOTIFY apmFirmwareNamesChanged)
Q_PROPERTY(QString px4StableVersion READ px4StableVersion NOTIFY px4StableVersionChanged)
Q_PROPERTY(QString px4BetaVersion READ px4BetaVersion NOTIFY px4BetaVersionChanged)
/// TextArea for log output
Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
......@@ -119,13 +112,15 @@ public:
/// Called when the firmware type has been selected by the user to continue the flash process.
Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
FirmwareType_t firmwareType = StableFirmware,
FirmwareBuildType_t firmwareType = StableFirmware,
FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
Q_INVOKABLE void flashFirmwareUrl(QString firmwareUrl);
/// Called to flash when upgrade is running in singleFirmwareMode
Q_INVOKABLE void flashSingleFirmwareMode(FirmwareType_t firmwareType);
Q_INVOKABLE void flashSingleFirmwareMode(FirmwareBuildType_t firmwareType);
Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromVersionIndex(int index);
Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromFirmwareSelectionIndex(int index);
// overload, not exposed to qml side
void flash(const FirmwareIdentifier& firmwareId);
......@@ -141,28 +136,28 @@ public:
QString boardPort(void) { return _foundBoardInfo.portName(); }
QString boardDescription(void) { return _foundBoardInfo.description(); }
FirmwareType_t selectedFirmwareType(void) { return _selectedFirmwareType; }
void setSelectedFirmwareType(FirmwareType_t firmwareType);
QString firmwareTypeAsString(FirmwareType_t type) const;
FirmwareBuildType_t selectedFirmwareBuildType(void) { return _selectedFirmwareBuildType; }
void setSelectedFirmwareBuildType(FirmwareBuildType_t firmwareType);
QString firmwareTypeAsString(FirmwareBuildType_t type) const;
QStringList apmAvailableVersions(void);
QString px4StableVersion(void) { return _px4StableVersion; }
QString px4BetaVersion(void) { return _px4BetaVersion; }
QString px4StableVersion (void) { return _px4StableVersion; }
QString px4BetaVersion (void) { return _px4BetaVersion; }
bool pixhawkBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePixhawk; }
bool px4FlowBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePX4Flow; }
signals:
void boardFound(void);
void noBoardFound(void);
void boardGone(void);
void flashComplete(void);
void flashCancelled(void);
void error(void);
void selectedFirmwareTypeChanged(FirmwareType_t firmwareType);
void apmAvailableVersionsChanged(void);
void px4StableVersionChanged(const QString& px4StableVersion);
void px4BetaVersionChanged(const QString& px4BetaVersion);
void boardFound (void);
void noBoardFound (void);
void boardGone (void);
void flashComplete (void);
void flashCancelled (void);
void error (void);
void selectedFirmwareBuildTypeChanged(FirmwareBuildType_t firmwareType);
void apmFirmwareNamesChanged (void);
void px4StableVersionChanged (const QString& px4StableVersion);
void px4BetaVersionChanged (const QString& px4BetaVersion);
void downloadingFirmwareListChanged (bool downloadingFirmwareList);
private slots:
void _firmwareDownloadProgress(qint64 curr, qint64 total);
......@@ -180,22 +175,25 @@ private slots:
void _eraseStarted(void);
void _eraseComplete(void);
void _eraseProgressTick(void);
void _apmVersionDownloadFinished(QString remoteFile, QString localFile);
void _px4ReleasesGithubDownloadFinished(QString remoteFile, QString localFile);
void _px4ReleasesGithubDownloadError(QString errorMsg);
void _ardupilotManifestDownloadFinished(QString remoteFile, QString localFile);
void _ardupilotManifestDownloadError(QString errorMsg);
void _buildAPMFirmwareNames(void);
private:
void _getFirmwareFile(FirmwareIdentifier firmwareId);
void _initFirmwareHash();
void _downloadFirmware(void);
void _appendStatusLog(const QString& text, bool critical = false);
void _errorCancel(const QString& msg);
void _loadAPMVersions(uint32_t bootloaderBoardID);
QHash<FirmwareIdentifier, QString>* _firmwareHashForBoardId(int boardId);
void _determinePX4StableVersion(void);
void _getFirmwareFile(FirmwareIdentifier firmwareId);
void _initFirmwareHash (void);
void _downloadFirmware (void);
void _appendStatusLog (const QString& text, bool critical = false);
void _errorCancel (const QString& msg);
void _determinePX4StableVersion (void);
void _downloadArduPilotManifest (void);
QString _singleFirmwareURL;
bool _singleFirmwareMode;
bool _downloadingFirmwareList;
QString _portName;
QString _portDescription;
......@@ -220,7 +218,7 @@ private:
QHash<FirmwareIdentifier, QString> _rgAPMChibiosReplaceNamedBoardFirmware;
QHash<FirmwareIdentifier, QString> _rgFirmwareDynamic;
QMap<FirmwareType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
QMap<FirmwareBuildType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
QList<FirmwareVehicleType_t> _apmVehicleTypeFromCurrentVersionList;
/// Information which comes back from the bootloader
......@@ -259,7 +257,7 @@ private:
QGCSerialPortInfo::BoardType_t _foundBoardType;
QString _foundBoardTypeName;
FirmwareType_t _selectedFirmwareType;
FirmwareBuildType_t _selectedFirmwareBuildType;
FirmwareImage* _image;
......@@ -267,9 +265,46 @@ private:
QString _px4BetaVersion; // Version strange for latest PX4 beta
const QString _apmBoardDescriptionReplaceText;
static const char* _manifestFirmwareJsonKey;
static const char* _manifestBoardIdJsonKey;
static const char* _manifestMavTypeJsonKey;
static const char* _manifestFormatJsonKey;
static const char* _manifestUrlJsonKey;
static const char* _manifestMavFirmwareVersionTypeJsonKey;
static const char* _manifestUSBIDJsonKey;
static const char* _manifestMavFirmwareVersionJsonKey;
static const char* _manifestBootloaderStrJsonKey;
static const char* _manifestLatestKey;
static const char* _manifestPlatformKey;
static const char* _manifestBrandNameKey;
typedef struct {
uint32_t boardId;
FirmwareBuildType_t firmwareBuildType;
FirmwareVehicleType_t vehicleType;
QString url;
QString version;
QStringList rgBootloaderPortString;
QList<int> rgVID;
QList<int> rgPID;
QString friendlyName;
bool chibios;
bool fmuv2;
} ManifestFirmwareInfo_t;
QList<ManifestFirmwareInfo_t> _rgManifestFirmwareInfo;
QMap<QString, FirmwareBuildType_t> _manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap;
QMap<QString, FirmwareVehicleType_t> _manifestMavTypeToFirmwareVehicleTypeMap;
QStringList _apmFirmwareNames;
QStringList _apmFirmwareUrls;
Fact* _apmChibiOSSetting;
Fact* _apmVehicleTypeSetting;
FirmwareBuildType_t _manifestMavFirmwareVersionTypeToFirmwareBuildType (const QString& manifestMavFirmwareVersionType);
FirmwareVehicleType_t _manifestMavTypeToFirmwareVehicleType (const QString& manifestMavType);
};
// global hashing function
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);
#endif
......@@ -712,17 +712,18 @@ VideoReceiver::startRecording(const QString &videoFile)
gst_object_ref(_sink->mux);
gst_object_ref(_sink->filesink);
gst_bin_add_many(GST_BIN(_pipeline), _sink->queue, _sink->parse, _sink->mux, _sink->filesink, nullptr);
gst_element_link_many(_sink->queue, _sink->parse, _sink->mux, _sink->filesink, nullptr);
gst_bin_add_many(GST_BIN(_pipeline), _sink->queue, _sink->parse, _sink->mux, nullptr);
gst_element_link_many(_sink->queue, _sink->parse, _sink->mux, nullptr);
gst_element_sync_state_with_parent(_sink->queue);
gst_element_sync_state_with_parent(_sink->parse);
gst_element_sync_state_with_parent(_sink->mux);
gst_element_sync_state_with_parent(_sink->filesink);
// Install a probe on the recording branch to drop buffers until we hit our first keyframe
// When we hit our first keyframe, we can offset the timestamps appropriately according to the first keyframe time
// This will ensure the first frame is a keyframe at t=0, and decoding can begin immediately on playback
// Once we have this valid frame, we attach the filesink.
// Attaching it here would cause the filesink to fail to preroll and to stall the pipeline for a few seconds.
GstPad* probepad = gst_element_get_static_pad(_sink->queue, "src");
gst_pad_add_probe(probepad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER /* | GST_PAD_PROBE_TYPE_BLOCK */), _keyframeWatch, this, nullptr); // to drop the buffer or to block the buffer?
gst_object_unref(probepad);
......@@ -875,6 +876,12 @@ VideoReceiver::_keyframeWatch(GstPad* pad, GstPadProbeInfo* info, gpointer user_
gst_element_set_base_time(pThis->_pipeline, time); // offset pipeline timestamps to start at zero again
buf->dts = 0; // The offset will not apply to this current buffer, our first frame, timestamp is zero
buf->pts = 0;
// Add the filesink once we have a valid I-frame
gst_bin_add_many(GST_BIN(pThis->_pipeline), pThis->_sink->filesink, nullptr);
gst_element_link_many(pThis->_sink->mux, pThis->_sink->filesink, nullptr);
gst_element_sync_state_with_parent(pThis->_sink->filesink);
qCDebug(VideoReceiverLog) << "Got keyframe, stop dropping buffers";
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment