diff --git a/src/Vehicle/CompInfo.h b/src/Vehicle/CompInfo.h
index 2f22b2e..bcfffd6 100644
--- a/src/Vehicle/CompInfo.h
+++ b/src/Vehicle/CompInfo.h
@@ -29,10 +29,13 @@ public:
     CompInfo(COMP_METADATA_TYPE type, uint8_t compId, Vehicle* vehicle, QObject* parent = nullptr);
 
     const QString& uriMetaData() const { return _uris.uriMetaData; }
+    const QString& uriMetaDataFallback() const { return _uris.uriMetaDataFallback; }
     const QString& uriTranslation() const { return _uris.uriTranslation; }
 
     uint32_t crcMetaData() const { return _uris.crcMetaData; }
+    uint32_t crcMetaDataFallback() const { return _uris.crcMetaDataFallback; }
     bool crcMetaDataValid() const { return _uris.crcMetaDataValid; }
+    bool crcMetaDataFallbackValid() const { return _uris.crcMetaDataFallbackValid; }
     uint32_t crcTranslation() const { return _uris.crcTranslation; }
     bool crcTranslationValid() const { return _uris.crcTranslationValid; }
 
diff --git a/src/Vehicle/ComponentInformationManager.cc b/src/Vehicle/ComponentInformationManager.cc
index 62868ee..39c3732 100644
--- a/src/Vehicle/ComponentInformationManager.cc
+++ b/src/Vehicle/ComponentInformationManager.cc
@@ -37,6 +37,7 @@ int ComponentInformationManager::_cStates = sizeof(ComponentInformationManager::
 RequestMetaDataTypeStateMachine::StateFn RequestMetaDataTypeStateMachine::_rgStates[]= {
     RequestMetaDataTypeStateMachine::_stateRequestCompInfo,
     RequestMetaDataTypeStateMachine::_stateRequestMetaDataJson,
+    RequestMetaDataTypeStateMachine::_stateRequestMetaDataJsonFallback,
     RequestMetaDataTypeStateMachine::_stateRequestTranslationJson,
     RequestMetaDataTypeStateMachine::_stateRequestComplete,
 };
@@ -264,6 +265,7 @@ void RequestMetaDataTypeStateMachine::_ftpDownloadComplete(const QString& fileNa
     qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_ftpDownloadComplete fileName:errorMsg" << fileName << errorMsg;
 
     disconnect(_compInfo->vehicle->ftpManager(), &FTPManager::downloadComplete, this, &RequestMetaDataTypeStateMachine::_ftpDownloadComplete);
+    disconnect(_compInfo->vehicle->ftpManager(), &FTPManager::commandProgress, this, &RequestMetaDataTypeStateMachine::_ftpDownloadProgress);
     if (errorMsg.isEmpty()) {
         if (_currentFileName) {
             *_currentFileName = _downloadCompleteJsonWorker(fileName);
@@ -271,11 +273,24 @@ void RequestMetaDataTypeStateMachine::_ftpDownloadComplete(const QString& fileNa
     } else if (qgcApp()->runningUnitTests()) {
         // Unit test should always succeed
         qCWarning(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_ftpDownloadComplete failed filename:errorMsg" << fileName << errorMsg;
-    } // TODO: else: try fallback uri
+    }
 
     advance();
 }
 
+void RequestMetaDataTypeStateMachine::_ftpDownloadProgress(float progress)
+{
+    int elapsedSec = _downloadStartTime.elapsed() / 1000;
+    float totalDownloadTime = elapsedSec / progress;
+    // abort download if it's too slow (e.g. over telemetry link) and use the fallback.
+    // (we could also check if there's a http fallback)
+    const int maxDownloadTimeSec = 40;
+    if (elapsedSec > 10 && progress < 0.5 && totalDownloadTime > maxDownloadTimeSec) {
+        qCDebug(ComponentInformationManagerLog) << "Slow download, aborting. Total time (s):" << totalDownloadTime;
+        _compInfo->vehicle->ftpManager()->cancel();
+    }
+}
+
 void RequestMetaDataTypeStateMachine::_httpDownloadComplete(QString remoteFile, QString localFile, QString errorMsg)
 {
     qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_httpDownloadComplete remoteFile:localFile:errorMsg" << remoteFile << localFile << errorMsg;
@@ -288,7 +303,7 @@ void RequestMetaDataTypeStateMachine::_httpDownloadComplete(QString remoteFile,
     } else if (qgcApp()->runningUnitTests()) {
         // Unit test should always succeed
         qCWarning(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_httpDownloadCompleteMetaDataJson failed remoteFile:localFile:errorMsg" << remoteFile << localFile << errorMsg;
-    } // TODO: else: try fallback uri
+    }
 
     advance();
 }
@@ -299,6 +314,7 @@ void RequestMetaDataTypeStateMachine::_requestFile(const QString& cacheFileTag,
     _currentCacheFileTag = cacheFileTag;
     _currentFileName = &outputFileName;
     _currentFileValidCrc = crcValid;
+    outputFileName.clear();
 
     if (_compInfo->available() && !uri.isEmpty()) {
         const QString cachedFile = crcValid ? _compMgr->fileCache().access(cacheFileTag) : "";
@@ -307,19 +323,22 @@ void RequestMetaDataTypeStateMachine::_requestFile(const QString& cacheFileTag,
             qCDebug(ComponentInformationManagerLog) << "Downloading json" << uri;
             if (_uriIsMAVLinkFTP(uri)) {
                 connect(ftpManager, &FTPManager::downloadComplete, this, &RequestMetaDataTypeStateMachine::_ftpDownloadComplete);
-                if (!ftpManager->download(uri, QStandardPaths::writableLocation(QStandardPaths::TempLocation))) {
+                if (ftpManager->download(uri, QStandardPaths::writableLocation(QStandardPaths::TempLocation))) {
+                    _downloadStartTime.start();
+                    connect(ftpManager, &FTPManager::commandProgress, this, &RequestMetaDataTypeStateMachine::_ftpDownloadProgress);
+                } else {
                     qCWarning(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_requestFile FTPManager::download returned failure";
                     disconnect(ftpManager, &FTPManager::downloadComplete, this, &RequestMetaDataTypeStateMachine::_ftpDownloadComplete);
-                    // TODO: try fallback uri
                     advance();
                 }
             } else {
                 QGCFileDownload* download = new QGCFileDownload(this);
                 connect(download, &QGCFileDownload::downloadComplete, this, &RequestMetaDataTypeStateMachine::_httpDownloadComplete);
-                if (!download->download(uri)) {
+                if (download->download(uri)) {
+                    _downloadStartTime.start();
+                } else {
                     qCWarning(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_requestFile QGCFileDownload::download returned failure";
                     disconnect(download, &QGCFileDownload::downloadComplete, this, &RequestMetaDataTypeStateMachine::_httpDownloadComplete);
-                    // TODO: try fallback uri
                     advance();
                 }
             }
@@ -346,6 +365,23 @@ void RequestMetaDataTypeStateMachine::_stateRequestMetaDataJson(StateMachine* st
     requestMachine->_requestFile(fileTag, compInfo->crcMetaDataValid(), uri, requestMachine->_jsonMetadataFileName);
 }
 
+void RequestMetaDataTypeStateMachine::_stateRequestMetaDataJsonFallback(StateMachine* stateMachine)
+{
+    RequestMetaDataTypeStateMachine*    requestMachine  = static_cast<RequestMetaDataTypeStateMachine*>(stateMachine);
+    if (!requestMachine->_jsonMetadataFileName.isEmpty()) {
+        requestMachine->advance();
+        return;
+    }
+    qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_stateRequestMetaDataJsonFallback: trying fallback download";
+
+    CompInfo*                           compInfo        = requestMachine->compInfo();
+    const QString                       fileTag         = ComponentInformationManager::_getFileCacheTag(
+            compInfo->type, compInfo->crcMetaDataFallback(), false);
+    const QString                       uri             = compInfo->uriMetaDataFallback();
+    requestMachine->_jsonMetadataCrcValid               = compInfo->crcMetaDataFallbackValid();
+    requestMachine->_requestFile(fileTag, compInfo->crcMetaDataFallbackValid(), uri, requestMachine->_jsonMetadataFileName);
+}
+
 void RequestMetaDataTypeStateMachine::_stateRequestTranslationJson(StateMachine* stateMachine)
 {
     RequestMetaDataTypeStateMachine*    requestMachine  = static_cast<RequestMetaDataTypeStateMachine*>(stateMachine);
diff --git a/src/Vehicle/ComponentInformationManager.h b/src/Vehicle/ComponentInformationManager.h
index ac14c99..1c7c8c3 100644
--- a/src/Vehicle/ComponentInformationManager.h
+++ b/src/Vehicle/ComponentInformationManager.h
@@ -14,6 +14,8 @@
 #include "StateMachine.h"
 #include "ComponentInformationCache.h"
 
+#include <QTime>
+
 Q_DECLARE_LOGGING_CATEGORY(ComponentInformationManagerLog)
 
 class Vehicle;
@@ -40,12 +42,14 @@ public:
 
 private slots:
     void    _ftpDownloadComplete                (const QString& file, const QString& errorMsg);
+    void    _ftpDownloadProgress                (float progress);
     void    _httpDownloadComplete               (QString remoteFile, QString localFile, QString errorMsg);
     QString _downloadCompleteJsonWorker         (const QString& jsonFileName);
 
 private:
     static void _stateRequestCompInfo           (StateMachine* stateMachine);
     static void _stateRequestMetaDataJson       (StateMachine* stateMachine);
+    static void _stateRequestMetaDataJsonFallback(StateMachine* stateMachine);
     static void _stateRequestTranslationJson    (StateMachine* stateMachine);
     static void _stateRequestComplete           (StateMachine* stateMachine);
     static bool _uriIsMAVLinkFTP                (const QString& uri);
@@ -63,6 +67,8 @@ private:
     QString                         _currentCacheFileTag;
     bool                            _currentFileValidCrc        = false;
 
+    QTime                           _downloadStartTime;
+
     static StateFn  _rgStates[];
     static int      _cStates;
 };